perl5/libwww/lwptut.pod000044400000060566152462503210011164 0ustar00=head1 NAME lwptut -- An LWP Tutorial =head1 DESCRIPTION LWP (short for "Library for WWW in Perl") is a very popular group of Perl modules for accessing data on the Web. Like most Perl module-distributions, each of LWP's component modules comes with documentation that is a complete reference to its interface. However, there are so many modules in LWP that it's hard to know where to start looking for information on how to do even the simplest most common things. Really introducing you to using LWP would require a whole book -- a book that just happens to exist, called I. But this article should give you a taste of how you can go about some common tasks with LWP. =head2 Getting documents with LWP::Simple If you just want to get what's at a particular URL, the simplest way to do it is LWP::Simple's functions. In a Perl program, you can call its C function. It will try getting that URL's content. If it works, then it'll return the content; but if there's some error, it'll return undef. my $url = 'http://www.npr.org/programs/fa/?todayDate=current'; # Just an example: the URL for the most recent /Fresh Air/ show use LWP::Simple; my $content = get $url; die "Couldn't get $url" unless defined $content; # Then go do things with $content, like this: if($content =~ m/jazz/i) { print "They're talking about jazz today on Fresh Air!\n"; } else { print "Fresh Air is apparently jazzless today.\n"; } The handiest variant on C is C, which is useful in Perl one-liners. If it can get the page whose URL you provide, it sends it to STDOUT; otherwise it complains to STDERR. % perl -MLWP::Simple -e "getprint 'http://www.cpan.org/RECENT'" That is the URL of a plain text file that lists new files in CPAN in the past two weeks. You can easily make it part of a tidy little shell command, like this one that mails you the list of new C modules: % perl -MLWP::Simple -e "getprint 'http://www.cpan.org/RECENT'" \ | grep "/by-module/Acme" | mail -s "New Acme modules! Joy!" $USER There are other useful functions in LWP::Simple, including one function for running a HEAD request on a URL (useful for checking links, or getting the last-revised time of a URL), and two functions for saving/mirroring a URL to a local file. See L for the full details, or chapter 2 of I for more examples. =for comment ########################################################################## =head2 The Basics of the LWP Class Model LWP::Simple's functions are handy for simple cases, but its functions don't support cookies or authorization, don't support setting header lines in the HTTP request, generally don't support reading header lines in the HTTP response (notably the full HTTP error message, in case of an error). To get at all those features, you'll have to use the full LWP class model. While LWP consists of dozens of classes, the main two that you have to understand are L and L. LWP::UserAgent is a class for "virtual browsers" which you use for performing requests, and L is a class for the responses (or error messages) that you get back from those requests. The basic idiom is C<< $response = $browser->get($url) >>, or more fully illustrated: # Early in your program: use LWP 5.64; # Loads all important LWP classes, and makes # sure your version is reasonably recent. my $browser = LWP::UserAgent->new; ... # Then later, whenever you need to make a get request: my $url = 'http://www.npr.org/programs/fa/?todayDate=current'; my $response = $browser->get( $url ); die "Can't get $url -- ", $response->status_line unless $response->is_success; die "Hey, I was expecting HTML, not ", $response->content_type unless $response->content_type eq 'text/html'; # or whatever content-type you're equipped to deal with # Otherwise, process the content somehow: if($response->decoded_content =~ m/jazz/i) { print "They're talking about jazz today on Fresh Air!\n"; } else { print "Fresh Air is apparently jazzless today.\n"; } There are two objects involved: C<$browser>, which holds an object of class LWP::UserAgent, and then the C<$response> object, which is of class HTTP::Response. You really need only one browser object per program; but every time you make a request, you get back a new HTTP::Response object, which will have some interesting attributes: =over =item * A status code indicating success or failure (which you can test with C<< $response->is_success >>). =item * An HTTP status line that is hopefully informative if there's failure (which you can see with C<< $response->status_line >>, returning something like "404 Not Found"). =item * A MIME content-type like "text/html", "image/gif", "application/xml", etc., which you can see with C<< $response->content_type >> =item * The actual content of the response, in C<< $response->decoded_content >>. If the response is HTML, that's where the HTML source will be; if it's a GIF, then C<< $response->decoded_content >> will be the binary GIF data. =item * And dozens of other convenient and more specific methods that are documented in the docs for L, and its superclasses L and L. =back =for comment ########################################################################## =head2 Adding Other HTTP Request Headers The most commonly used syntax for requests is C<< $response = $browser->get($url) >>, but in truth, you can add extra HTTP header lines to the request by adding a list of key-value pairs after the URL, like so: $response = $browser->get( $url, $key1, $value1, $key2, $value2, ... ); For example, here's how to send some commonly used headers, in case you're dealing with a site that would otherwise reject your request: my @ns_headers = ( 'User-Agent' => 'Mozilla/4.76 [en] (Win98; U)', 'Accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*', 'Accept-Charset' => 'iso-8859-1,*,utf-8', 'Accept-Language' => 'en-US', ); ... $response = $browser->get($url, @ns_headers); If you weren't reusing that array, you could just go ahead and do this: $response = $browser->get($url, 'User-Agent' => 'Mozilla/4.76 [en] (Win98; U)', 'Accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*', 'Accept-Charset' => 'iso-8859-1,*,utf-8', 'Accept-Language' => 'en-US', ); If you were only ever changing the 'User-Agent' line, you could just change the C<$browser> object's default line from "libwww-perl/5.65" (or the like) to whatever you like, using the LWP::UserAgent C method: $browser->agent('Mozilla/4.76 [en] (Win98; U)'); =for comment ########################################################################## =head2 Enabling Cookies A default LWP::UserAgent object acts like a browser with its cookies support turned off. There are various ways of turning it on, by setting its C attribute. A "cookie jar" is an object representing a little database of all the HTTP cookies that a browser knows about. It can correspond to a file on disk or an in-memory object that starts out empty, and whose collection of cookies will disappear once the program is finished running. To give a browser an in-memory empty cookie jar, you set its C attribute like so: use HTTP::CookieJar::LWP; $browser->cookie_jar( HTTP::CookieJar::LWP->new ); To save a cookie jar to disk, see L<< HTTP::CookieJar/dump_cookies >>. To load cookies from disk into a jar, see L<< HTTP::CookieJar/load_cookies >>. =for comment ########################################################################## =head2 Posting Form Data Many HTML forms send data to their server using an HTTP POST request, which you can send with this syntax: $response = $browser->post( $url, [ formkey1 => value1, formkey2 => value2, ... ], ); Or if you need to send HTTP headers: $response = $browser->post( $url, [ formkey1 => value1, formkey2 => value2, ... ], headerkey1 => value1, headerkey2 => value2, ); For example, the following program makes a search request to AltaVista (by sending some form data via an HTTP POST request), and extracts from the HTML the report of the number of matches: use strict; use warnings; use LWP 5.64; my $browser = LWP::UserAgent->new; my $word = 'tarragon'; my $url = 'http://search.yahoo.com/yhs/search'; my $response = $browser->post( $url, [ 'q' => $word, # the Altavista query string 'fr' => 'altavista', 'pg' => 'q', 'avkw' => 'tgz', 'kl' => 'XX', ] ); die "$url error: ", $response->status_line unless $response->is_success; die "Weird content type at $url -- ", $response->content_type unless $response->content_is_html; if( $response->decoded_content =~ m{([0-9,]+)(?:<.*?>)? results for} ) { # The substring will be like "996,000 results for" print "$word: $1\n"; } else { print "Couldn't find the match-string in the response\n"; } =for comment ########################################################################## =head2 Sending GET Form Data Some HTML forms convey their form data not by sending the data in an HTTP POST request, but by making a normal GET request with the data stuck on the end of the URL. For example, if you went to C and ran a search on "Blade Runner", the URL you'd see in your browser window would be: http://www.imdb.com/find?s=all&q=Blade+Runner To run the same search with LWP, you'd use this idiom, which involves the URI class: use URI; my $url = URI->new( 'http://www.imdb.com/find' ); # makes an object representing the URL $url->query_form( # And here the form data pairs: 'q' => 'Blade Runner', 's' => 'all', ); my $response = $browser->get($url); See chapter 5 of I for a longer discussion of HTML forms and of form data, and chapters 6 through 9 for a longer discussion of extracting data from HTML. =head2 Absolutizing URLs The URI class that we just mentioned above provides all sorts of methods for accessing and modifying parts of URLs (such as asking sort of URL it is with C<< $url->scheme >>, and asking what host it refers to with C<< $url->host >>, and so on, as described in L. However, the methods of most immediate interest are the C method seen above, and now the C method for taking a probably-relative URL string (like "../foo.html") and getting back an absolute URL (like "http://www.perl.com/stuff/foo.html"), as shown here: use URI; $abs = URI->new_abs($maybe_relative, $base); For example, consider this program that matches URLs in the HTML list of new modules in CPAN: use strict; use warnings; use LWP; my $browser = LWP::UserAgent->new; my $url = 'http://www.cpan.org/RECENT.html'; my $response = $browser->get($url); die "Can't get $url -- ", $response->status_line unless $response->is_success; my $html = $response->decoded_content; while( $html =~ m/ method, by changing the C loop to this: while( $html =~ m/new_abs( $1, $response->base ) ,"\n"; } (The C<< $response->base >> method from L is for returning what URL should be used for resolving relative URLs -- it's usually just the same as the URL that you requested.) That program then emits nicely absolute URLs: http://www.cpan.org/MIRRORING.FROM http://www.cpan.org/RECENT http://www.cpan.org/RECENT.html http://www.cpan.org/authors/00whois.html http://www.cpan.org/authors/01mailrc.txt.gz http://www.cpan.org/authors/id/A/AA/AASSAD/CHECKSUMS ... See chapter 4 of I for a longer discussion of URI objects. Of course, using a regexp to match hrefs is a bit simplistic, and for more robust programs, you'll probably want to use an HTML-parsing module like L or L or even maybe L. =for comment ########################################################################## =head2 Other Browser Attributes LWP::UserAgent objects have many attributes for controlling how they work. Here are a few notable ones: =over =item * C<< $browser->timeout(15); >> This sets this browser object to give up on requests that don't answer within 15 seconds. =item * C<< $browser->protocols_allowed( [ 'http', 'gopher'] ); >> This sets this browser object to not speak any protocols other than HTTP and gopher. If it tries accessing any other kind of URL (like an "ftp:" or "mailto:" or "news:" URL), then it won't actually try connecting, but instead will immediately return an error code 500, with a message like "Access to 'ftp' URIs has been disabled". =item * C<< use LWP::ConnCache; $browser->conn_cache(LWP::ConnCache->new()); >> This tells the browser object to try using the HTTP/1.1 "Keep-Alive" feature, which speeds up requests by reusing the same socket connection for multiple requests to the same server. =item * C<< $browser->agent( 'SomeName/1.23 (more info here maybe)' ) >> This changes how the browser object will identify itself in the default "User-Agent" line is its HTTP requests. By default, it'll send "libwww-perl/I", like "libwww-perl/5.65". You can change that to something more descriptive like this: $browser->agent( 'SomeName/3.14 (contact@robotplexus.int)' ); Or if need be, you can go in disguise, like this: $browser->agent( 'Mozilla/4.0 (compatible; MSIE 5.12; Mac_PowerPC)' ); =item * C<< push @{ $ua->requests_redirectable }, 'POST'; >> This tells this browser to obey redirection responses to POST requests (like most modern interactive browsers), even though the HTTP RFC says that should not normally be done. =back For more options and information, see L. =for comment ########################################################################## =head2 Writing Polite Robots If you want to make sure that your LWP-based program respects F files and doesn't make too many requests too fast, you can use the LWP::RobotUA class instead of the LWP::UserAgent class. LWP::RobotUA class is just like LWP::UserAgent, and you can use it like so: use LWP::RobotUA; my $browser = LWP::RobotUA->new('YourSuperBot/1.34', 'you@yoursite.com'); # Your bot's name and your email address my $response = $browser->get($url); But HTTP::RobotUA adds these features: =over =item * If the F on C<$url>'s server forbids you from accessing C<$url>, then the C<$browser> object (assuming it's of class LWP::RobotUA) won't actually request it, but instead will give you back (in C<$response>) a 403 error with a message "Forbidden by robots.txt". That is, if you have this line: die "$url -- ", $response->status_line, "\nAborted" unless $response->is_success; then the program would die with an error message like this: http://whatever.site.int/pith/x.html -- 403 Forbidden by robots.txt Aborted at whateverprogram.pl line 1234 =item * If this C<$browser> object sees that the last time it talked to C<$url>'s server was too recently, then it will pause (via C) to avoid making too many requests too often. How long it will pause for, is by default one minute -- but you can control it with the C<< $browser->delay( I ) >> attribute. For example, this code: $browser->delay( 7/60 ); ...means that this browser will pause when it needs to avoid talking to any given server more than once every 7 seconds. =back For more options and information, see L. =for comment ########################################################################## =head2 Using Proxies In some cases, you will want to (or will have to) use proxies for accessing certain sites and/or using certain protocols. This is most commonly the case when your LWP program is running (or could be running) on a machine that is behind a firewall. To make a browser object use proxies that are defined in the usual environment variables (C, etc.), just call the C on a user-agent object before you go making any requests on it. Specifically: use LWP::UserAgent; my $browser = LWP::UserAgent->new; # And before you go making any requests: $browser->env_proxy; For more information on proxy parameters, see L, specifically the C, C, and C methods. =for comment ########################################################################## =head2 HTTP Authentication Many web sites restrict access to documents by using "HTTP Authentication". This isn't just any form of "enter your password" restriction, but is a specific mechanism where the HTTP server sends the browser an HTTP code that says "That document is part of a protected 'realm', and you can access it only if you re-request it and add some special authorization headers to your request". For example, the Unicode.org admins stop email-harvesting bots from harvesting the contents of their mailing list archives, by protecting them with HTTP Authentication, and then publicly stating the username and password (at C) -- namely username "unicode-ml" and password "unicode". For example, consider this URL, which is part of the protected area of the web site: http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html If you access that with a browser, you'll get a prompt like "Enter username and password for 'Unicode-MailList-Archives' at server 'www.unicode.org'". In LWP, if you just request that URL, like this: use LWP; my $browser = LWP::UserAgent->new; my $url = 'http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html'; my $response = $browser->get($url); die "Error: ", $response->header('WWW-Authenticate') || 'Error accessing', # ('WWW-Authenticate' is the realm-name) "\n ", $response->status_line, "\n at $url\n Aborting" unless $response->is_success; Then you'll get this error: Error: Basic realm="Unicode-MailList-Archives" 401 Authorization Required at http://www.unicode.org/mail-arch/unicode-ml/y2002-m08/0067.html Aborting at auth1.pl line 9. [or wherever] ...because the C<$browser> doesn't know any the username and password for that realm ("Unicode-MailList-Archives") at that host ("www.unicode.org"). The simplest way to let the browser know about this is to use the C method to let it know about a username and password that it can try using for that realm at that host. The syntax is: $browser->credentials( 'servername:portnumber', 'realm-name', 'username' => 'password' ); In most cases, the port number is 80, the default TCP/IP port for HTTP; and you usually call the C method before you make any requests. For example: $browser->credentials( 'reports.mybazouki.com:80', 'web_server_usage_reports', 'plinky' => 'banjo123' ); So if we add the following to the program above, right after the C<< $browser = LWP::UserAgent->new; >> line... $browser->credentials( # add this to our $browser 's "key ring" 'www.unicode.org:80', 'Unicode-MailList-Archives', 'unicode-ml' => 'unicode' ); ...then when we run it, the request succeeds, instead of causing the C to be called. =for comment ########################################################################## =head2 Accessing HTTPS URLs When you access an HTTPS URL, it'll work for you just like an HTTP URL would -- if your LWP installation has HTTPS support (via an appropriate Secure Sockets Layer library). For example: use LWP; my $url = 'https://www.paypal.com/'; # Yes, HTTPS! my $browser = LWP::UserAgent->new; my $response = $browser->get($url); die "Error at $url\n ", $response->status_line, "\n Aborting" unless $response->is_success; print "Whee, it worked! I got that ", $response->content_type, " document!\n"; If your LWP installation doesn't have HTTPS support set up, then the response will be unsuccessful, and you'll get this error message: Error at https://www.paypal.com/ 501 Protocol scheme 'https' is not supported Aborting at paypal.pl line 7. [or whatever program and line] If your LWP installation I have HTTPS support installed, then the response should be successful, and you should be able to consult C<$response> just like with any normal HTTP response. For information about installing HTTPS support for your LWP installation, see the helpful F file that comes in the libwww-perl distribution. =for comment ########################################################################## =head2 Getting Large Documents When you're requesting a large (or at least potentially large) document, a problem with the normal way of using the request methods (like C<< $response = $browser->get($url) >>) is that the response object in memory will have to hold the whole document -- I. If the response is a thirty megabyte file, this is likely to be quite an imposition on this process's memory usage. A notable alternative is to have LWP save the content to a file on disk, instead of saving it up in memory. This is the syntax to use: $response = $ua->get($url, ':content_file' => $filespec, ); For example, $response = $ua->get('http://search.cpan.org/', ':content_file' => '/tmp/sco.html' ); When you use this C<:content_file> option, the C<$response> will have all the normal header lines, but C<< $response->content >> will be empty. Errors writing to the content file (for example due to permission denied or the filesystem being full) will be reported via the C or C response headers, and not the C method: if ($response->header('Client-Aborted') eq 'die') { # handle error ... Note that this ":content_file" option isn't supported under older versions of LWP, so you should consider adding C to check the LWP version, if you think your program might run on systems with older versions. If you need to be compatible with older LWP versions, then use this syntax, which does the same thing: use HTTP::Request::Common; $response = $ua->request( GET($url), $filespec ); =for comment ########################################################################## =head1 SEE ALSO Remember, this article is just the most rudimentary introduction to LWP -- to learn more about LWP and LWP-related tasks, you really must read from the following: =over =item * L -- simple functions for getting/heading/mirroring URLs =item * L -- overview of the libwww-perl modules =item * L -- the class for objects that represent "virtual browsers" =item * L -- the class for objects that represent the response to a LWP response, as in C<< $response = $browser->get(...) >> =item * L and L -- classes that provide more methods to HTTP::Response. =item * L -- class for objects that represent absolute or relative URLs =item * L -- functions for URL-escaping and URL-unescaping strings (like turning "this & that" to and from "this%20%26%20that"). =item * L -- functions for HTML-escaping and HTML-unescaping strings (like turning "C. & E. BrontE" to and from "C. & E. Brontë") =item * L and L -- classes for parsing HTML =item * L -- class for finding links in HTML documents =item * The book I by Sean M. Burke. O'Reilly & Associates, 2002. ISBN: 0-596-00178-9, L. The whole book is also available free online: L. =back =head1 COPYRIGHT Copyright 2002, Sean M. Burke. You can redistribute this document and/or modify it, but only under the same terms as Perl itself. =head1 AUTHOR Sean M. Burke C =for comment ########################################################################## =cut # End of Pod perl5/libwww/lwpcook.pod000044400000022061152462503210011267 0ustar00=head1 NAME lwpcook - The libwww-perl cookbook =head1 DESCRIPTION This document contain some examples that show typical usage of the libwww-perl library. You should consult the documentation for the individual modules for more detail. All examples should be runnable programs. You can, in most cases, test the code sections by piping the program text directly to perl. =head1 GET It is very easy to use this library to just fetch documents from the net. The LWP::Simple module provides the get() function that return the document specified by its URL argument: use LWP::Simple; $doc = get 'http://search.cpan.org/dist/libwww-perl/'; or, as a perl one-liner using the getprint() function: perl -MLWP::Simple -e 'getprint "http://search.cpan.org/dist/libwww-perl/"' or, how about fetching the latest perl by running this command: perl -MLWP::Simple -e ' getstore "ftp://ftp.sunet.se/pub/lang/perl/CPAN/src/latest.tar.gz", "perl.tar.gz"' You will probably first want to find a CPAN site closer to you by running something like the following command: perl -MLWP::Simple -e 'getprint "http://www.cpan.org/SITES.html"' Enough of this simple stuff! The LWP object oriented interface gives you more control over the request sent to the server. Using this interface you have full control over headers sent and how you want to handle the response returned. use LWP::UserAgent; $ua = LWP::UserAgent->new; $ua->agent("$0/0.1 " . $ua->agent); # $ua->agent("Mozilla/8.0") # pretend we are very capable browser $req = HTTP::Request->new( GET => 'http://search.cpan.org/dist/libwww-perl/'); $req->header('Accept' => 'text/html'); # send request $res = $ua->request($req); # check the outcome if ($res->is_success) { print $res->decoded_content; } else { print "Error: " . $res->status_line . "\n"; } The lwp-request program (alias GET) that is distributed with the library can also be used to fetch documents from WWW servers. =head1 HEAD If you just want to check if a document is present (i.e. the URL is valid) try to run code that looks like this: use LWP::Simple; if (head($url)) { # ok document exists } The head() function really returns a list of meta-information about the document. The first three values of the list returned are the document type, the size of the document, and the age of the document. More control over the request or access to all header values returned require that you use the object oriented interface described for GET above. Just s/GET/HEAD/g. =head1 POST There is no simple procedural interface for posting data to a WWW server. You must use the object oriented interface for this. The most common POST operation is to access a WWW form application: use LWP::UserAgent; $ua = LWP::UserAgent->new; my $req = HTTP::Request->new( POST => 'https://rt.cpan.org/Public/Dist/Display.html'); $req->content_type('application/x-www-form-urlencoded'); $req->content('Status=Active&Name=libwww-perl'); my $res = $ua->request($req); print $res->as_string; Lazy people use the HTTP::Request::Common module to set up a suitable POST request message (it handles all the escaping issues) and has a suitable default for the content_type: use HTTP::Request::Common qw(POST); use LWP::UserAgent; $ua = LWP::UserAgent->new; my $req = POST 'https://rt.cpan.org/Public/Dist/Display.html', [ Status => 'Active', Name => 'libwww-perl' ]; print $ua->request($req)->as_string; The lwp-request program (alias POST) that is distributed with the library can also be used for posting data. =head1 PROXIES Some sites use proxies to go through fire wall machines, or just as cache in order to improve performance. Proxies can also be used for accessing resources through protocols not supported directly (or supported badly :-) by the libwww-perl library. You should initialize your proxy setting before you start sending requests: use LWP::UserAgent; $ua = LWP::UserAgent->new; $ua->env_proxy; # initialize from environment variables # or $ua->proxy(ftp => 'http://proxy.myorg.com'); $ua->proxy(wais => 'http://proxy.myorg.com'); $ua->no_proxy(qw(no se fi)); my $req = HTTP::Request->new(GET => 'wais://xxx.com/'); print $ua->request($req)->as_string; The LWP::Simple interface will call env_proxy() for you automatically. Applications that use the $ua->env_proxy() method will normally not use the $ua->proxy() and $ua->no_proxy() methods. Some proxies also require that you send it a username/password in order to let requests through. You should be able to add the required header, with something like this: use LWP::UserAgent; $ua = LWP::UserAgent->new; $ua->proxy(['http', 'ftp'] => 'http://username:password@proxy.myorg.com'); $req = HTTP::Request->new('GET',"http://www.perl.com"); $res = $ua->request($req); print $res->decoded_content if $res->is_success; Replace C, C and C with something suitable for your site. =head1 ACCESS TO PROTECTED DOCUMENTS Documents protected by basic authorization can easily be accessed like this: use LWP::UserAgent; $ua = LWP::UserAgent->new; $req = HTTP::Request->new(GET => 'http://www.linpro.no/secret/'); $req->authorization_basic('aas', 'mypassword'); print $ua->request($req)->as_string; The other alternative is to provide a subclass of I that overrides the get_basic_credentials() method. Study the I program for an example of this. =head1 COOKIES Some sites like to play games with cookies. By default LWP ignores cookies provided by the servers it visits. LWP will collect cookies and respond to cookie requests if you set up a cookie jar. LWP doesn't provide a cookie jar itself, but if you install L, it can be used like this: use LWP::UserAgent; use HTTP::CookieJar::LWP; $ua = LWP::UserAgent->new( cookie_jar => HTTP::CookieJar::LWP->new, ); # and then send requests just as you used to do $res = $ua->request(HTTP::Request->new(GET => "http://no.yahoo.com/")); print $res->status_line, "\n"; =head1 HTTPS URLs with https scheme are accessed in exactly the same way as with http scheme, provided that an SSL interface module for LWP has been properly installed (see the F file found in the libwww-perl distribution for more details). If no SSL interface is installed for LWP to use, then you will get "501 Protocol scheme 'https' is not supported" errors when accessing such URLs. Here's an example of fetching and printing a WWW page using SSL: use LWP::UserAgent; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => 'https://www.helsinki.fi/'); my $res = $ua->request($req); if ($res->is_success) { print $res->as_string; } else { print "Failed: ", $res->status_line, "\n"; } =head1 MIRRORING If you want to mirror documents from a WWW server, then try to run code similar to this at regular intervals: use LWP::Simple; %mirrors = ( 'http://www.sn.no/' => 'sn.html', 'http://www.perl.com/' => 'perl.html', 'http://search.cpan.org/distlibwww-perl/' => 'lwp.html', 'gopher://gopher.sn.no/' => 'gopher.html', ); while (($url, $localfile) = each(%mirrors)) { mirror($url, $localfile); } Or, as a perl one-liner: perl -MLWP::Simple -e 'mirror("http://www.perl.com/", "perl.html")'; The document will not be transferred unless it has been updated. =head1 LARGE DOCUMENTS If the document you want to fetch is too large to be kept in memory, then you have two alternatives. You can instruct the library to write the document content to a file (second $ua->request() argument is a file name): use LWP::UserAgent; $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => 'http://www.cpan.org/CPAN/authors/id/O/OA/OALDERS/libwww-perl-6.26.tar.gz'); $res = $ua->request($req, "libwww-perl.tar.gz"); if ($res->is_success) { print "ok\n"; } else { print $res->status_line, "\n"; } Or you can process the document as it arrives (second $ua->request() argument is a code reference): use LWP::UserAgent; $ua = LWP::UserAgent->new; $URL = 'ftp://ftp.isc.org/pub/rfc/rfc-index.txt'; my $expected_length; my $bytes_received = 0; my $res = $ua->request(HTTP::Request->new(GET => $URL), sub { my($chunk, $res) = @_; $bytes_received += length($chunk); unless (defined $expected_length) { $expected_length = $res->content_length || 0; } if ($expected_length) { printf STDERR "%d%% - ", 100 * $bytes_received / $expected_length; } print STDERR "$bytes_received bytes received\n"; # XXX Should really do something with the chunk itself # print $chunk; }); print $res->status_line, "\n"; =head1 COPYRIGHT Copyright 1996-2001, Gisle Aas This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. perl5/LWP/ConnCache.pm000044400000021057152462503210010417 0ustar00package LWP::ConnCache; use strict; our $VERSION = '6.58'; our $DEBUG; sub new { my($class, %cnf) = @_; my $total_capacity = 1; if (exists $cnf{total_capacity}) { $total_capacity = delete $cnf{total_capacity}; } if (%cnf && $^W) { require Carp; Carp::carp("Unrecognised options: @{[sort keys %cnf]}") } my $self = bless { cc_conns => [] }, $class; $self->total_capacity($total_capacity); $self; } sub deposit { my($self, $type, $key, $conn) = @_; push(@{$self->{cc_conns}}, [$conn, $type, $key, time]); $self->enforce_limits($type); return; } sub withdraw { my($self, $type, $key) = @_; my $conns = $self->{cc_conns}; for my $i (0 .. @$conns - 1) { my $c = $conns->[$i]; next unless $c->[1] eq $type && $c->[2] eq $key; splice(@$conns, $i, 1); # remove it return $c->[0]; } return undef; } sub total_capacity { my $self = shift; my $old = $self->{cc_limit_total}; if (@_) { $self->{cc_limit_total} = shift; $self->enforce_limits; } $old; } sub capacity { my $self = shift; my $type = shift; my $old = $self->{cc_limit}{$type}; if (@_) { $self->{cc_limit}{$type} = shift; $self->enforce_limits($type); } $old; } sub enforce_limits { my($self, $type) = @_; my $conns = $self->{cc_conns}; my @types = $type ? ($type) : ($self->get_types); for $type (@types) { next unless $self->{cc_limit}; my $limit = $self->{cc_limit}{$type}; next unless defined $limit; for my $i (reverse 0 .. @$conns - 1) { next unless $conns->[$i][1] eq $type; if (--$limit < 0) { $self->dropping(splice(@$conns, $i, 1), "$type capacity exceeded"); } } } if (defined(my $total = $self->{cc_limit_total})) { while (@$conns > $total) { $self->dropping(shift(@$conns), "Total capacity exceeded"); } } } sub dropping { my($self, $c, $reason) = @_; print "DROPPING @$c [$reason]\n" if $DEBUG; } sub drop { my($self, $checker, $reason) = @_; if (ref($checker) ne "CODE") { # make it so if (!defined $checker) { $checker = sub { 1 }; # drop all of them } elsif (_looks_like_number($checker)) { my $age_limit = $checker; my $time_limit = time - $age_limit; $reason ||= "older than $age_limit"; $checker = sub { $_[3] < $time_limit }; } else { my $type = $checker; $reason ||= "drop $type"; $checker = sub { $_[1] eq $type }; # match on type } } $reason ||= "drop"; local $SIG{__DIE__}; # don't interfere with eval below local $@; my @c; for (@{$self->{cc_conns}}) { my $drop; eval { if (&$checker(@$_)) { $self->dropping($_, $reason); $drop++; } }; push(@c, $_) unless $drop; } @{$self->{cc_conns}} = @c; } sub prune { my $self = shift; $self->drop(sub { !shift->ping }, "ping"); } sub get_types { my $self = shift; my %t; $t{$_->[1]}++ for @{$self->{cc_conns}}; return keys %t; } sub get_connections { my($self, $type) = @_; my @c; for (@{$self->{cc_conns}}) { push(@c, $_->[0]) if !$type || ($type && $type eq $_->[1]); } @c; } sub _looks_like_number { $_[0] =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/; } 1; __END__ =pod =head1 NAME LWP::ConnCache - Connection cache manager =head1 NOTE This module is experimental. Details of its interface is likely to change in the future. =head1 SYNOPSIS use LWP::ConnCache; my $cache = LWP::ConnCache->new; $cache->deposit($type, $key, $sock); $sock = $cache->withdraw($type, $key); =head1 DESCRIPTION The C class is the standard connection cache manager for L. =head1 METHODS The following basic methods are provided: =head2 new my $cache = LWP::ConnCache->new( %options ) This method constructs a new L object. The only option currently accepted is C. If specified it initializes the L option. It defaults to C<1>. =head2 total_capacity my $cap = $cache->total_capacity; $cache->total_capacity(0); # drop all immediately $cache->total_capacity(undef); # no limit $cache->total_capacity($number); Get/sets the number of connection that will be cached. Connections will start to be dropped when this limit is reached. If set to C<0>, then all connections are immediately dropped. If set to C, then there is no limit. =head2 capacity my $http_capacity = $cache->capacity('http'); $cache->capacity('http', 2 ); Get/set a limit for the number of connections of the specified type that can be cached. The first parameter is a short string like C<"http"> or C<"ftp">. =head2 drop $cache->drop(); # Drop ALL connections # which is just a synonym for: $cache->drop(sub{1}); # Drop ALL connections # drop all connections older than 22 seconds and add a reason for it! $cache->drop(22, "Older than 22 secs dropped"); # which is just a synonym for: $cache->drop(sub { my ($conn, $type, $key, $deposit_time) = @_; if ($deposit_time < 22) { # true values drop the connection return 1; } # false values don't drop the connection return 0; }, "Older than 22 secs dropped" ); Drop connections by some criteria. The $checker argument is a subroutine that is called for each connection. If the routine returns a TRUE value then the connection is dropped. The routine is called with C<($conn, $type, $key, $deposit_time)> as arguments. Shortcuts: If the C<$checker> argument is absent (or C) all cached connections are dropped. If the $checker is a number then all connections untouched that the given number of seconds or more are dropped. If $checker is a string then all connections of the given type are dropped. The C is passed on to the L method. =head2 prune $cache->prune(); Calling this method will drop all connections that are dead. This is tested by calling the L method on the connections. If the L method exists and returns a false value, then the connection is dropped. =head2 get_types my @types = $cache->get_types(); This returns all the C fields used for the currently cached connections. =head2 get_connections my @conns = $cache->get_connections(); # all connections my @conns = $cache->get_connections('http'); # connections for http This returns all connection objects of the specified type. If no type is specified then all connections are returned. In scalar context the number of cached connections of the specified type is returned. =head1 PROTOCOL METHODS The following methods are called by low-level protocol modules to try to save away connections and to get them back. =head2 deposit $cache->deposit($type, $key, $conn); This method adds a new connection to the cache. As a result, other already cached connections might be dropped. Multiple connections with the same type/key might be added. =head2 withdraw my $conn = $cache->withdraw($type, $key); This method tries to fetch back a connection that was previously deposited. If no cached connection with the specified $type/$key is found, then C is returned. There is not guarantee that a deposited connection can be withdrawn, as the cache manger is free to drop connections at any time. =head1 INTERNAL METHODS The following methods are called internally. Subclasses might want to override them. =head2 enforce_limits $conn->enforce_limits([$type]) This method is called with after a new connection is added (deposited) in the cache or capacity limits are adjusted. The default implementation drops connections until the specified capacity limits are not exceeded. =head2 dropping $conn->dropping($conn_record, $reason) This method is called when a connection is dropped. The record belonging to the dropped connection is passed as the first argument and a string describing the reason for the drop is passed as the second argument. The default implementation makes some noise if the C<$LWP::ConnCache::DEBUG> variable is set and nothing more. =head1 SUBCLASSING For specialized cache policy it makes sense to subclass C and perhaps override the L, L, and L methods. The object itself is a hash. Keys prefixed with C are reserved for the base class. =head1 SEE ALSO L =head1 COPYRIGHT Copyright 2001 Gisle Aas. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/LWP/Debug/TraceHTTP.pm000044400000001131152462503210011351 0ustar00package LWP::Debug::TraceHTTP; # Just call: # # require LWP::Debug::TraceHTTP; # LWP::Protocol::implementor('http', 'LWP::Debug::TraceHTTP'); # # to use this module to trace all calls to the HTTP socket object in # programs that use LWP. use strict; use parent 'LWP::Protocol::http'; our $VERSION = '6.58'; package # hide from PAUSE LWP::Debug::TraceHTTP::Socket; use Data::Dump 1.13; use Data::Dump::Trace qw(autowrap mcall); autowrap("LWP::Protocol::http::Socket" => "sock"); sub new { my $class = shift; return mcall("LWP::Protocol::http::Socket" => "new", undef, @_); } 1; perl5/LWP/UserAgent.pm000044400000216200152462503210010467 0ustar00package LWP::UserAgent; use strict; use parent qw(LWP::MemberMixin); use Carp (); use HTTP::Request (); use HTTP::Response (); use HTTP::Date (); use LWP (); use HTTP::Status (); use LWP::Protocol (); use Scalar::Util qw(blessed); use Try::Tiny qw(try catch); our $VERSION = '6.58'; sub new { # Check for common user mistake Carp::croak("Options to LWP::UserAgent should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH'; my($class, %cnf) = @_; my $agent = delete $cnf{agent}; my $from = delete $cnf{from}; my $def_headers = delete $cnf{default_headers}; my $timeout = delete $cnf{timeout}; $timeout = 3*60 unless defined $timeout; my $local_address = delete $cnf{local_address}; my $ssl_opts = delete $cnf{ssl_opts} || {}; unless (exists $ssl_opts->{verify_hostname}) { # The processing of HTTPS_CA_* below is for compatibility with Crypt::SSLeay if (exists $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}) { $ssl_opts->{verify_hostname} = $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}; } elsif ($ENV{HTTPS_CA_FILE} || $ENV{HTTPS_CA_DIR}) { # Crypt-SSLeay compatibility (verify peer certificate; but not the hostname) $ssl_opts->{verify_hostname} = 0; $ssl_opts->{SSL_verify_mode} = 1; } else { $ssl_opts->{verify_hostname} = 1; } } unless (exists $ssl_opts->{SSL_ca_file}) { if (my $ca_file = $ENV{PERL_LWP_SSL_CA_FILE} || $ENV{HTTPS_CA_FILE}) { $ssl_opts->{SSL_ca_file} = $ca_file; } } unless (exists $ssl_opts->{SSL_ca_path}) { if (my $ca_path = $ENV{PERL_LWP_SSL_CA_PATH} || $ENV{HTTPS_CA_DIR}) { $ssl_opts->{SSL_ca_path} = $ca_path; } } my $use_eval = delete $cnf{use_eval}; $use_eval = 1 unless defined $use_eval; my $parse_head = delete $cnf{parse_head}; $parse_head = 1 unless defined $parse_head; my $send_te = delete $cnf{send_te}; $send_te = 1 unless defined $send_te; my $show_progress = delete $cnf{show_progress}; my $max_size = delete $cnf{max_size}; my $max_redirect = delete $cnf{max_redirect}; $max_redirect = 7 unless defined $max_redirect; my $env_proxy = exists $cnf{env_proxy} ? delete $cnf{env_proxy} : $ENV{PERL_LWP_ENV_PROXY}; my $no_proxy = exists $cnf{no_proxy} ? delete $cnf{no_proxy} : []; Carp::croak(qq{no_proxy must be an arrayref, not $no_proxy!}) if ref $no_proxy ne 'ARRAY'; my $cookie_jar = delete $cnf{cookie_jar}; my $conn_cache = delete $cnf{conn_cache}; my $keep_alive = delete $cnf{keep_alive}; Carp::croak("Can't mix conn_cache and keep_alive") if $conn_cache && $keep_alive; my $protocols_allowed = delete $cnf{protocols_allowed}; my $protocols_forbidden = delete $cnf{protocols_forbidden}; my $requests_redirectable = delete $cnf{requests_redirectable}; $requests_redirectable = ['GET', 'HEAD'] unless defined $requests_redirectable; # Actually ""s are just as good as 0's, but for concision we'll just say: Carp::croak("protocols_allowed has to be an arrayref or 0, not \"$protocols_allowed\"!") if $protocols_allowed and ref($protocols_allowed) ne 'ARRAY'; Carp::croak("protocols_forbidden has to be an arrayref or 0, not \"$protocols_forbidden\"!") if $protocols_forbidden and ref($protocols_forbidden) ne 'ARRAY'; Carp::croak("requests_redirectable has to be an arrayref or 0, not \"$requests_redirectable\"!") if $requests_redirectable and ref($requests_redirectable) ne 'ARRAY'; if (%cnf && $^W) { Carp::carp("Unrecognized LWP::UserAgent options: @{[sort keys %cnf]}"); } my $self = bless { def_headers => $def_headers, timeout => $timeout, local_address => $local_address, ssl_opts => $ssl_opts, use_eval => $use_eval, show_progress => $show_progress, max_size => $max_size, max_redirect => $max_redirect, # We set proxy later as we do validation on the values proxy => {}, no_proxy => [ @{ $no_proxy } ], protocols_allowed => $protocols_allowed, protocols_forbidden => $protocols_forbidden, requests_redirectable => $requests_redirectable, send_te => $send_te, }, $class; $self->agent(defined($agent) ? $agent : $class->_agent) if defined($agent) || !$def_headers || !$def_headers->header("User-Agent"); $self->from($from) if $from; $self->cookie_jar($cookie_jar) if $cookie_jar; $self->parse_head($parse_head); $self->env_proxy if $env_proxy; if (exists $cnf{proxy}) { Carp::croak(qq{proxy must be an arrayref, not $cnf{proxy}!}) if ref $cnf{proxy} ne 'ARRAY'; $self->proxy($cnf{proxy}); } $self->protocols_allowed( $protocols_allowed ) if $protocols_allowed; $self->protocols_forbidden($protocols_forbidden) if $protocols_forbidden; if ($keep_alive) { $conn_cache ||= { total_capacity => $keep_alive }; } $self->conn_cache($conn_cache) if $conn_cache; return $self; } sub send_request { my($self, $request, $arg, $size) = @_; my($method, $url) = ($request->method, $request->uri); my $scheme = $url->scheme; local($SIG{__DIE__}); # protect against user defined die handlers $self->progress("begin", $request); my $response = $self->run_handlers("request_send", $request); unless ($response) { my $protocol; { # Honor object-specific restrictions by forcing protocol objects # into class LWP::Protocol::nogo. my $x; if($x = $self->protocols_allowed) { if (grep lc($_) eq $scheme, @$x) { } else { require LWP::Protocol::nogo; $protocol = LWP::Protocol::nogo->new; } } elsif ($x = $self->protocols_forbidden) { if(grep lc($_) eq $scheme, @$x) { require LWP::Protocol::nogo; $protocol = LWP::Protocol::nogo->new; } } # else fall thru and create the protocol object normally } # Locate protocol to use my $proxy = $request->{proxy}; if ($proxy) { $scheme = $proxy->scheme; } unless ($protocol) { try { $protocol = LWP::Protocol::create($scheme, $self); } catch { my $error = $_; $error =~ s/ at .* line \d+.*//s; # remove file/line number $response = _new_response($request, HTTP::Status::RC_NOT_IMPLEMENTED, $error); if ($scheme eq "https") { $response->message($response->message . " (LWP::Protocol::https not installed)"); $response->content_type("text/plain"); $response->content(<{use_eval}) { # we eval, and turn dies into responses below try { $response = $protocol->request($request, $proxy, $arg, $size, $self->{timeout}) || die "No response returned by $protocol"; } catch { my $error = $_; if (blessed($error) && $error->isa("HTTP::Response")) { $response = $error; $response->request($request); } else { my $full = $error; (my $status = $error) =~ s/\n.*//s; $status =~ s/ at .* line \d+.*//s; # remove file/line number my $code = ($status =~ s/^(\d\d\d)\s+//) ? $1 : HTTP::Status::RC_INTERNAL_SERVER_ERROR; $response = _new_response($request, $code, $status, $full); } }; } elsif (!$response) { $response = $protocol->request($request, $proxy, $arg, $size, $self->{timeout}); # XXX: Should we die unless $response->is_success ??? } } $response->request($request); # record request for reference $response->header("Client-Date" => HTTP::Date::time2str(time)); $self->run_handlers("response_done", $response); $self->progress("end", $response); return $response; } sub prepare_request { my($self, $request) = @_; die "Method missing" unless $request->method; my $url = $request->uri; die "URL missing" unless $url; die "URL must be absolute" unless $url->scheme; $self->run_handlers("request_preprepare", $request); if (my $def_headers = $self->{def_headers}) { for my $h ($def_headers->header_field_names) { $request->init_header($h => [$def_headers->header($h)]); } } $self->run_handlers("request_prepare", $request); return $request; } sub simple_request { my($self, $request, $arg, $size) = @_; # sanity check the request passed in if (defined $request) { if (ref $request) { Carp::croak("You need a request object, not a " . ref($request) . " object") if ref($request) eq 'ARRAY' or ref($request) eq 'HASH' or !$request->can('method') or !$request->can('uri'); } else { Carp::croak("You need a request object, not '$request'"); } } else { Carp::croak("No request object passed in"); } my $error; try { $request = $self->prepare_request($request); } catch { $error = $_; $error =~ s/ at .* line \d+.*//s; # remove file/line number }; if ($error) { return _new_response($request, HTTP::Status::RC_BAD_REQUEST, $error); } return $self->send_request($request, $arg, $size); } sub request { my ($self, $request, $arg, $size, $previous) = @_; my $response = $self->simple_request($request, $arg, $size); $response->previous($previous) if $previous; if ($response->redirects >= $self->{max_redirect}) { if ($response->header('Location')) { $response->header("Client-Warning" => "Redirect loop detected (max_redirect = $self->{max_redirect})" ); } return $response; } if (my $req = $self->run_handlers("response_redirect", $response)) { return $self->request($req, $arg, $size, $response); } my $code = $response->code; if ( $code == HTTP::Status::RC_MOVED_PERMANENTLY or $code == HTTP::Status::RC_FOUND or $code == HTTP::Status::RC_SEE_OTHER or $code == HTTP::Status::RC_TEMPORARY_REDIRECT or $code == HTTP::Status::RC_PERMANENT_REDIRECT) { my $referral = $request->clone; # These headers should never be forwarded $referral->remove_header('Host', 'Cookie'); if ( $referral->header('Referer') && $request->uri->scheme eq 'https' && $referral->uri->scheme eq 'http') { # RFC 2616, section 15.1.3. # https -> http redirect, suppressing Referer $referral->remove_header('Referer'); } if ( $code == HTTP::Status::RC_SEE_OTHER || $code == HTTP::Status::RC_FOUND) { my $method = uc($referral->method); unless ($method eq "GET" || $method eq "HEAD") { $referral->method("GET"); $referral->content(""); $referral->remove_content_headers; } } # And then we update the URL based on the Location:-header. my $referral_uri = $response->header('Location'); { # Some servers erroneously return a relative URL for redirects, # so make it absolute if it not already is. local $URI::ABS_ALLOW_RELATIVE_SCHEME = 1; my $base = $response->base; $referral_uri = "" unless defined $referral_uri; $referral_uri = $HTTP::URI_CLASS->new($referral_uri, $base)->abs($base); } $referral->uri($referral_uri); return $response unless $self->redirect_ok($referral, $response); return $self->request($referral, $arg, $size, $response); } elsif ($code == HTTP::Status::RC_UNAUTHORIZED || $code == HTTP::Status::RC_PROXY_AUTHENTICATION_REQUIRED) { my $proxy = ($code == HTTP::Status::RC_PROXY_AUTHENTICATION_REQUIRED); my $ch_header = $proxy || $request->method eq 'CONNECT' ? "Proxy-Authenticate" : "WWW-Authenticate"; my @challenges = $response->header($ch_header); unless (@challenges) { $response->header( "Client-Warning" => "Missing Authenticate header"); return $response; } require HTTP::Headers::Util; CHALLENGE: for my $challenge (@challenges) { $challenge =~ tr/,/;/; # "," is used to separate auth-params!! ($challenge) = HTTP::Headers::Util::split_header_words($challenge); my $scheme = shift(@$challenge); shift(@$challenge); # no value $challenge = {@$challenge}; # make rest into a hash unless ($scheme =~ /^([a-z]+(?:-[a-z]+)*)$/) { $response->header( "Client-Warning" => "Bad authentication scheme '$scheme'"); return $response; } $scheme = $1; # untainted now my $class = "LWP::Authen::\u$scheme"; $class =~ tr/-/_/; no strict 'refs'; unless (%{"$class\::"}) { # try to load it my $error; try { (my $req = $class) =~ s{::}{/}g; $req .= '.pm' unless $req =~ /\.pm$/; require $req; } catch { $error = $_; }; if ($error) { if ($error =~ /^Can\'t locate/) { $response->header("Client-Warning" => "Unsupported authentication scheme '$scheme'"); } else { $response->header("Client-Warning" => $error); } next CHALLENGE; } } unless ($class->can("authenticate")) { $response->header("Client-Warning" => "Unsupported authentication scheme '$scheme'"); next CHALLENGE; } my $re = $class->authenticate($self, $proxy, $challenge, $response, $request, $arg, $size); next CHALLENGE if $re->code == HTTP::Status::RC_UNAUTHORIZED; return $re; } return $response; } return $response; } # # Now the shortcuts... # sub get { require HTTP::Request::Common; my($self, @parameters) = @_; my @suff = $self->_process_colonic_headers(\@parameters,1); return $self->request( HTTP::Request::Common::GET( @parameters ), @suff ); } sub _maybe_copy_default_content_type { my $self = shift; my $req = shift; my $default_ct = $self->default_header('Content-Type'); return unless defined $default_ct; # drop url shift; # adapted from HTTP::Request::Common::request_type_with_data my $content; $content = shift if @_ and ref $_[0]; # We only care about the final value, really my $ct; my ($k, $v); while (($k, $v) = splice(@_, 0, 2)) { if (lc($k) eq 'content') { $content = $v; } elsif (lc($k) eq 'content-type') { $ct = $v; } } # Content-type provided and truthy? skip return if $ct; # Content is not just a string? Then it must be x-www-form-urlencoded return if defined $content && ref($content); # Provide default $req->header('Content-Type' => $default_ct); } sub post { require HTTP::Request::Common; my($self, @parameters) = @_; my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1)); my $req = HTTP::Request::Common::POST(@parameters); $self->_maybe_copy_default_content_type($req, @parameters); return $self->request($req, @suff); } sub head { require HTTP::Request::Common; my($self, @parameters) = @_; my @suff = $self->_process_colonic_headers(\@parameters,1); return $self->request( HTTP::Request::Common::HEAD( @parameters ), @suff ); } sub patch { require HTTP::Request::Common; my($self, @parameters) = @_; my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1)); # this work-around is in place as HTTP::Request::Common # did not implement a patch convenience method until # version 6.12. Once we can bump the prereq to at least # that version, we can use ::PATCH instead of this hack my $req = HTTP::Request::Common::PUT(@parameters); $req->method('PATCH'); $self->_maybe_copy_default_content_type($req, @parameters); return $self->request($req, @suff); } sub put { require HTTP::Request::Common; my($self, @parameters) = @_; my @suff = $self->_process_colonic_headers(\@parameters, (ref($parameters[1]) ? 2 : 1)); my $req = HTTP::Request::Common::PUT(@parameters); $self->_maybe_copy_default_content_type($req, @parameters); return $self->request($req, @suff); } sub delete { require HTTP::Request::Common; my($self, @parameters) = @_; my @suff = $self->_process_colonic_headers(\@parameters,1); return $self->request( HTTP::Request::Common::DELETE( @parameters ), @suff ); } sub _process_colonic_headers { # Process :content_cb / :content_file / :read_size_hint headers. my($self, $args, $start_index) = @_; my($arg, $size); for(my $i = $start_index; $i < @$args; $i += 2) { next unless defined $args->[$i]; #printf "Considering %s => %s\n", $args->[$i], $args->[$i + 1]; if($args->[$i] eq ':content_cb') { # Some sanity-checking... $arg = $args->[$i + 1]; Carp::croak("A :content_cb value can't be undef") unless defined $arg; Carp::croak("A :content_cb value must be a coderef") unless ref $arg and UNIVERSAL::isa($arg, 'CODE'); } elsif ($args->[$i] eq ':content_file') { $arg = $args->[$i + 1]; # Some sanity-checking... Carp::croak("A :content_file value can't be undef") unless defined $arg; Carp::croak("A :content_file value can't be a reference") if ref $arg; Carp::croak("A :content_file value can't be \"\"") unless length $arg; } elsif ($args->[$i] eq ':read_size_hint') { $size = $args->[$i + 1]; # Bother checking it? } else { next; } splice @$args, $i, 2; $i -= 2; } # And return a suitable suffix-list for request(REQ,...) return unless defined $arg; return $arg, $size if defined $size; return $arg; } sub is_online { my $self = shift; return 1 if $self->get("http://www.msftncsi.com/ncsi.txt")->content eq "Microsoft NCSI"; return 1 if $self->get("http://www.apple.com")->content =~ m,Apple,; return 0; } my @ANI = qw(- \ | /); sub progress { my($self, $status, $m) = @_; return unless $self->{show_progress}; local($,, $\); if ($status eq "begin") { print STDERR "** ", $m->method, " ", $m->uri, " ==> "; $self->{progress_start} = time; $self->{progress_lastp} = ""; $self->{progress_ani} = 0; } elsif ($status eq "end") { delete $self->{progress_lastp}; delete $self->{progress_ani}; print STDERR $m->status_line; my $t = time - delete $self->{progress_start}; print STDERR " (${t}s)" if $t; print STDERR "\n"; } elsif ($status eq "tick") { print STDERR "$ANI[$self->{progress_ani}++]\b"; $self->{progress_ani} %= @ANI; } else { my $p = sprintf "%3.0f%%", $status * 100; return if $p eq $self->{progress_lastp}; print STDERR "$p\b\b\b\b"; $self->{progress_lastp} = $p; } STDERR->flush; } # # This whole allow/forbid thing is based on man 1 at's way of doing things. # sub is_protocol_supported { my($self, $scheme) = @_; if (ref $scheme) { # assume we got a reference to an URI object $scheme = $scheme->scheme; } else { Carp::croak("Illegal scheme '$scheme' passed to is_protocol_supported") if $scheme =~ /\W/; $scheme = lc $scheme; } my $x; if(ref($self) and $x = $self->protocols_allowed) { return 0 unless grep lc($_) eq $scheme, @$x; } elsif (ref($self) and $x = $self->protocols_forbidden) { return 0 if grep lc($_) eq $scheme, @$x; } local($SIG{__DIE__}); # protect against user defined die handlers $x = LWP::Protocol::implementor($scheme); return 1 if $x and $x ne 'LWP::Protocol::nogo'; return 0; } sub protocols_allowed { shift->_elem('protocols_allowed' , @_) } sub protocols_forbidden { shift->_elem('protocols_forbidden' , @_) } sub requests_redirectable { shift->_elem('requests_redirectable', @_) } sub redirect_ok { # RFC 2616, section 10.3.2 and 10.3.3 say: # If the 30[12] status code is received in response to a request other # than GET or HEAD, the user agent MUST NOT automatically redirect the # request unless it can be confirmed by the user, since this might # change the conditions under which the request was issued. # Note that this routine used to be just: # return 0 if $_[1]->method eq "POST"; return 1; my($self, $new_request, $response) = @_; my $method = $response->request->method; return 0 unless grep $_ eq $method, @{ $self->requests_redirectable || [] }; if ($new_request->uri->scheme eq 'file') { $response->header("Client-Warning" => "Can't redirect to a file:// URL!"); return 0; } # Otherwise it's apparently okay... return 1; } sub credentials { my $self = shift; my $netloc = lc(shift || ''); my $realm = shift || ""; my $old = $self->{basic_authentication}{$netloc}{$realm}; if (@_) { $self->{basic_authentication}{$netloc}{$realm} = [@_]; } return unless $old; return @$old if wantarray; return join(":", @$old); } sub get_basic_credentials { my($self, $realm, $uri, $proxy) = @_; return if $proxy; return $self->credentials($uri->host_port, $realm); } sub timeout { shift->_elem('timeout', @_); } sub local_address{ shift->_elem('local_address',@_); } sub max_size { shift->_elem('max_size', @_); } sub max_redirect { shift->_elem('max_redirect', @_); } sub show_progress{ shift->_elem('show_progress', @_); } sub send_te { shift->_elem('send_te', @_); } sub ssl_opts { my $self = shift; if (@_ == 1) { my $k = shift; return $self->{ssl_opts}{$k}; } if (@_) { my $old; while (@_) { my($k, $v) = splice(@_, 0, 2); $old = $self->{ssl_opts}{$k} unless @_; if (defined $v) { $self->{ssl_opts}{$k} = $v; } else { delete $self->{ssl_opts}{$k}; } } %{$self->{ssl_opts}} = (%{$self->{ssl_opts}}, @_); return $old; } my @opts= sort keys %{$self->{ssl_opts}}; return @opts; } sub parse_head { my $self = shift; if (@_) { my $flag = shift; my $parser; my $old = $self->set_my_handler("response_header", $flag ? sub { my($response, $ua) = @_; require HTML::HeadParser; $parser = HTML::HeadParser->new; $parser->xml_mode(1) if $response->content_is_xhtml; $parser->utf8_mode(1) if $] >= 5.008 && $HTML::Parser::VERSION >= 3.40; push(@{$response->{handlers}{response_data}}, { callback => sub { return unless $parser; unless ($parser->parse($_[3])) { my $h = $parser->header; my $r = $_[0]; for my $f ($h->header_field_names) { $r->init_header($f, [$h->header($f)]); } undef($parser); } }, }); } : undef, m_media_type => "html", ); return !!$old; } else { return !!$self->get_my_handler("response_header"); } } sub cookie_jar { my $self = shift; my $old = $self->{cookie_jar}; if (@_) { my $jar = shift; if (ref($jar) eq "HASH") { require HTTP::Cookies; $jar = HTTP::Cookies->new(%$jar); } $self->{cookie_jar} = $jar; $self->set_my_handler("request_prepare", $jar ? sub { return if $_[0]->header("Cookie"); $jar->add_cookie_header($_[0]); } : undef, ); $self->set_my_handler("response_done", $jar ? sub { $jar->extract_cookies($_[0]); } : undef, ); } $old; } sub default_headers { my $self = shift; my $old = $self->{def_headers} ||= HTTP::Headers->new; if (@_) { Carp::croak("default_headers not set to HTTP::Headers compatible object") unless @_ == 1 && $_[0]->can("header_field_names"); $self->{def_headers} = shift; } return $old; } sub default_header { my $self = shift; return $self->default_headers->header(@_); } sub _agent { "libwww-perl/$VERSION" } sub agent { my $self = shift; if (@_) { my $agent = shift; if ($agent) { $agent .= $self->_agent if $agent =~ /\s+$/; } else { undef($agent) } return $self->default_header("User-Agent", $agent); } return $self->default_header("User-Agent"); } sub from { # legacy my $self = shift; return $self->default_header("From", @_); } sub conn_cache { my $self = shift; my $old = $self->{conn_cache}; if (@_) { my $cache = shift; if (ref($cache) eq "HASH") { require LWP::ConnCache; $cache = LWP::ConnCache->new(%$cache); } $self->{conn_cache} = $cache; } $old; } sub add_handler { my($self, $phase, $cb, %spec) = @_; $spec{line} ||= join(":", (caller)[1,2]); my $conf = $self->{handlers}{$phase} ||= do { require HTTP::Config; HTTP::Config->new; }; $conf->add(%spec, callback => $cb); } sub set_my_handler { my($self, $phase, $cb, %spec) = @_; $spec{owner} = (caller(1))[3] unless exists $spec{owner}; $self->remove_handler($phase, %spec); $spec{line} ||= join(":", (caller)[1,2]); $self->add_handler($phase, $cb, %spec) if $cb; } sub get_my_handler { my $self = shift; my $phase = shift; my $init = pop if @_ % 2; my %spec = @_; my $conf = $self->{handlers}{$phase}; unless ($conf) { return unless $init; require HTTP::Config; $conf = $self->{handlers}{$phase} = HTTP::Config->new; } $spec{owner} = (caller(1))[3] unless exists $spec{owner}; my @h = $conf->find(%spec); if (!@h && $init) { if (ref($init) eq "CODE") { $init->(\%spec); } elsif (ref($init) eq "HASH") { $spec{$_}= $init->{$_} for keys %$init; } $spec{callback} ||= sub {}; $spec{line} ||= join(":", (caller)[1,2]); $conf->add(\%spec); return \%spec; } return wantarray ? @h : $h[0]; } sub remove_handler { my($self, $phase, %spec) = @_; if ($phase) { my $conf = $self->{handlers}{$phase} || return; my @h = $conf->remove(%spec); delete $self->{handlers}{$phase} if $conf->empty; return @h; } return unless $self->{handlers}; return map $self->remove_handler($_), sort keys %{$self->{handlers}}; } sub handlers { my($self, $phase, $o) = @_; my @h; if ($o->{handlers} && $o->{handlers}{$phase}) { push(@h, @{$o->{handlers}{$phase}}); } if (my $conf = $self->{handlers}{$phase}) { push(@h, $conf->matching($o)); } return @h; } sub run_handlers { my($self, $phase, $o) = @_; # here we pass $_[2] to the callbacks, instead of $o, so that they # can assign to it; e.g. request_prepare is documented to allow # that if (defined(wantarray)) { for my $h ($self->handlers($phase, $o)) { my $ret = $h->{callback}->($_[2], $self, $h); return $ret if $ret; } return undef; } for my $h ($self->handlers($phase, $o)) { $h->{callback}->($_[2], $self, $h); } } # deprecated sub use_eval { shift->_elem('use_eval', @_); } sub use_alarm { Carp::carp("LWP::UserAgent->use_alarm(BOOL) is a no-op") if @_ > 1 && $^W; ""; } sub clone { my $self = shift; my $copy = bless { %$self }, ref $self; # copy most fields delete $copy->{handlers}; delete $copy->{conn_cache}; # copy any plain arrays and hashes; known not to need recursive copy for my $k (qw(proxy no_proxy requests_redirectable ssl_opts)) { next unless $copy->{$k}; if (ref($copy->{$k}) eq "ARRAY") { $copy->{$k} = [ @{$copy->{$k}} ]; } elsif (ref($copy->{$k}) eq "HASH") { $copy->{$k} = { %{$copy->{$k}} }; } } if ($self->{def_headers}) { $copy->{def_headers} = $self->{def_headers}->clone; } # re-enable standard handlers $copy->parse_head($self->parse_head); # no easy way to clone the cookie jar; so let's just remove it for now $copy->cookie_jar(undef); $copy; } sub mirror { my($self, $url, $file) = @_; die "Local file name is missing" unless defined $file && length $file; my $request = HTTP::Request->new('GET', $url); # If the file exists, add a cache-related header if ( -e $file ) { my ($mtime) = ( stat($file) )[9]; if ($mtime) { $request->header( 'If-Modified-Since' => HTTP::Date::time2str($mtime) ); } } my $tmpfile = "$file-$$"; my $response = $self->request($request, $tmpfile); if ( $response->header('X-Died') ) { die $response->header('X-Died'); } # Only fetching a fresh copy of the file would be considered success. # If the file was not modified, "304" would returned, which # is considered by HTTP::Status to be a "redirect", /not/ "success" if ( $response->is_success ) { my @stat = stat($tmpfile) or die "Could not stat tmpfile '$tmpfile': $!"; my $file_length = $stat[7]; my ($content_length) = $response->header('Content-length'); if ( defined $content_length and $file_length < $content_length ) { unlink($tmpfile); die "Transfer truncated: " . "only $file_length out of $content_length bytes received\n"; } elsif ( defined $content_length and $file_length > $content_length ) { unlink($tmpfile); die "Content-length mismatch: " . "expected $content_length bytes, got $file_length\n"; } # The file was the expected length. else { # Replace the stale file with a fresh copy if ( -e $file ) { # Some DOSish systems fail to rename if the target exists chmod 0777, $file; unlink $file; } rename( $tmpfile, $file ) or die "Cannot rename '$tmpfile' to '$file': $!\n"; # make sure the file has the same last modification time if ( my $lm = $response->last_modified ) { utime $lm, $lm, $file; } } } # The local copy is fresh enough, so just delete the temp file else { unlink($tmpfile); } return $response; } sub _need_proxy { my($req, $ua) = @_; return if exists $req->{proxy}; my $proxy = $ua->{proxy}{$req->uri->scheme} || return; if ($ua->{no_proxy}) { if (my $host = eval { $req->uri->host }) { for my $domain (@{$ua->{no_proxy}}) { if ($host =~ /\Q$domain\E$/) { return; } } } } $req->{proxy} = $HTTP::URI_CLASS->new($proxy); } sub proxy { my $self = shift; my $key = shift; if (!@_ && ref $key eq 'ARRAY') { die 'odd number of items in proxy arrayref!' unless @{$key} % 2 == 0; # This map reads the elements of $key 2 at a time return map { $self->proxy($key->[2 * $_], $key->[2 * $_ + 1]) } (0 .. @{$key} / 2 - 1); } return map { $self->proxy($_, @_) } @$key if ref $key; Carp::croak("'$key' is not a valid URI scheme") unless $key =~ /^$URI::scheme_re\z/; my $old = $self->{'proxy'}{$key}; if (@_) { my $url = shift; if (defined($url) && length($url)) { Carp::croak("Proxy must be specified as absolute URI; '$url' is not") unless $url =~ /^$URI::scheme_re:/; Carp::croak("Bad http proxy specification '$url'") if $url =~ /^https?:/ && $url !~ m,^https?://[\w[],; } $self->{proxy}{$key} = $url; $self->set_my_handler("request_preprepare", \&_need_proxy) } return $old; } sub env_proxy { my ($self) = @_; require Encode; require Encode::Locale; my $env_request_method= $ENV{REQUEST_METHOD}; my %seen; foreach my $k (sort keys %ENV) { my $real_key= $k; my $v= $ENV{$k} or next; if ( $env_request_method ) { # Need to be careful when called in the CGI environment, as # the HTTP_PROXY variable is under control of that other guy. next if $k =~ /^HTTP_/; $k = "HTTP_PROXY" if $k eq "CGI_HTTP_PROXY"; } $k = lc($k); if (my $from_key= $seen{$k}) { warn "Environment contains multiple differing definitions for '$k'.\n". "Using value from '$from_key' ($ENV{$from_key}) and ignoring '$real_key' ($v)" if $v ne $ENV{$from_key}; next; } else { $seen{$k}= $real_key; } next unless $k =~ /^(.*)_proxy$/; $k = $1; if ($k eq 'no') { $self->no_proxy(split(/\s*,\s*/, $v)); } else { # Ignore random _proxy variables, allow only valid schemes next unless $k =~ /^$URI::scheme_re\z/; # Ignore xxx_proxy variables if xxx isn't a supported protocol next unless LWP::Protocol::implementor($k); $self->proxy($k, Encode::decode(locale => $v)); } } } sub no_proxy { my($self, @no) = @_; if (@no) { push(@{ $self->{'no_proxy'} }, @no); } else { $self->{'no_proxy'} = []; } } sub _new_response { my($request, $code, $message, $content) = @_; $message ||= HTTP::Status::status_message($code); my $response = HTTP::Response->new($code, $message); $response->request($request); $response->header("Client-Date" => HTTP::Date::time2str(time)); $response->header("Client-Warning" => "Internal response"); $response->header("Content-Type" => "text/plain"); $response->content($content || "$code $message\n"); return $response; } 1; __END__ =pod =head1 NAME LWP::UserAgent - Web user agent class =head1 SYNOPSIS use strict; use warnings; use LWP::UserAgent (); my $ua = LWP::UserAgent->new(timeout => 10); $ua->env_proxy; my $response = $ua->get('http://example.com'); if ($response->is_success) { print $response->decoded_content; } else { die $response->status_line; } Extra layers of security (note the C and C): use strict; use warnings; use HTTP::CookieJar::LWP (); use LWP::UserAgent (); my $jar = HTTP::CookieJar::LWP->new; my $ua = LWP::UserAgent->new( cookie_jar => $jar, protocols_allowed => ['http', 'https'], timeout => 10, ); $ua->env_proxy; my $response = $ua->get('http://example.com'); if ($response->is_success) { print $response->decoded_content; } else { die $response->status_line; } =head1 DESCRIPTION The L is a class implementing a web user agent. L objects can be used to dispatch web requests. In normal use the application creates an L object, and then configures it with values for timeouts, proxies, name, etc. It then creates an instance of L for the request that needs to be performed. This request is then passed to one of the request method the UserAgent, which dispatches it using the relevant protocol, and returns a L object. There are convenience methods for sending the most common request types: L, L, L, L and L. When using these methods, the creation of the request object is hidden as shown in the synopsis above. The basic approach of the library is to use HTTP-style communication for all protocol schemes. This means that you will construct L objects and receive L objects even for non-HTTP resources like I and I. In order to achieve even more similarity to HTTP-style communications, I menus and file directories are converted to HTML documents. =head1 CONSTRUCTOR METHODS The following constructor methods are available: =head2 clone my $ua2 = $ua->clone; Returns a copy of the L object. B: Please be aware that the clone method does not copy or clone your C attribute. Due to the limited restrictions on what can be used for your cookie jar, there is no way to clone the attribute. The C attribute will be C in the new object instance. =head2 new my $ua = LWP::UserAgent->new( %options ) This method constructs a new L object and returns it. Key/value pair arguments may be provided to set up the initial state. The following options correspond to attribute methods described below: KEY DEFAULT ----------- -------------------- agent "libwww-perl/#.###" conn_cache undef cookie_jar undef default_headers HTTP::Headers->new from undef local_address undef max_redirect 7 max_size undef no_proxy [] parse_head 1 protocols_allowed undef protocols_forbidden undef proxy undef requests_redirectable ['GET', 'HEAD'] ssl_opts { verify_hostname => 1 } timeout 180 The following additional options are also accepted: If the C option is passed in with a true value, then proxy settings are read from environment variables (see L). If C isn't provided, the C environment variable controls if L is called during initialization. If the C option value is defined and non-zero, then an C is set up (see L). The C value is passed on as the C for the connection cache. C must be set as an arrayref of key/value pairs. C takes an arrayref of domains. =head1 ATTRIBUTES The settings of the configuration attributes modify the behaviour of the L when it dispatches requests. Most of these can also be initialized by options passed to the constructor method. The following attribute methods are provided. The attribute value is left unchanged if no argument is given. The return value from each method is the old attribute value. =head2 agent my $agent = $ua->agent; $ua->agent('Checkbot/0.4 '); # append the default to the end $ua->agent('Mozilla/5.0'); $ua->agent(""); # don't identify Get/set the product token that is used to identify the user agent on the network. The agent value is sent as the C header in the requests. The default is a string of the form C, where C<#.###> is substituted with the version number of this library. If the provided string ends with space, the default C string is appended to it. The user agent string should be one or more simple product identifiers with an optional version number separated by the C character. =head2 conn_cache my $cache_obj = $ua->conn_cache; $ua->conn_cache( $cache_obj ); Get/set the L object to use. See L for details. =head2 cookie_jar my $jar = $ua->cookie_jar; $ua->cookie_jar( $cookie_jar_obj ); Get/set the cookie jar object to use. The only requirement is that the cookie jar object must implement the C and C methods. These methods will then be invoked by the user agent as requests are sent and responses are received. Normally this will be a L object or some subclass. You are, however, encouraged to use L instead. See L for more information. use HTTP::CookieJar::LWP (); my $jar = HTTP::CookieJar::LWP->new; my $ua = LWP::UserAgent->new( cookie_jar => $jar ); # or after object creation $ua->cookie_jar( $cookie_jar ); The default is to have no cookie jar, i.e. never automatically add C headers to the requests. Shortcut: If a reference to a plain hash is passed in, it is replaced with an instance of L that is initialized based on the hash. This form also automatically loads the L module. It means that: $ua->cookie_jar({ file => "$ENV{HOME}/.cookies.txt" }); is really just a shortcut for: require HTTP::Cookies; $ua->cookie_jar(HTTP::Cookies->new(file => "$ENV{HOME}/.cookies.txt")); =head2 credentials my $creds = $ua->credentials(); $ua->credentials( $netloc, $realm ); $ua->credentials( $netloc, $realm, $uname, $pass ); $ua->credentials("www.example.com:80", "Some Realm", "foo", "secret"); Get/set the user name and password to be used for a realm. The C<$netloc> is a string of the form C<< : >>. The username and password will only be passed to this server. =head2 default_header $ua->default_header( $field ); $ua->default_header( $field => $value ); $ua->default_header('Accept-Encoding' => scalar HTTP::Message::decodable()); $ua->default_header('Accept-Language' => "no, en"); This is just a shortcut for C<< $ua->default_headers->header( $field => $value ) >>. =head2 default_headers my $headers = $ua->default_headers; $ua->default_headers( $headers_obj ); Get/set the headers object that will provide default header values for any requests sent. By default this will be an empty L object. =head2 from my $from = $ua->from; $ua->from('foo@bar.com'); Get/set the email address for the human user who controls the requesting user agent. The address should be machine-usable, as defined in L. The C value is sent as the C header in the requests. The default is to not send a C header. See L for the more general interface that allow any header to be defaulted. =head2 local_address my $address = $ua->local_address; $ua->local_address( $address ); Get/set the local interface to bind to for network connections. The interface can be specified as a hostname or an IP address. This value is passed as the C argument to L. =head2 max_redirect my $max = $ua->max_redirect; $ua->max_redirect( $n ); This reads or sets the object's limit of how many times it will obey redirection responses in a given request cycle. By default, the value is C<7>. This means that if you call L and the response is a redirect elsewhere which is in turn a redirect, and so on seven times, then LWP gives up after that seventh request. =head2 max_size my $size = $ua->max_size; $ua->max_size( $bytes ); Get/set the size limit for response content. The default is C, which means that there is no limit. If the returned response content is only partial, because the size limit was exceeded, then a C header will be added to the response. The content might end up longer than C as we abort once appending a chunk of data makes the length exceed the limit. The C header, if present, will indicate the length of the full content and will normally not be the same as C<< length($res->content) >>. =head2 parse_head my $bool = $ua->parse_head; $ua->parse_head( $boolean ); Get/set a value indicating whether we should initialize response headers from the Ehead> section of HTML documents. The default is true. I unless you know what you are doing. =head2 protocols_allowed my $aref = $ua->protocols_allowed; # get allowed protocols $ua->protocols_allowed( \@protocols ); # allow ONLY these $ua->protocols_allowed(undef); # delete the list $ua->protocols_allowed(['http',]); # ONLY allow http By default, an object has neither a C list, nor a L list. This reads (or sets) this user agent's list of protocols that the request methods will exclusively allow. The protocol names are case insensitive. For example: C<< $ua->protocols_allowed( [ 'http', 'https'] ); >> means that this user agent will I those protocols, and attempts to use this user agent to access URLs with any other schemes (like C) will result in a 500 error. Note that having a C list causes any L list to be ignored. =head2 protocols_forbidden my $aref = $ua->protocols_forbidden; # get the forbidden list $ua->protocols_forbidden(\@protocols); # do not allow these $ua->protocols_forbidden(['http',]); # All http reqs get a 500 $ua->protocols_forbidden(undef); # delete the list This reads (or sets) this user agent's list of protocols that the request method will I allow. The protocol names are case insensitive. For example: C<< $ua->protocols_forbidden( [ 'file', 'mailto'] ); >> means that this user agent will I allow those protocols, and attempts to use this user agent to access URLs with those schemes will result in a 500 error. =head2 requests_redirectable my $aref = $ua->requests_redirectable; $ua->requests_redirectable( \@requests ); $ua->requests_redirectable(['GET', 'HEAD',]); # the default This reads or sets the object's list of request names that L will allow redirection for. By default, this is C<['GET', 'HEAD']>, as per L. To change to include C, consider: push @{ $ua->requests_redirectable }, 'POST'; =head2 send_te my $bool = $ua->send_te; $ua->send_te( $boolean ); If true, will send a C header along with the request. The default is true. Set it to false to disable the C header for systems who can't handle it. =head2 show_progress my $bool = $ua->show_progress; $ua->show_progress( $boolean ); Get/set a value indicating whether a progress bar should be displayed on the terminal as requests are processed. The default is false. =head2 ssl_opts my @keys = $ua->ssl_opts; my $val = $ua->ssl_opts( $key ); $ua->ssl_opts( $key => $value ); Get/set the options for SSL connections. Without argument return the list of options keys currently set. With a single argument return the current value for the given option. With 2 arguments set the option value and return the old. Setting an option to the value C removes this option. The options that LWP relates to are: =over =item C => $bool When TRUE LWP will for secure protocol schemes ensure it connects to servers that have a valid certificate matching the expected hostname. If FALSE no checks are made and you can't be sure that you communicate with the expected peer. The no checks behaviour was the default for libwww-perl-5.837 and earlier releases. This option is initialized from the C environment variable. If this environment variable isn't set; then C defaults to 1. =item C => $path The path to a file containing Certificate Authority certificates. A default setting for this option is provided by checking the environment variables C and C in order. =item C => $path The path to a directory containing files containing Certificate Authority certificates. A default setting for this option is provided by checking the environment variables C and C in order. =back Other options can be set and are processed directly by the SSL Socket implementation in use. See L or L for details. The libwww-perl core no longer bundles protocol plugins for SSL. You will need to install L separately to enable support for processing https-URLs. =head2 timeout my $secs = $ua->timeout; $ua->timeout( $secs ); Get/set the timeout value in seconds. The default value is 180 seconds, i.e. 3 minutes. The request is aborted if no activity on the connection to the server is observed for C seconds. This means that the time it takes for the complete transaction and the L method to actually return might be longer. When a request times out, a response object is still returned. The response will have a standard HTTP Status Code (500). This response will have the "Client-Warning" header set to the value of "Internal response". See the L method description below for further details. =head1 PROXY ATTRIBUTES The following methods set up when requests should be passed via a proxy server. =head2 env_proxy $ua->env_proxy; Load proxy settings from C<*_proxy> environment variables. You might specify proxies like this (sh-syntax): gopher_proxy=http://proxy.my.place/ wais_proxy=http://proxy.my.place/ no_proxy="localhost,example.com" export gopher_proxy wais_proxy no_proxy csh or tcsh users should use the C command to define these environment variables. On systems with case insensitive environment variables there exists a name clash between the CGI environment variables and the C environment variable normally picked up by C. Because of this C is not honored for CGI scripts. The C environment variable can be used instead. =head2 no_proxy $ua->no_proxy( @domains ); $ua->no_proxy('localhost', 'example.com'); $ua->no_proxy(); # clear the list Do not proxy requests to the given domains. Calling C without any domains clears the list of domains. =head2 proxy $ua->proxy(\@schemes, $proxy_url) $ua->proxy(['http', 'ftp'], 'http://proxy.sn.no:8001/'); # For a single scheme: $ua->proxy($scheme, $proxy_url) $ua->proxy('gopher', 'http://proxy.sn.no:8001/'); # To set multiple proxies at once: $ua->proxy([ ftp => 'http://ftp.example.com:8001/', [ 'http', 'https' ] => 'http://http.example.com:8001/', ]); Set/retrieve proxy URL for a scheme. The first form specifies that the URL is to be used as a proxy for access methods listed in the list in the first method argument, i.e. C and C. The second form shows a shorthand form for specifying proxy URL for a single access scheme. The third form demonstrates setting multiple proxies at once. This is also the only form accepted by the constructor. =head1 HANDLERS Handlers are code that injected at various phases during the processing of requests. The following methods are provided to manage the active handlers: =head2 add_handler $ua->add_handler( $phase => \&cb, %matchspec ) Add handler to be invoked in the given processing phase. For how to specify C<%matchspec> see L. The possible values C<$phase> and the corresponding callback signatures are as follows. Note that the handlers are documented in the order in which they will be run, which is: request_preprepare request_prepare request_send response_header response_data response_done response_redirect =over =item request_preprepare => sub { my($request, $ua, $handler) = @_; ... } The handler is called before the C and other standard initialization of the request. This can be used to set up headers and attributes that the C handler depends on. Proxy initialization should take place here; but in general don't register handlers for this phase. =item request_prepare => sub { my($request, $ua, $handler) = @_; ... } The handler is called before the request is sent and can modify the request any way it see fit. This can for instance be used to add certain headers to specific requests. The method can assign a new request object to C<$_[0]> to replace the request that is sent fully. The return value from the callback is ignored. If an exception is raised it will abort the request and make the request method return a "400 Bad request" response. =item request_send => sub { my($request, $ua, $handler) = @_; ... } This handler gets a chance of handling requests before they're sent to the protocol handlers. It should return an L object if it wishes to terminate the processing; otherwise it should return nothing. The C and C handlers will not be invoked for this response, but the C will be. =item response_header => sub { my($response, $ua, $handler) = @_; ... } This handler is called right after the response headers have been received, but before any content data. The handler might set up handlers for data and might croak to abort the request. The handler might set the C<< $response->{default_add_content} >> value to control if any received data should be added to the response object directly. This will initially be false if the C<< $ua->request() >> method was called with a C<$content_file> or C<$content_cb argument>; otherwise true. =item response_data => sub { my($response, $ua, $handler, $data) = @_; ... } This handler is called for each chunk of data received for the response. The handler might croak to abort the request. This handler needs to return a TRUE value to be called again for subsequent chunks for the same request. =item response_done => sub { my($response, $ua, $handler) = @_; ... } The handler is called after the response has been fully received, but before any redirect handling is attempted. The handler can be used to extract information or modify the response. =item response_redirect => sub { my($response, $ua, $handler) = @_; ... } The handler is called in C<< $ua->request >> after C. If the handler returns an L object we'll start over with processing this request instead. =back For all of these, C<$handler> is a code reference to the handler that is currently being run. =head2 get_my_handler $ua->get_my_handler( $phase, %matchspec ); $ua->get_my_handler( $phase, %matchspec, $init ); Will retrieve the matching handler as hash ref. If C<$init> is passed as a true value, create and add the handler if it's not found. If C<$init> is a subroutine reference, then it's called with the created handler hash as argument. This sub might populate the hash with extra fields; especially the callback. If C<$init> is a hash reference, merge the hashes. =head2 handlers $ua->handlers( $phase, $request ) $ua->handlers( $phase, $response ) Returns the handlers that apply to the given request or response at the given processing phase. =head2 remove_handler $ua->remove_handler( undef, %matchspec ); $ua->remove_handler( $phase, %matchspec ); $ua->remove_handler(); # REMOVE ALL HANDLERS IN ALL PHASES Remove handlers that match the given C<%matchspec>. If C<$phase> is not provided, remove handlers from all phases. Be careful as calling this function with C<%matchspec> that is not specific enough can remove handlers not owned by you. It's probably better to use the L method instead. The removed handlers are returned. =head2 set_my_handler $ua->set_my_handler( $phase, $cb, %matchspec ); $ua->set_my_handler($phase, undef); # remove handler for phase Set handlers private to the executing subroutine. Works by defaulting an C field to the C<%matchspec> that holds the name of the called subroutine. You might pass an explicit C to override this. If C<$cb> is passed as C, remove the handler. =head1 REQUEST METHODS The methods described in this section are used to dispatch requests via the user agent. The following request methods are provided: =head2 delete my $res = $ua->delete( $url ); my $res = $ua->delete( $url, $field_name => $value, ... ); This method will dispatch a C request on the given URL. Additional headers and content options are the same as for the L method. This method will use the C function from L to build the request. See L for a details on how to pass form content and other advanced features. =head2 get my $res = $ua->get( $url ); my $res = $ua->get( $url , $field_name => $value, ... ); This method will dispatch a C request on the given URL. Further arguments can be given to initialize the headers of the request. These are given as separate name/value pairs. The return value is a response object. See L for a description of the interface it provides. There will still be a response object returned when LWP can't connect to the server specified in the URL or when other failures in protocol handlers occur. These internal responses use the standard HTTP status codes, so the responses can't be differentiated by testing the response status code alone. Error responses that LWP generates internally will have the "Client-Warning" header set to the value "Internal response". If you need to differentiate these internal responses from responses that a remote server actually generates, you need to test this header value. Fields names that start with ":" are special. These will not initialize headers of the request but will determine how the response content is treated. The following special field names are recognized: ':content_file' => $filename ':content_cb' => \&callback ':read_size_hint' => $bytes If a C<$filename> is provided with the C<:content_file> option, then the response content will be saved here instead of in the response object. If a callback is provided with the C<:content_cb> option then this function will be called for each chunk of the response content as it is received from the server. If neither of these options are given, then the response content will accumulate in the response object itself. This might not be suitable for very large response bodies. Only one of C<:content_file> or C<:content_cb> can be specified. The content of unsuccessful responses will always accumulate in the response object itself, regardless of the C<:content_file> or C<:content_cb> options passed in. Note that errors writing to the content file (for example due to permission denied or the filesystem being full) will be reported via the C or C response headers, and not the C method. The C<:read_size_hint> option is passed to the protocol module which will try to read data from the server in chunks of this size. A smaller value for the C<:read_size_hint> will result in a higher number of callback invocations. The callback function is called with 3 arguments: a chunk of data, a reference to the response object, and a reference to the protocol object. The callback can abort the request by invoking C. The exception message will show up as the "X-Died" header field in the response returned by the C<< $ua->get() >> method. =head2 head my $res = $ua->head( $url ); my $res = $ua->head( $url , $field_name => $value, ... ); This method will dispatch a C request on the given URL. Otherwise it works like the L method described above. =head2 is_protocol_supported my $bool = $ua->is_protocol_supported( $scheme ); You can use this method to test whether this user agent object supports the specified C. (The C might be a string (like C or C) or it might be an L object reference.) Whether a scheme is supported is determined by the user agent's C or C lists (if any), and by the capabilities of LWP. I.e., this will return true only if LWP supports this protocol I it's permitted for this particular object. =head2 is_online my $bool = $ua->is_online; Tries to determine if you have access to the Internet. Returns C<1> (true) if the built-in heuristics determine that the user agent is able to access the Internet (over HTTP) or C<0> (false). See also L. =head2 mirror my $res = $ua->mirror( $url, $filename ); This method will get the document identified by URL and store it in file called C<$filename>. If the file already exists, then the request will contain an C header matching the modification time of the file. If the document on the server has not changed since this time, then nothing happens. If the document has been updated, it will be downloaded again. The modification time of the file will be forced to match that of the server. The return value is an L object. =head2 patch # Any version of HTTP::Message works with this form: my $res = $ua->patch( $url, $field_name => $value, Content => $content ); # Using hash or array references requires HTTP::Message >= 6.12 use HTTP::Request 6.12; my $res = $ua->patch( $url, \%form ); my $res = $ua->patch( $url, \@form ); my $res = $ua->patch( $url, \%form, $field_name => $value, ... ); my $res = $ua->patch( $url, $field_name => $value, Content => \%form ); my $res = $ua->patch( $url, $field_name => $value, Content => \@form ); This method will dispatch a C request on the given URL, with C<%form> or C<@form> providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the L method. CAVEAT: This method can only accept content that is in key-value pairs when using L prior to version C<6.12>. Any use of hash or array references will result in an error prior to version C<6.12>. This method will use the C function from L to build the request. See L for a details on how to pass form content and other advanced features. =head2 post my $res = $ua->post( $url, \%form ); my $res = $ua->post( $url, \@form ); my $res = $ua->post( $url, \%form, $field_name => $value, ... ); my $res = $ua->post( $url, $field_name => $value, Content => \%form ); my $res = $ua->post( $url, $field_name => $value, Content => \@form ); my $res = $ua->post( $url, $field_name => $value, Content => $content ); This method will dispatch a C request on the given URL, with C<%form> or C<@form> providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the L method. This method will use the C function from L to build the request. See L for a details on how to pass form content and other advanced features. =head2 put # Any version of HTTP::Message works with this form: my $res = $ua->put( $url, $field_name => $value, Content => $content ); # Using hash or array references requires HTTP::Message >= 6.07 use HTTP::Request 6.07; my $res = $ua->put( $url, \%form ); my $res = $ua->put( $url, \@form ); my $res = $ua->put( $url, \%form, $field_name => $value, ... ); my $res = $ua->put( $url, $field_name => $value, Content => \%form ); my $res = $ua->put( $url, $field_name => $value, Content => \@form ); This method will dispatch a C request on the given URL, with C<%form> or C<@form> providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the L method. CAVEAT: This method can only accept content that is in key-value pairs when using L prior to version C<6.07>. Any use of hash or array references will result in an error prior to version C<6.07>. This method will use the C function from L to build the request. See L for a details on how to pass form content and other advanced features. =head2 request my $res = $ua->request( $request ); my $res = $ua->request( $request, $content_file ); my $res = $ua->request( $request, $content_cb ); my $res = $ua->request( $request, $content_cb, $read_size_hint ); This method will dispatch the given C<$request> object. Normally this will be an instance of the L class, but any object with a similar interface will do. The return value is an L object. The C method will process redirects and authentication responses transparently. This means that it may actually send several simple requests via the L method described below. The request methods described above; L, L, L and L will all dispatch the request they build via this method. They are convenience methods that simply hide the creation of the request object for you. The C<$content_file>, C<$content_cb> and C<$read_size_hint> all correspond to options described with the L method above. Note that errors writing to the content file (for example due to permission denied or the filesystem being full) will be reported via the C or C response headers, and not the C method. You are allowed to use a CODE reference as C in the request object passed in. The C function should return the content when called. The content can be returned in chunks. The content function will be invoked repeatedly until it return an empty string to signal that there is no more content. =head2 simple_request my $request = HTTP::Request->new( ... ); my $res = $ua->simple_request( $request ); my $res = $ua->simple_request( $request, $content_file ); my $res = $ua->simple_request( $request, $content_cb ); my $res = $ua->simple_request( $request, $content_cb, $read_size_hint ); This method dispatches a single request and returns the response received. Arguments are the same as for the L described above. The difference from L is that C will not try to handle redirects or authentication responses. The L method will, in fact, invoke this method for each simple request it sends. =head1 CALLBACK METHODS The following methods will be invoked as requests are processed. These methods are documented here because subclasses of L might want to override their behaviour. =head2 get_basic_credentials # This checks wantarray and can either return an array: my ($user, $pass) = $ua->get_basic_credentials( $realm, $uri, $isproxy ); # or a string that looks like "user:pass" my $creds = $ua->get_basic_credentials($realm, $uri, $isproxy); This is called by L to retrieve credentials for documents protected by Basic or Digest Authentication. The arguments passed in is the C<$realm> provided by the server, the C<$uri> requested and a C to indicate if this is authentication against a proxy server. The method should return a username and password. It should return an empty list to abort the authentication resolution attempt. Subclasses can override this method to prompt the user for the information. An example of this can be found in C program distributed with this library. The base implementation simply checks a set of pre-stored member variables, set up with the L method. =head2 prepare_request $request = $ua->prepare_request( $request ); This method is invoked by L. Its task is to modify the given C<$request> object by setting up various headers based on the attributes of the user agent. The return value should normally be the C<$request> object passed in. If a different request object is returned it will be the one actually processed. The headers affected by the base implementation are; C, C, C and C. =head2 progress my $prog = $ua->progress( $status, $request_or_response ); This is called frequently as the response is received regardless of how the content is processed. The method is called with C<$status> "begin" at the start of processing the request and with C<$state> "end" before the request method returns. In between these C<$status> will be the fraction of the response currently received or the string "tick" if the fraction can't be calculated. When C<$status> is "begin" the second argument is the L object, otherwise it is the L object. =head2 redirect_ok my $bool = $ua->redirect_ok( $prospective_request, $response ); This method is called by L before it tries to follow a redirection to the request in C<$response>. This should return a true value if this redirection is permissible. The C<$prospective_request> will be the request to be sent if this method returns true. The base implementation will return false unless the method is in the object's C list, false if the proposed redirection is to a C URL, and true otherwise. =head1 BEST PRACTICES The default settings can get you up and running quickly, but there are settings you can change in order to make your life easier. =head2 Handling Cookies You are encouraged to install L and use L as your cookie jar. L provides a better security model matching that of current Web browsers when L is installed. use HTTP::CookieJar::LWP (); my $jar = HTTP::CookieJar::LWP->new; my $ua = LWP::UserAgent->new( cookie_jar => $jar ); See L for more information. =head2 Managing Protocols C gives you the ability to allow arbitrary protocols. my $ua = LWP::UserAgent->new( protocols_allowed => [ 'http', 'https' ] ); This will prevent you from inadvertently following URLs like C. See L. C gives you the ability to deny arbitrary protocols. my $ua = LWP::UserAgent->new( protocols_forbidden => [ 'file', 'mailto', 'ssh', ] ); This can also prevent you from inadvertently following URLs like C. See L. =head1 SEE ALSO See L for a complete overview of libwww-perl5. See L and the scripts F and F for examples of usage. See L and L for a description of the message objects dispatched and received. See L and L for other ways to build request objects. See L and L for examples of more specialized user agents based on L. =head1 COPYRIGHT AND LICENSE Copyright 1995-2009 Gisle Aas. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/LWP/Protocol.pm000044400000021477152462503210010405 0ustar00package LWP::Protocol; use parent 'LWP::MemberMixin'; our $VERSION = '6.58'; use strict; use Carp (); use HTTP::Status (); use HTTP::Response (); use Try::Tiny qw(try catch); my %ImplementedBy = (); # scheme => classname sub new { my($class, $scheme, $ua) = @_; my $self = bless { scheme => $scheme, ua => $ua, # historical/redundant max_size => $ua->{max_size}, }, $class; $self; } sub create { my($scheme, $ua) = @_; my $impclass = LWP::Protocol::implementor($scheme) or Carp::croak("Protocol scheme '$scheme' is not supported"); # hand-off to scheme specific implementation sub-class my $protocol = $impclass->new($scheme, $ua); return $protocol; } sub implementor { my($scheme, $impclass) = @_; if ($impclass) { $ImplementedBy{$scheme} = $impclass; } my $ic = $ImplementedBy{$scheme}; return $ic if $ic; return '' unless $scheme =~ /^([.+\-\w]+)$/; # check valid URL schemes $scheme = $1; # untaint $scheme =~ tr/.+-/_/; # make it a legal module name # scheme not yet known, look for a 'use'd implementation $ic = "LWP::Protocol::$scheme"; # default location $ic = "LWP::Protocol::nntp" if $scheme eq 'news'; #XXX ugly hack no strict 'refs'; # check we actually have one for the scheme: unless (@{"${ic}::ISA"}) { # try to autoload it try { (my $class = $ic) =~ s{::}{/}g; $class .= '.pm' unless $class =~ /\.pm$/; require $class; } catch { my $error = $_; if ($error =~ /Can't locate/) { $ic = ''; } else { die "$error\n"; } }; } $ImplementedBy{$scheme} = $ic if $ic; $ic; } sub request { my($self, $request, $proxy, $arg, $size, $timeout) = @_; Carp::croak('LWP::Protocol::request() needs to be overridden in subclasses'); } # legacy sub timeout { shift->_elem('timeout', @_); } sub max_size { shift->_elem('max_size', @_); } sub collect { my ($self, $arg, $response, $collector) = @_; my $content; my($ua, $max_size) = @{$self}{qw(ua max_size)}; # This can't be moved to Try::Tiny due to the closures within causing # leaks on any version of Perl prior to 5.18. # https://perl5.git.perl.org/perl.git/commitdiff/a0d2bbd5c my $error = do { #catch local $@; local $\; # protect the print below from surprises eval { # try if (!defined($arg) || !$response->is_success) { $response->{default_add_content} = 1; } elsif (!ref($arg) && length($arg)) { open(my $fh, ">", $arg) or die "Can't write to '$arg': $!"; binmode($fh); push(@{$response->{handlers}{response_data}}, { callback => sub { print $fh $_[3] or die "Can't write to '$arg': $!"; 1; }, }); push(@{$response->{handlers}{response_done}}, { callback => sub { close($fh) or die "Can't write to '$arg': $!"; undef($fh); }, }); } elsif (ref($arg) eq 'CODE') { push(@{$response->{handlers}{response_data}}, { callback => sub { &$arg($_[3], $_[0], $self); 1; }, }); } else { die "Unexpected collect argument '$arg'"; } $ua->run_handlers("response_header", $response); if (delete $response->{default_add_content}) { push(@{$response->{handlers}{response_data}}, { callback => sub { $_[0]->add_content($_[3]); 1; }, }); } my $content_size = 0; my $length = $response->content_length; my %skip_h; while ($content = &$collector, length $$content) { for my $h ($ua->handlers("response_data", $response)) { next if $skip_h{$h}; unless ($h->{callback}->($response, $ua, $h, $$content)) { # XXX remove from $response->{handlers}{response_data} if present $skip_h{$h}++; } } $content_size += length($$content); $ua->progress(($length ? ($content_size / $length) : "tick"), $response); if (defined($max_size) && $content_size > $max_size) { $response->push_header("Client-Aborted", "max_size"); last; } } 1; }; $@; }; if ($error) { chomp($error); $response->push_header('X-Died' => $error); $response->push_header("Client-Aborted", "die"); }; delete $response->{handlers}{response_data}; delete $response->{handlers} unless %{$response->{handlers}}; return $response; } sub collect_once { my($self, $arg, $response) = @_; my $content = \ $_[3]; my $first = 1; $self->collect($arg, $response, sub { return $content if $first--; return \ ""; }); } 1; __END__ =pod =head1 NAME LWP::Protocol - Base class for LWP protocols =head1 SYNOPSIS package LWP::Protocol::foo; use parent qw(LWP::Protocol); =head1 DESCRIPTION This class is used as the base class for all protocol implementations supported by the LWP library. When creating an instance of this class using C, and you get an initialized subclass appropriate for that access method. In other words, the L function calls the constructor for one of its subclasses. All derived C classes need to override the C method which is used to service a request. The overridden method can make use of the C method to collect together chunks of data as it is received. =head1 METHODS The following methods and functions are provided: =head2 new my $prot = LWP::Protocol->new(); The LWP::Protocol constructor is inherited by subclasses. As this is a virtual base class this method should B be called directly. =head2 create my $prot = LWP::Protocol::create($scheme) Create an object of the class implementing the protocol to handle the given scheme. This is a function, not a method. It is more an object factory than a constructor. This is the function user agents should use to access protocols. =head2 implementor my $class = LWP::Protocol::implementor($scheme, [$class]) Get and/or set implementor class for a scheme. Returns C<''> if the specified scheme is not supported. =head2 request $response = $protocol->request($request, $proxy, undef); $response = $protocol->request($request, $proxy, '/tmp/sss'); $response = $protocol->request($request, $proxy, \&callback, 1024); Dispatches a request over the protocol, and returns a response object. This method needs to be overridden in subclasses. Refer to L for description of the arguments. =head2 collect my $res = $prot->collect(undef, $response, $collector); # stored in $response my $res = $prot->collect($filename, $response, $collector); my $res = $prot->collect(sub { ... }, $response, $collector); Collect the content of a request, and process it appropriately into a scalar, file, or by calling a callback. If the first parameter is undefined, then the content is stored within the C<$response>. If it's a simple scalar, then it's interpreted as a file name and the content is written to this file. If it's a code reference, then content is passed to this routine. The collector is a routine that will be called and which is responsible for returning pieces (as ref to scalar) of the content to process. The C<$collector> signals C by returning a reference to an empty string. The return value is the L object reference. B We will only use the callback or file argument if C<< $response->is_success() >>. This avoids sending content data for redirects and authentication responses to the callback which would be confusing. =head2 collect_once $prot->collect_once($arg, $response, $content) Can be called when the whole response content is available as content. This will invoke L with a collector callback that returns a reference to C<$content> the first time and an empty string the next. =head1 SEE ALSO Inspect the F and F files for examples of usage. =head1 COPYRIGHT Copyright 1995-2001 Gisle Aas. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/LWP/Simple.pm000044400000014626152462503210010033 0ustar00package LWP::Simple; use strict; our $VERSION = '6.58'; require Exporter; our @EXPORT = qw(get head getprint getstore mirror); our @EXPORT_OK = qw($ua); # I really hate this. It was a bad idea to do it in the first place. # Wonder how to get rid of it??? (It even makes LWP::Simple 7% slower # for trivial tests) use HTTP::Status; push(@EXPORT, @HTTP::Status::EXPORT); sub import { my $pkg = shift; my $callpkg = caller; Exporter::export($pkg, $callpkg, @_); } use LWP::UserAgent (); use HTTP::Date (); our $ua = LWP::UserAgent->new; # we create a global UserAgent object $ua->agent("LWP::Simple/$VERSION "); $ua->env_proxy; sub get ($) { my $response = $ua->get(shift); return $response->decoded_content if $response->is_success; return undef; } sub head ($) { my($url) = @_; my $request = HTTP::Request->new(HEAD => $url); my $response = $ua->request($request); if ($response->is_success) { return $response unless wantarray; return (scalar $response->header('Content-Type'), scalar $response->header('Content-Length'), HTTP::Date::str2time($response->header('Last-Modified')), HTTP::Date::str2time($response->header('Expires')), scalar $response->header('Server'), ); } return; } sub getprint ($) { my($url) = @_; my $request = HTTP::Request->new(GET => $url); local($\) = ""; # ensure standard $OUTPUT_RECORD_SEPARATOR my $callback = sub { print $_[0] }; if ($^O eq "MacOS") { $callback = sub { $_[0] =~ s/\015?\012/\n/g; print $_[0] } } my $response = $ua->request($request, $callback); unless ($response->is_success) { print STDERR $response->status_line, " \n"; } $response->code; } sub getstore ($$) { my($url, $file) = @_; my $request = HTTP::Request->new(GET => $url); my $response = $ua->request($request, $file); $response->code; } sub mirror ($$) { my($url, $file) = @_; my $response = $ua->mirror($url, $file); $response->code; } 1; __END__ =pod =head1 NAME LWP::Simple - simple procedural interface to LWP =head1 SYNOPSIS perl -MLWP::Simple -e 'getprint "http://www.sn.no"' use LWP::Simple; $content = get("http://www.sn.no/"); die "Couldn't get it!" unless defined $content; if (mirror("http://www.sn.no/", "foo") == RC_NOT_MODIFIED) { ... } if (is_success(getprint("http://www.sn.no/"))) { ... } =head1 DESCRIPTION This module is meant for people who want a simplified view of the libwww-perl library. It should also be suitable for one-liners. If you need more control or access to the header fields in the requests sent and responses received, then you should use the full object-oriented interface provided by the L module. The module will also export the L object as C<$ua> if you ask for it explicitly. The user agent created by this module will identify itself as C and will initialize its proxy defaults from the environment (by calling C<< $ua->env_proxy >>). =head1 FUNCTIONS The following functions are provided (and exported) by this module: =head2 get my $res = get($url); The get() function will fetch the document identified by the given URL and return it. It returns C if it fails. The C<$url> argument can be either a string or a reference to a L object. You will not be able to examine the response code or response headers (like C) when you are accessing the web using this function. If you need that information you should use the full OO interface (see L). =head2 head my $res = head($url); Get document headers. Returns the following 5 values if successful: ($content_type, $document_length, $modified_time, $expires, $server) Returns an empty list if it fails. In scalar context returns TRUE if successful. =head2 getprint my $code = getprint($url); Get and print a document identified by a URL. The document is printed to the selected default filehandle for output (normally STDOUT) as data is received from the network. If the request fails, then the status code and message are printed on STDERR. The return value is the HTTP response code. =head2 getstore my $code = getstore($url, $file) Gets a document identified by a URL and stores it in the file. The return value is the HTTP response code. =head2 mirror my $code = mirror($url, $file); Get and store a document identified by a URL, using I, and checking the I. Returns the HTTP response code. =head1 STATUS CONSTANTS This module also exports the L constants and procedures. You can use them when you check the response code from L, L or L. The constants are: RC_CONTINUE RC_SWITCHING_PROTOCOLS RC_OK RC_CREATED RC_ACCEPTED RC_NON_AUTHORITATIVE_INFORMATION RC_NO_CONTENT RC_RESET_CONTENT RC_PARTIAL_CONTENT RC_MULTIPLE_CHOICES RC_MOVED_PERMANENTLY RC_MOVED_TEMPORARILY RC_SEE_OTHER RC_NOT_MODIFIED RC_USE_PROXY RC_BAD_REQUEST RC_UNAUTHORIZED RC_PAYMENT_REQUIRED RC_FORBIDDEN RC_NOT_FOUND RC_METHOD_NOT_ALLOWED RC_NOT_ACCEPTABLE RC_PROXY_AUTHENTICATION_REQUIRED RC_REQUEST_TIMEOUT RC_CONFLICT RC_GONE RC_LENGTH_REQUIRED RC_PRECONDITION_FAILED RC_REQUEST_ENTITY_TOO_LARGE RC_REQUEST_URI_TOO_LARGE RC_UNSUPPORTED_MEDIA_TYPE RC_INTERNAL_SERVER_ERROR RC_NOT_IMPLEMENTED RC_BAD_GATEWAY RC_SERVICE_UNAVAILABLE RC_GATEWAY_TIMEOUT RC_HTTP_VERSION_NOT_SUPPORTED =head1 CLASSIFICATION FUNCTIONS The L classification functions are: =head2 is_success my $bool = is_success($rc); True if response code indicated a successful request. =head2 is_error my $bool = is_error($rc) True if response code indicated that an error occurred. =head1 CAVEAT Note that if you are using both LWP::Simple and the very popular L module, you may be importing a C function from each module, producing a warning like C. Get around this problem by just not importing LWP::Simple's C function, like so: use LWP::Simple qw(!head); use CGI qw(:standard); # then only CGI.pm defines a head() Then if you do need LWP::Simple's C function, you can just call it as C. =head1 SEE ALSO L, L, L, L, L, L =cut perl5/LWP/Authen/Ntlm.pm000044400000012426152462503210010734 0ustar00package LWP::Authen::Ntlm; use strict; our $VERSION = '6.58'; use Authen::NTLM "1.02"; use MIME::Base64 "2.12"; sub authenticate { my($class, $ua, $proxy, $auth_param, $response, $request, $arg, $size) = @_; my($user, $pass) = $ua->get_basic_credentials($auth_param->{realm}, $request->uri, $proxy); unless(defined $user and defined $pass) { return $response; } if (!$ua->conn_cache()) { warn "The keep_alive option must be enabled for NTLM authentication to work. NTLM authentication aborted.\n"; return $response; } my($domain, $username) = split(/\\/, $user); ntlm_domain($domain); ntlm_user($username); ntlm_password($pass); my $auth_header = $proxy ? "Proxy-Authorization" : "Authorization"; # my ($challenge) = $response->header('WWW-Authenticate'); my $challenge; foreach ($response->header('WWW-Authenticate')) { last if /^NTLM/ && ($challenge=$_); } if ($challenge eq 'NTLM') { # First phase, send handshake my $auth_value = "NTLM " . ntlm(); ntlm_reset(); # Need to check this isn't a repeated fail! my $r = $response; my $retry_count = 0; while ($r) { my $auth = $r->request->header($auth_header); ++$retry_count if ($auth && $auth eq $auth_value); if ($retry_count > 2) { # here we know this failed before $response->header("Client-Warning" => "Credentials for '$user' failed before"); return $response; } $r = $r->previous; } my $referral = $request->clone; $referral->header($auth_header => $auth_value); return $ua->request($referral, $arg, $size, $response); } else { # Second phase, use the response challenge (unless non-401 code # was returned, in which case, we just send back the response # object, as is my $auth_value; if ($response->code ne '401') { return $response; } else { my $challenge; foreach ($response->header('WWW-Authenticate')) { last if /^NTLM/ && ($challenge=$_); } $challenge =~ s/^NTLM //; ntlm(); $auth_value = "NTLM " . ntlm($challenge); ntlm_reset(); } my $referral = $request->clone; $referral->header($auth_header => $auth_value); my $response2 = $ua->request($referral, $arg, $size, $response); return $response2; } } 1; __END__ =pod =head1 NAME LWP::Authen::Ntlm - Library for enabling NTLM authentication (Microsoft) in LWP =head1 SYNOPSIS use LWP::UserAgent; use HTTP::Request::Common; my $url = 'http://www.company.com/protected_page.html'; # Set up the ntlm client and then the base64 encoded ntlm handshake message my $ua = LWP::UserAgent->new(keep_alive=>1); $ua->credentials('www.company.com:80', '', "MyDomain\\MyUserCode", 'MyPassword'); $request = GET $url; print "--Performing request now...-----------\n"; $response = $ua->request($request); print "--Done with request-------------------\n"; if ($response->is_success) {print "It worked!->" . $response->code . "\n"} else {print "It didn't work!->" . $response->code . "\n"} =head1 DESCRIPTION L allows LWP to authenticate against servers that are using the NTLM authentication scheme popularized by Microsoft. This type of authentication is common on intranets of Microsoft-centric organizations. The module takes advantage of the Authen::NTLM module by Mark Bush. Since there is also another Authen::NTLM module available from CPAN by Yee Man Chan with an entirely different interface, it is necessary to ensure that you have the correct NTLM module. In addition, there have been problems with incompatibilities between different versions of L, which Bush's L makes use of. Therefore, it is necessary to ensure that your Mime::Base64 module supports exporting of the C and C functions. =head1 USAGE The module is used indirectly through LWP, rather than including it directly in your code. The LWP system will invoke the NTLM authentication when it encounters the authentication scheme while attempting to retrieve a URL from a server. In order for the NTLM authentication to work, you must have a few things set up in your code prior to attempting to retrieve the URL: =over 4 =item * Enable persistent HTTP connections To do this, pass the C<< "keep_alive=>1" >> option to the L when creating it, like this: my $ua = LWP::UserAgent->new(keep_alive=>1); =item * Set the credentials on the UserAgent object The credentials must be set like this: $ua->credentials('www.company.com:80', '', "MyDomain\\MyUserCode", 'MyPassword'); Note that you cannot use the L object's C method to set the credentials. Note, too, that the C<'www.company.com:80'> portion only sets credentials on the specified port AND it is case-sensitive (this is due to the way LWP is coded, and has nothing to do with LWP::Authen::Ntlm) =back =head1 AVAILABILITY General queries regarding LWP should be made to the LWP Mailing List. Questions specific to LWP::Authen::Ntlm can be forwarded to jtillman@bigfoot.com =head1 COPYRIGHT Copyright (c) 2002 James Tillman. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L, L. =cut perl5/LWP/Authen/Basic.pm000044400000005074152462503210011044 0ustar00package LWP::Authen::Basic; use strict; our $VERSION = '6.58'; require Encode; require MIME::Base64; sub auth_header { my($class, $user, $pass, $request, $ua, $h) = @_; my $userpass = "$user:$pass"; # https://tools.ietf.org/html/rfc7617#section-2.1 my $charset = uc($h->{auth_param}->{charset} || ""); $userpass = Encode::encode($charset, $userpass) if ($charset eq "UTF-8"); return "Basic " . MIME::Base64::encode($userpass, ""); } sub _reauth_requested { return 0; } sub authenticate { my($class, $ua, $proxy, $auth_param, $response, $request, $arg, $size) = @_; my $realm = $auth_param->{realm} || ""; my $url = $proxy ? $request->{proxy} : $request->uri_canonical; return $response unless $url; my $host_port = $url->host_port; my $auth_header = $proxy ? "Proxy-Authorization" : "Authorization"; my @m = $proxy ? (m_proxy => $url) : (m_host_port => $host_port); push(@m, realm => $realm); my $h = $ua->get_my_handler("request_prepare", @m, sub { $_[0]{callback} = sub { my($req, $ua, $h) = @_; my($user, $pass) = $ua->credentials($host_port, $h->{realm}); if (defined $user) { my $auth_value = $class->auth_header($user, $pass, $req, $ua, $h); $req->header($auth_header => $auth_value); } }; }); $h->{auth_param} = $auth_param; my $reauth_requested = $class->_reauth_requested($auth_param, $ua, $request, $auth_header); if ( !$proxy && (!$request->header($auth_header) || $reauth_requested) && $ua->credentials($host_port, $realm)) { # we can make sure this handler applies and retry add_path($h, $url->path) unless $reauth_requested; # Do not clobber up path list for retries return $ua->request($request->clone, $arg, $size, $response); } my($user, $pass) = $ua->get_basic_credentials($realm, $url, $proxy); unless (defined $user and defined $pass) { $ua->set_my_handler("request_prepare", undef, @m); # delete handler return $response; } # check that the password has changed my ($olduser, $oldpass) = $ua->credentials($host_port, $realm); return $response if (defined $olduser and defined $oldpass and $user eq $olduser and $pass eq $oldpass); $ua->credentials($host_port, $realm, $user, $pass); add_path($h, $url->path) unless $proxy; return $ua->request($request->clone, $arg, $size, $response); } sub add_path { my($h, $path) = @_; $path =~ s,[^/]+\z,,; push(@{$h->{m_path_prefix}}, $path); } 1; perl5/LWP/Authen/Digest.pm000044400000004177152462503210011245 0ustar00package LWP::Authen::Digest; use strict; use parent 'LWP::Authen::Basic'; our $VERSION = '6.58'; require Digest::MD5; sub _reauth_requested { my ($class, $auth_param, $ua, $request, $auth_header) = @_; my $ret = defined($$auth_param{stale}) && lc($$auth_param{stale}) eq 'true'; if ($ret) { my $hdr = $request->header($auth_header); $hdr =~ tr/,/;/; # "," is used to separate auth-params!! ($hdr) = HTTP::Headers::Util::split_header_words($hdr); my $nonce = {@$hdr}->{nonce}; delete $$ua{authen_md5_nonce_count}{$nonce}; } return $ret; } sub auth_header { my($class, $user, $pass, $request, $ua, $h) = @_; my $auth_param = $h->{auth_param}; my $nc = sprintf "%08X", ++$ua->{authen_md5_nonce_count}{$auth_param->{nonce}}; my $cnonce = sprintf "%8x", time; my $uri = $request->uri->path_query; $uri = "/" unless length $uri; my $md5 = Digest::MD5->new; my(@digest); $md5->add(join(":", $user, $auth_param->{realm}, $pass)); push(@digest, $md5->hexdigest); $md5->reset; push(@digest, $auth_param->{nonce}); if ($auth_param->{qop}) { push(@digest, $nc, $cnonce, ($auth_param->{qop} =~ m|^auth[,;]auth-int$|) ? 'auth' : $auth_param->{qop}); } $md5->add(join(":", $request->method, $uri)); push(@digest, $md5->hexdigest); $md5->reset; $md5->add(join(":", @digest)); my($digest) = $md5->hexdigest; $md5->reset; my %resp = map { $_ => $auth_param->{$_} } qw(realm nonce opaque); @resp{qw(username uri response algorithm)} = ($user, $uri, $digest, "MD5"); if (($auth_param->{qop} || "") =~ m|^auth([,;]auth-int)?$|) { @resp{qw(qop cnonce nc)} = ("auth", $cnonce, $nc); } my(@order) = qw(username realm qop algorithm uri nonce nc cnonce response opaque); my @pairs; for (@order) { next unless defined $resp{$_}; # RFC2617 says that qop-value and nc-value should be unquoted. if ( $_ eq 'qop' || $_ eq 'nc' ) { push(@pairs, "$_=" . $resp{$_}); } else { push(@pairs, "$_=" . qq("$resp{$_}")); } } my $auth_value = "Digest " . join(", ", @pairs); return $auth_value; } 1; perl5/LWP/Debug.pm000044400000005542152462503210007625 0ustar00package LWP::Debug; # legacy our $VERSION = '6.58'; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw(level trace debug conns); use Carp (); my @levels = qw(trace debug conns); our %current_level = (); sub import { my $pack = shift; my $callpkg = caller(0); my @symbols = (); my @levels = (); for (@_) { if (/^[-+]/) { push(@levels, $_); } else { push(@symbols, $_); } } Exporter::export($pack, $callpkg, @symbols); level(@levels); } sub level { for (@_) { if ($_ eq '+') { # all on # switch on all levels %current_level = map { $_ => 1 } @levels; } elsif ($_ eq '-') { # all off %current_level = (); } elsif (/^([-+])(\w+)$/) { $current_level{$2} = $1 eq '+'; } else { Carp::croak("Illegal level format $_"); } } } sub trace { _log(@_) if $current_level{'trace'}; } sub debug { _log(@_) if $current_level{'debug'}; } sub conns { _log(@_) if $current_level{'conns'}; } sub _log { my $msg = shift; $msg .= "\n" unless $msg =~ /\n$/; # ensure trailing "\n" my ($package, $filename, $line, $sub) = caller(2); print STDERR "$sub: $msg"; } 1; __END__ =pod =head1 NAME LWP::Debug - deprecated =head1 DESCRIPTION This module has been deprecated. Please see L for your debugging needs. LWP::Debug is used to provide tracing facilities, but these are not used by LWP any more. The code in this module is kept around (undocumented) so that 3rd party code that happens to use the old interfaces continue to run. One useful feature that LWP::Debug provided (in an imprecise and troublesome way) was network traffic monitoring. The following section provides some hints about recommended replacements. =head2 Network traffic monitoring The best way to monitor the network traffic that LWP generates is to use an external TCP monitoring program. The L program is highly recommended for this. Another approach it to use a debugging HTTP proxy server and make LWP direct all its traffic via this one. Call C<< $ua->proxy >> to set it up and then just use LWP as before. For less precise monitoring needs just setting up a few simple handlers might do. The following example sets up handlers to dump the request and response objects that pass through LWP: use LWP::UserAgent; $ua = LWP::UserAgent->new; $ua->default_header('Accept-Encoding' => scalar HTTP::Message::decodable()); $ua->add_handler("request_send", sub { shift->dump; return }); $ua->add_handler("response_done", sub { shift->dump; return }); $ua->get("http://www.example.com"); =head1 SEE ALSO L, L, L =cut perl5/LWP/MemberMixin.pm000044400000001555152462503210011013 0ustar00package LWP::MemberMixin; our $VERSION = '6.58'; sub _elem { my $self = shift; my $elem = shift; my $old = $self->{$elem}; $self->{$elem} = shift if @_; return $old; } 1; __END__ =pod =head1 NAME LWP::MemberMixin - Member access mixin class =head1 SYNOPSIS package Foo; use parent qw(LWP::MemberMixin); =head1 DESCRIPTION A mixin class to get methods that provide easy access to member variables in the C<%$self>. Ideally there should be better Perl language support for this. =head1 METHODS There is only one method provided: =head2 _elem _elem($elem [, $val]) Internal method to get/set the value of member variable C<$elem>. If C<$val> is present it is used as the new value for the member variable. If it is not present the current value is not touched. In both cases the previous value of the member variable is returned. =cut perl5/LWP/DebugFile.pm000044400000000103152462503210010411 0ustar00package LWP::DebugFile; our $VERSION = '6.58'; # legacy stub 1; perl5/LWP/RobotUA.pm000044400000017323152462503210010112 0ustar00package LWP::RobotUA; use parent qw(LWP::UserAgent); our $VERSION = '6.58'; require WWW::RobotRules; require HTTP::Request; require HTTP::Response; use Carp (); use HTTP::Status (); use HTTP::Date qw(time2str); use strict; # # Additional attributes in addition to those found in LWP::UserAgent: # # $self->{'delay'} Required delay between request to the same # server in minutes. # # $self->{'rules'} A WWW::RobotRules object # sub new { my $class = shift; my %cnf; if (@_ < 4) { # legacy args @cnf{qw(agent from rules)} = @_; } else { %cnf = @_; } Carp::croak('LWP::RobotUA agent required') unless $cnf{agent}; Carp::croak('LWP::RobotUA from address required') unless $cnf{from} && $cnf{from} =~ m/\@/; my $delay = delete $cnf{delay} || 1; my $use_sleep = delete $cnf{use_sleep}; $use_sleep = 1 unless defined($use_sleep); my $rules = delete $cnf{rules}; my $self = LWP::UserAgent->new(%cnf); $self = bless $self, $class; $self->{'delay'} = $delay; # minutes $self->{'use_sleep'} = $use_sleep; if ($rules) { $rules->agent($cnf{agent}); $self->{'rules'} = $rules; } else { $self->{'rules'} = WWW::RobotRules->new($cnf{agent}); } $self; } sub delay { shift->_elem('delay', @_); } sub use_sleep { shift->_elem('use_sleep', @_); } sub agent { my $self = shift; my $old = $self->SUPER::agent(@_); if (@_) { # Changing our name means to start fresh $self->{'rules'}->agent($self->{'agent'}); } $old; } sub rules { my $self = shift; my $old = $self->_elem('rules', @_); $self->{'rules'}->agent($self->{'agent'}) if @_; $old; } sub no_visits { my($self, $netloc) = @_; $self->{'rules'}->no_visits($netloc) || 0; } *host_count = \&no_visits; # backwards compatibility with LWP-5.02 sub host_wait { my($self, $netloc) = @_; return undef unless defined $netloc; my $last = $self->{'rules'}->last_visit($netloc); if ($last) { my $wait = int($self->{'delay'} * 60 - (time - $last)); $wait = 0 if $wait < 0; return $wait; } return 0; } sub simple_request { my($self, $request, $arg, $size) = @_; # Do we try to access a new server? my $allowed = $self->{'rules'}->allowed($request->uri); if ($allowed < 0) { # Host is not visited before, or robots.txt expired; fetch "robots.txt" my $robot_url = $request->uri->clone; $robot_url->path("robots.txt"); $robot_url->query(undef); # make access to robot.txt legal since this will be a recursive call $self->{'rules'}->parse($robot_url, ""); my $robot_req = HTTP::Request->new('GET', $robot_url); my $parse_head = $self->parse_head(0); my $robot_res = $self->request($robot_req); $self->parse_head($parse_head); my $fresh_until = $robot_res->fresh_until; my $content = ""; if ($robot_res->is_success && $robot_res->content_is_text) { $content = $robot_res->decoded_content; $content = "" unless $content && $content =~ /^\s*Disallow\s*:/mi; } $self->{'rules'}->parse($robot_url, $content, $fresh_until); # recalculate allowed... $allowed = $self->{'rules'}->allowed($request->uri); } # Check rules unless ($allowed) { my $res = HTTP::Response->new( HTTP::Status::RC_FORBIDDEN, 'Forbidden by robots.txt'); $res->request( $request ); # bind it to that request return $res; } my $netloc = eval { local $SIG{__DIE__}; $request->uri->host_port; }; my $wait = $self->host_wait($netloc); if ($wait) { if ($self->{'use_sleep'}) { sleep($wait) } else { my $res = HTTP::Response->new( HTTP::Status::RC_SERVICE_UNAVAILABLE, 'Please, slow down'); $res->header('Retry-After', time2str(time + $wait)); $res->request( $request ); # bind it to that request return $res; } } # Perform the request my $res = $self->SUPER::simple_request($request, $arg, $size); $self->{'rules'}->visit($netloc); $res; } sub as_string { my $self = shift; my @s; push(@s, "Robot: $self->{'agent'} operated by $self->{'from'} [$self]"); push(@s, " Minimum delay: " . int($self->{'delay'}*60) . "s"); push(@s, " Will sleep if too early") if $self->{'use_sleep'}; push(@s, " Rules = $self->{'rules'}"); join("\n", @s, ''); } 1; __END__ =pod =head1 NAME LWP::RobotUA - a class for well-behaved Web robots =head1 SYNOPSIS use LWP::RobotUA; my $ua = LWP::RobotUA->new('my-robot/0.1', 'me@foo.com'); $ua->delay(10); # be very nice -- max one hit every ten minutes! ... # Then just use it just like a normal LWP::UserAgent: my $response = $ua->get('http://whatever.int/...'); ... =head1 DESCRIPTION This class implements a user agent that is suitable for robot applications. Robots should be nice to the servers they visit. They should consult the F file to ensure that they are welcomed and they should not make requests too frequently. But before you consider writing a robot, take a look at L. When you use an I object as your user agent, then you do not really have to think about these things yourself; C files are automatically consulted and obeyed, the server isn't queried too rapidly, and so on. Just send requests as you do when you are using a normal I object (using C<< $ua->get(...) >>, C<< $ua->head(...) >>, C<< $ua->request(...) >>, etc.), and this special agent will make sure you are nice. =head1 METHODS The LWP::RobotUA is a sub-class of L and implements the same methods. In addition the following methods are provided: =head2 new my $ua = LWP::RobotUA->new( %options ) my $ua = LWP::RobotUA->new( $agent, $from ) my $ua = LWP::RobotUA->new( $agent, $from, $rules ) The LWP::UserAgent options C and C are mandatory. The options C, C and C initialize attributes private to the RobotUA. If C are not provided, then L is instantiated providing an internal database of F. It is also possible to just pass the value of C, C and optionally C as plain positional arguments. =head2 delay my $delay = $ua->delay; $ua->delay( $minutes ); Get/set the minimum delay between requests to the same server, in I. The default is C<1> minute. Note that this number doesn't have to be an integer; for example, this sets the delay to C<10> seconds: $ua->delay(10/60); =head2 use_sleep my $bool = $ua->use_sleep; $ua->use_sleep( $boolean ); Get/set a value indicating whether the UA should L if requests arrive too fast, defined as C<< $ua->delay >> minutes not passed since last request to the given server. The default is true. If this value is false then an internal C response will be generated. It will have a C header that indicates when it is OK to send another request to this server. =head2 rules my $rules = $ua->rules; $ua->rules( $rules ); Set/get which I object to use. =head2 no_visits my $num = $ua->no_visits( $netloc ) Returns the number of documents fetched from this server host. Yeah I know, this method should probably have been named C or something like that. :-( =head2 host_wait my $num = $ua->host_wait( $netloc ) Returns the number of I (from now) you must wait before you can make a new request to this host. =head2 as_string my $string = $ua->as_string; Returns a string that describes the state of the UA. Mainly useful for debugging. =head1 SEE ALSO L, L =head1 COPYRIGHT Copyright 1996-2004 Gisle Aas. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/LWP/Protocol/nntp.pm000044400000010146152462503210011353 0ustar00package LWP::Protocol::nntp; # Implementation of the Network News Transfer Protocol (RFC 977) use parent qw(LWP::Protocol); our $VERSION = '6.58'; require HTTP::Response; require HTTP::Status; require Net::NNTP; use strict; sub request { my ($self, $request, $proxy, $arg, $size, $timeout) = @_; $size = 4096 unless $size; # Check for proxy if (defined $proxy) { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'You can not proxy through NNTP'); } # Check that the scheme is as expected my $url = $request->uri; my $scheme = $url->scheme; unless ($scheme eq 'news' || $scheme eq 'nntp') { return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR, "LWP::Protocol::nntp::request called for '$scheme'"); } # check for a valid method my $method = $request->method; unless ($method eq 'GET' || $method eq 'HEAD' || $method eq 'POST') { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for '$scheme:' URLs"); } # extract the identifier and check against posting to an article my $groupart = $url->_group; my $is_art = $groupart =~ /@/; if ($is_art && $method eq 'POST') { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, "Can't post to an article <$groupart>"); } my $nntp = Net::NNTP->new( $url->host, #Port => 18574, Timeout => $timeout, #Debug => 1, ); die "Can't connect to nntp server" unless $nntp; # Check the initial welcome message from the NNTP server if ($nntp->status != 2) { return HTTP::Response->new(HTTP::Status::RC_SERVICE_UNAVAILABLE, $nntp->message); } my $response = HTTP::Response->new(HTTP::Status::RC_OK, "OK"); my $mess = $nntp->message; # Try to extract server name from greeting message. # Don't know if this works well for a large class of servers, but # this works for our server. $mess =~ s/\s+ready\b.*//; $mess =~ s/^\S+\s+//; $response->header(Server => $mess); # First we handle posting of articles if ($method eq 'POST') { $nntp->quit; $nntp = undef; $response->code(HTTP::Status::RC_NOT_IMPLEMENTED); $response->message("POST not implemented yet"); return $response; } # The method must be "GET" or "HEAD" by now if (!$is_art) { if (!$nntp->group($groupart)) { $response->code(HTTP::Status::RC_NOT_FOUND); $response->message($nntp->message); } $nntp->quit; $nntp = undef; # HEAD: just check if the group exists if ($method eq 'GET' && $response->is_success) { $response->code(HTTP::Status::RC_NOT_IMPLEMENTED); $response->message("GET newsgroup not implemented yet"); } return $response; } # Send command to server to retrieve an article (or just the headers) my $get = $method eq 'HEAD' ? "head" : "article"; my $art = $nntp->$get("<$groupart>"); unless ($art) { $nntp->quit; $response->code(HTTP::Status::RC_NOT_FOUND); $response->message($nntp->message); $nntp = undef; return $response; } # Parse headers my ($key, $val); local $_; while ($_ = shift @$art) { if (/^\s+$/) { last; # end of headers } elsif (/^(\S+):\s*(.*)/) { $response->push_header($key, $val) if $key; ($key, $val) = ($1, $2); } elsif (/^\s+(.*)/) { next unless $key; $val .= $1; } else { unshift(@$art, $_); last; } } $response->push_header($key, $val) if $key; # Ensure that there is a Content-Type header $response->header("Content-Type", "text/plain") unless $response->header("Content-Type"); # Collect the body $response = $self->collect_once($arg, $response, join("", @$art)) if @$art; # Say goodbye to the server $nntp->quit; $nntp = undef; $response; } 1; perl5/LWP/Protocol/ftp.pm000044400000045310152462503210011166 0ustar00package LWP::Protocol::ftp; # Implementation of the ftp protocol (RFC 959). We let the Net::FTP # package do all the dirty work. use parent qw(LWP::Protocol); use strict; our $VERSION = '6.58'; use Carp (); use HTTP::Status (); use HTTP::Negotiate (); use HTTP::Response (); use LWP::MediaTypes (); use File::Listing (); { package # hide from PAUSE LWP::Protocol::MyFTP; use strict; use parent qw(Net::FTP); sub new { my $class = shift; my $self = $class->SUPER::new(@_) || return undef; my $mess = $self->message; # welcome message $mess =~ s|\n.*||s; # only first line left $mess =~ s|\s*ready\.?$||; # Make the version number more HTTP like $mess =~ s|\s*\(Version\s*|/| and $mess =~ s|\)$||; ${*$self}{myftp_server} = $mess; #$response->header("Server", $mess); $self; } sub http_server { my $self = shift; ${*$self}{myftp_server}; } sub home { my $self = shift; my $old = ${*$self}{myftp_home}; if (@_) { ${*$self}{myftp_home} = shift; } $old; } sub go_home { my $self = shift; $self->cwd(${*$self}{myftp_home}); } sub request_count { my $self = shift; ++${*$self}{myftp_reqcount}; } sub ping { my $self = shift; return $self->go_home; } } sub _connect { my ($self, $host, $port, $user, $account, $password, $timeout) = @_; my $key; my $conn_cache = $self->{ua}{conn_cache}; if ($conn_cache) { $key = "$host:$port:$user"; $key .= ":$account" if defined($account); if (my $ftp = $conn_cache->withdraw("ftp", $key)) { if ($ftp->ping) { # save it again $conn_cache->deposit("ftp", $key, $ftp); return $ftp; } } } # try to make a connection my $ftp = LWP::Protocol::MyFTP->new( $host, Port => $port, Timeout => $timeout, LocalAddr => $self->{ua}{local_address}, ); # XXX Should be some what to pass on 'Passive' (header??) unless ($ftp) { $@ =~ s/^Net::FTP: //; return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR, $@); } unless ($ftp->login($user, $password, $account)) { # Unauthorized. Let's fake a RC_UNAUTHORIZED response my $mess = scalar($ftp->message); $mess =~ s/\n$//; my $res = HTTP::Response->new(HTTP::Status::RC_UNAUTHORIZED, $mess); $res->header("Server", $ftp->http_server); $res->header("WWW-Authenticate", qq(Basic Realm="FTP login")); return $res; } my $home = $ftp->pwd; $ftp->home($home); $conn_cache->deposit("ftp", $key, $ftp) if $conn_cache; return $ftp; } sub request { my ($self, $request, $proxy, $arg, $size, $timeout) = @_; $size = 4096 unless $size; # check proxy if (defined $proxy) { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'You can not proxy through the ftp'); } my $url = $request->uri; if ($url->scheme ne 'ftp') { my $scheme = $url->scheme; return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR, "LWP::Protocol::ftp::request called for '$scheme'"); } # check method my $method = $request->method; unless ($method eq 'GET' || $method eq 'HEAD' || $method eq 'PUT') { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'ftp:' URLs"); } my $host = $url->host; my $port = $url->port; my $user = $url->user; my $password = $url->password; # If a basic authorization header is present than we prefer these over # the username/password specified in the URL. { my ($u, $p) = $request->authorization_basic; if (defined $u) { $user = $u; $password = $p; } } # We allow the account to be specified in the "Account" header my $account = $request->header('Account'); my $ftp = $self->_connect($host, $port, $user, $account, $password, $timeout); return $ftp if ref($ftp) eq "HTTP::Response"; # ugh! # Create an initial response object my $response = HTTP::Response->new(HTTP::Status::RC_OK, "OK"); $response->header(Server => $ftp->http_server); $response->header('Client-Request-Num' => $ftp->request_count); $response->request($request); # Get & fix the path my @path = grep {length} $url->path_segments; my $remote_file = pop(@path); $remote_file = '' unless defined $remote_file; my $type; if (ref $remote_file) { my @params; ($remote_file, @params) = @$remote_file; for (@params) { $type = $_ if s/^type=//; } } if ($type && $type eq 'a') { $ftp->ascii; } else { $ftp->binary; } for (@path) { unless ($ftp->cwd($_)) { return HTTP::Response->new(HTTP::Status::RC_NOT_FOUND, "Can't chdir to $_"); } } if ($method eq 'GET' || $method eq 'HEAD') { if (my $mod_time = $ftp->mdtm($remote_file)) { $response->last_modified($mod_time); if (my $ims = $request->if_modified_since) { if ($mod_time <= $ims) { $response->code(HTTP::Status::RC_NOT_MODIFIED); $response->message("Not modified"); return $response; } } } # We'll use this later to abort the transfer if necessary. # if $max_size is defined, we need to abort early. Otherwise, it's # a normal transfer my $max_size = undef; # Set resume location, if the client requested it if ($request->header('Range') && $ftp->supported('REST')) { my $range_info = $request->header('Range'); # Change bytes=2772992-6781209 to just 2772992 my ($start_byte, $end_byte) = $range_info =~ /.*=\s*(\d+)-(\d+)?/; if (defined $start_byte && !defined $end_byte) { # open range -- only the start is specified $ftp->restart($start_byte); # don't define $max_size, we don't want to abort early } elsif (defined $start_byte && defined $end_byte && $start_byte >= 0 && $end_byte >= $start_byte) { $ftp->restart($start_byte); $max_size = $end_byte - $start_byte; } else { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'Incorrect syntax for Range request'); } } elsif ($request->header('Range') && !$ftp->supported('REST')) { return HTTP::Response->new(HTTP::Status::RC_NOT_IMPLEMENTED, "Server does not support resume." ); } my $data; # the data handle if (length($remote_file) and $data = $ftp->retr($remote_file)) { my ($type, @enc) = LWP::MediaTypes::guess_media_type($remote_file); $response->header('Content-Type', $type) if $type; for (@enc) { $response->push_header('Content-Encoding', $_); } my $mess = $ftp->message; if ($mess =~ /\((\d+)\s+bytes\)/) { $response->header('Content-Length', "$1"); } if ($method ne 'HEAD') { # Read data from server $response = $self->collect( $arg, $response, sub { my $content = ''; my $result = $data->read($content, $size); # Stop early if we need to. if (defined $max_size) { # We need an interface to Net::FTP::dataconn for getting # the number of bytes already read my $bytes_received = $data->bytes_read(); # We were already over the limit. (Should only happen # once at the end.) if ($bytes_received - length($content) > $max_size) { $content = ''; } # We just went over the limit elsif ($bytes_received > $max_size) { # Trim content $content = substr($content, 0, $max_size - ($bytes_received - length($content))); } # We're under the limit else { } } return \$content; } ); } # abort is needed for HEAD, it's == close if the transfer has # already completed. unless ($data->abort) { # Something did not work too well. Note that we treat # responses to abort() with code 0 in case of HEAD as ok # (at least wu-ftpd 2.6.1(1) does that). if ($method ne 'HEAD' || $ftp->code != 0) { $response->code(HTTP::Status::RC_INTERNAL_SERVER_ERROR); $response->message("FTP close response: " . $ftp->code . " " . $ftp->message); } } } elsif (!length($remote_file) || ($ftp->code >= 400 && $ftp->code < 600)) { # not a plain file, try to list instead if (length($remote_file) && !$ftp->cwd($remote_file)) { return HTTP::Response->new(HTTP::Status::RC_NOT_FOUND, "File '$remote_file' not found" ); } # It should now be safe to try to list the directory my @lsl = $ftp->dir; # Try to figure out if the user want us to convert the # directory listing to HTML. my @variants = ( ['html', 0.60, 'text/html'], ['dir', 1.00, 'text/ftp-dir-listing'] ); #$HTTP::Negotiate::DEBUG=1; my $prefer = HTTP::Negotiate::choose(\@variants, $request); my $content = ''; if (!defined($prefer)) { return HTTP::Response->new(HTTP::Status::RC_NOT_ACCEPTABLE, "Neither HTML nor directory listing wanted"); } elsif ($prefer eq 'html') { $response->header('Content-Type' => 'text/html'); $content = "File Listing\n"; my $base = $request->uri->clone; my $path = $base->path; $base->path("$path/") unless $path =~ m|/$|; $content .= qq(\n\n); $content .= "\n\n"; } else { $response->header('Content-Type', 'text/ftp-dir-listing'); $content = join("\n", @lsl, ''); } $response->header('Content-Length', length($content)); if ($method ne 'HEAD') { $response = $self->collect_once($arg, $response, $content); } } else { my $res = HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, "FTP return code " . $ftp->code); $res->content_type("text/plain"); $res->content($ftp->message); return $res; } } elsif ($method eq 'PUT') { # method must be PUT unless (length($remote_file)) { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, "Must have a file name to PUT to" ); } my $data; if ($data = $ftp->stor($remote_file)) { my $content = $request->content; my $bytes = 0; if (defined $content) { if (ref($content) eq 'SCALAR') { $bytes = $data->write($$content, length($$content)); } elsif (ref($content) eq 'CODE') { my ($buf, $n); while (length($buf = &$content)) { $n = $data->write($buf, length($buf)); last unless $n; $bytes += $n; } } elsif (!ref($content)) { if (defined $content && length($content)) { $bytes = $data->write($content, length($content)); } } else { die "Bad content"; } } $data->close; $response->code(HTTP::Status::RC_CREATED); $response->header('Content-Type', 'text/plain'); $response->content("$bytes bytes stored as $remote_file on $host\n") } else { my $res = HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, "FTP return code " . $ftp->code); $res->content_type("text/plain"); $res->content($ftp->message); return $res; } } else { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, "Illegal method $method"); } $response; } 1; __END__ # This is what RFC 1738 has to say about FTP access: # -------------------------------------------------- # # 3.2. FTP # # The FTP URL scheme is used to designate files and directories on # Internet hosts accessible using the FTP protocol (RFC959). # # A FTP URL follow the syntax described in Section 3.1. If : is # omitted, the port defaults to 21. # # 3.2.1. FTP Name and Password # # A user name and password may be supplied; they are used in the ftp # "USER" and "PASS" commands after first making the connection to the # FTP server. If no user name or password is supplied and one is # requested by the FTP server, the conventions for "anonymous" FTP are # to be used, as follows: # # The user name "anonymous" is supplied. # # The password is supplied as the Internet e-mail address # of the end user accessing the resource. # # If the URL supplies a user name but no password, and the remote # server requests a password, the program interpreting the FTP URL # should request one from the user. # # 3.2.2. FTP url-path # # The url-path of a FTP URL has the following syntax: # # //...//;type= # # Where through and are (possibly encoded) strings # and is one of the characters "a", "i", or "d". The part # ";type=" may be omitted. The and parts may be # empty. The whole url-path may be omitted, including the "/" # delimiting it from the prefix containing user, password, host, and # port. # # The url-path is interpreted as a series of FTP commands as follows: # # Each of the elements is to be supplied, sequentially, as the # argument to a CWD (change working directory) command. # # If the typecode is "d", perform a NLST (name list) command with # as the argument, and interpret the results as a file # directory listing. # # Otherwise, perform a TYPE command with as the argument, # and then access the file whose name is (for example, using # the RETR command.) # # Within a name or CWD component, the characters "/" and ";" are # reserved and must be encoded. The components are decoded prior to # their use in the FTP protocol. In particular, if the appropriate FTP # sequence to access a particular file requires supplying a string # containing a "/" as an argument to a CWD or RETR command, it is # necessary to encode each "/". # # For example, the URL is # interpreted by FTP-ing to "host.dom", logging in as "myname" # (prompting for a password if it is asked for), and then executing # "CWD /etc" and then "RETR motd". This has a different meaning from # which would "CWD etc" and then # "RETR motd"; the initial "CWD" might be executed relative to the # default directory for "myname". On the other hand, # , would "CWD " with a null # argument, then "CWD etc", and then "RETR motd". # # FTP URLs may also be used for other operations; for example, it is # possible to update a file on a remote file server, or infer # information about it from the directory listings. The mechanism for # doing so is not spelled out here. # # 3.2.3. FTP Typecode is Optional # # The entire ;type= part of a FTP URL is optional. If it is # omitted, the client program interpreting the URL must guess the # appropriate mode to use. In general, the data content type of a file # can only be guessed from the name, e.g., from the suffix of the name; # the appropriate type code to be used for transfer of the file can # then be deduced from the data content of the file. # # 3.2.4 Hierarchy # # For some file systems, the "/" used to denote the hierarchical # structure of the URL corresponds to the delimiter used to construct a # file name hierarchy, and thus, the filename will look similar to the # URL path. This does NOT mean that the URL is a Unix filename. # # 3.2.5. Optimization # # Clients accessing resources via FTP may employ additional heuristics # to optimize the interaction. For some FTP servers, for example, it # may be reasonable to keep the control connection open while accessing # multiple URLs from the same server. However, there is no common # hierarchical model to the FTP protocol, so if a directory change # command has been given, it is impossible in general to deduce what # sequence should be given to navigate to another directory for a # second retrieval, if the paths are different. The only reliable # algorithm is to disconnect and reestablish the control connection. perl5/LWP/Protocol/loopback.pm000044400000001114152462503210012161 0ustar00package LWP::Protocol::loopback; use strict; our $VERSION = '6.58'; require HTTP::Response; use parent qw(LWP::Protocol); sub request { my($self, $request, $proxy, $arg, $size, $timeout) = @_; my $response = HTTP::Response->new(200, "OK"); $response->content_type("message/http; msgtype=request"); $response->header("Via", "loopback/1.0 $proxy") if $proxy; $response->header("X-Arg", $arg); $response->header("X-Read-Size", $size); $response->header("X-Timeout", $timeout); return $self->collect_once($arg, $response, $request->as_string); } 1; perl5/LWP/Protocol/nogo.pm000044400000001144152462503210011334 0ustar00package LWP::Protocol::nogo; # If you want to disable access to a particular scheme, use this # class and then call # LWP::Protocol::implementor(that_scheme, 'LWP::Protocol::nogo'); # For then on, attempts to access URLs with that scheme will generate # a 500 error. use strict; our $VERSION = '6.58'; require HTTP::Response; require HTTP::Status; use parent qw(LWP::Protocol); sub request { my($self, $request) = @_; my $scheme = $request->uri->scheme; return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "Access to \'$scheme\' URIs has been disabled" ); } 1; perl5/LWP/Protocol/data.pm000044400000002323152462503210011303 0ustar00package LWP::Protocol::data; # Implements access to data:-URLs as specified in RFC 2397 use strict; our $VERSION = '6.58'; require HTTP::Response; require HTTP::Status; use parent qw(LWP::Protocol); use HTTP::Date qw(time2str); require LWP; # needs version number sub request { my($self, $request, $proxy, $arg, $size) = @_; # check proxy if (defined $proxy) { return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST, 'You can not proxy with data'); } # check method my $method = $request->method; unless ($method eq 'GET' || $method eq 'HEAD') { return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'data:' URLs"); } my $url = $request->uri; my $response = HTTP::Response->new( HTTP::Status::RC_OK, "Document follows"); my $media_type = $url->media_type; my $data = $url->data; $response->header('Content-Type' => $media_type, 'Content-Length' => length($data), 'Date' => time2str(time), 'Server' => "libwww-perl-internal/$LWP::VERSION" ); $data = "" if $method eq "HEAD"; return $self->collect_once($arg, $response, $data); } 1; perl5/LWP/Protocol/gopher.pm000044400000013142152462503210011657 0ustar00package LWP::Protocol::gopher; # Implementation of the gopher protocol (RFC 1436) # # This code is based on 'wwwgopher.pl,v 0.10 1994/10/17 18:12:34 shelden' # which in turn is a vastly modified version of Oscar's http'get() # dated 28/3/94 in # including contributions from Marc van Heyningen and Martijn Koster. use strict; our $VERSION = '6.58'; require HTTP::Response; require HTTP::Status; require IO::Socket; require IO::Select; use parent qw(LWP::Protocol); my %gopher2mimetype = ( '0' => 'text/plain', # 0 file '1' => 'text/html', # 1 menu # 2 CSO phone-book server # 3 Error '4' => 'application/mac-binhex40', # 4 BinHexed Macintosh file '5' => 'application/zip', # 5 DOS binary archive of some sort '6' => 'application/octet-stream', # 6 UNIX uuencoded file. '7' => 'text/html', # 7 Index-Search server # 8 telnet session '9' => 'application/octet-stream', # 9 binary file 'h' => 'text/html', # html 'g' => 'image/gif', # gif 'I' => 'image/*', # some kind of image ); my %gopher2encoding = ( '6' => 'x_uuencode', # 6 UNIX uuencoded file. ); sub request { my($self, $request, $proxy, $arg, $size, $timeout) = @_; $size = 4096 unless $size; # check proxy if (defined $proxy) { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'You can not proxy through the gopher'); } my $url = $request->uri; die "bad scheme" if $url->scheme ne 'gopher'; my $method = $request->method; unless ($method eq 'GET' || $method eq 'HEAD') { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'gopher:' URLs"); } my $gophertype = $url->gopher_type; unless (exists $gopher2mimetype{$gophertype}) { return HTTP::Response->new(HTTP::Status::RC_NOT_IMPLEMENTED, 'Library does not support gophertype ' . $gophertype); } my $response = HTTP::Response->new(HTTP::Status::RC_OK, "OK"); $response->header('Content-type' => $gopher2mimetype{$gophertype} || 'text/plain'); $response->header('Content-Encoding' => $gopher2encoding{$gophertype}) if exists $gopher2encoding{$gophertype}; if ($method eq 'HEAD') { # XXX: don't even try it so we set this header $response->header('Client-Warning' => 'Client answer only'); return $response; } if ($gophertype eq '7' && ! $url->search) { # the url is the prompt for a gopher search; supply boiler-plate return $self->collect_once($arg, $response, <<"EOT"); Gopher Index

$url
Gopher Search

This is a searchable Gopher index. Use the search function of your browser to enter search terms. EOT } my $host = $url->host; my $port = $url->port; my $requestLine = ""; my $selector = $url->selector; if (defined $selector) { $requestLine .= $selector; my $search = $url->search; if (defined $search) { $requestLine .= "\t$search"; my $string = $url->string; if (defined $string) { $requestLine .= "\t$string"; } } } $requestLine .= "\015\012"; # potential request headers are just ignored # Ok, lets make the request my $socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, LocalAddr => $self->{ua}{local_address}, Proto => 'tcp', Timeout => $timeout); die "Can't connect to $host:$port" unless $socket; my $sel = IO::Select->new($socket); { die "write timeout" if $timeout && !$sel->can_write($timeout); my $n = syswrite($socket, $requestLine, length($requestLine)); die $! unless defined($n); die "short write" if $n != length($requestLine); } my $user_arg = $arg; # must handle menus in a special way since they are to be # converted to HTML. Undefing $arg ensures that the user does # not see the data before we get a change to convert it. $arg = undef if $gophertype eq '1' || $gophertype eq '7'; # collect response my $buf = ''; $response = $self->collect($arg, $response, sub { die "read timeout" if $timeout && !$sel->can_read($timeout); my $n = sysread($socket, $buf, $size); die $! unless defined($n); return \$buf; } ); # Convert menu to HTML and return data to user. if ($gophertype eq '1' || $gophertype eq '7') { my $content = menu2html($response->content); if (defined $user_arg) { $response = $self->collect_once($user_arg, $response, $content); } else { $response->content($content); } } $response; } sub gopher2url { my($gophertype, $path, $host, $port) = @_; my $url; if ($gophertype eq '8' || $gophertype eq 'T') { # telnet session $url = $HTTP::URI_CLASS->new($gophertype eq '8' ? 'telnet:':'tn3270:'); $url->user($path) if defined $path; } else { $path = URI::Escape::uri_escape($path); $url = $HTTP::URI_CLASS->new("gopher:/$gophertype$path"); } $url->host($host); $url->port($port); $url; } sub menu2html { my($menu) = @_; $menu =~ tr/\015//d; # remove carriage return my $tmp = <<"EOT"; Gopher menu

Gopher menu

EOT for (split("\n", $menu)) { last if /^\./; my($pretty, $path, $host, $port) = split("\t"); $pretty =~ s/^(.)//; my $type = $1; my $url = gopher2url($type, $path, $host, $port)->as_string; $tmp .= qq{$pretty
\n}; } $tmp .= "\n\n"; $tmp; } 1; perl5/LWP/Protocol/http.pm000044400000035411152462503210011355 0ustar00package LWP::Protocol::http; use strict; our $VERSION = '6.58'; require HTTP::Response; require HTTP::Status; require Net::HTTP; use parent qw(LWP::Protocol); our @EXTRA_SOCK_OPTS; my $CRLF = "\015\012"; sub _new_socket { my($self, $host, $port, $timeout) = @_; # IPv6 literal IP address should be [bracketed] to remove # ambiguity between ip address and port number. if ( ($host =~ /:/) && ($host !~ /^\[/) ) { $host = "[$host]"; } local($^W) = 0; # IO::Socket::INET can be noisy my $sock = $self->socket_class->new(PeerAddr => $host, PeerPort => $port, LocalAddr => $self->{ua}{local_address}, Proto => 'tcp', Timeout => $timeout, KeepAlive => !!$self->{ua}{conn_cache}, SendTE => $self->{ua}{send_te}, $self->_extra_sock_opts($host, $port), ); unless ($sock) { # IO::Socket::INET leaves additional error messages in $@ my $status = "Can't connect to $host:$port"; if ($@ =~ /\bconnect: (.*)/ || $@ =~ /\b(Bad hostname)\b/ || $@ =~ /\b(nodename nor servname provided, or not known)\b/ || $@ =~ /\b(certificate verify failed)\b/ || $@ =~ /\b(Crypt-SSLeay can't verify hostnames)\b/ ) { $status .= " ($1)"; } elsif ($@) { $status .= " ($@)"; } die "$status\n\n$@"; } # perl 5.005's IO::Socket does not have the blocking method. eval { $sock->blocking(0); }; $sock; } sub socket_type { return "http"; } sub socket_class { my $self = shift; (ref($self) || $self) . "::Socket"; } sub _extra_sock_opts # to be overridden by subclass { return @EXTRA_SOCK_OPTS; } sub _check_sock { #my($self, $req, $sock) = @_; } sub _get_sock_info { my($self, $res, $sock) = @_; if (defined(my $peerhost = $sock->peerhost)) { $res->header("Client-Peer" => "$peerhost:" . $sock->peerport); } } sub _fixup_header { my($self, $h, $url, $proxy) = @_; # Extract 'Host' header my $hhost = $url->authority; if ($hhost =~ s/^([^\@]*)\@//) { # get rid of potential "user:pass@" # add authorization header if we need them. HTTP URLs do # not really support specification of user and password, but # we allow it. if (defined($1) && not $h->header('Authorization')) { require URI::Escape; $h->authorization_basic(map URI::Escape::uri_unescape($_), split(":", $1, 2)); } } $h->init_header('Host' => $hhost); if ($proxy && $url->scheme ne 'https') { # Check the proxy URI's userinfo() for proxy credentials # export http_proxy="http://proxyuser:proxypass@proxyhost:port". # For https only the initial CONNECT requests needs authorization. my $p_auth = $proxy->userinfo(); if(defined $p_auth) { require URI::Escape; $h->proxy_authorization_basic(map URI::Escape::uri_unescape($_), split(":", $p_auth, 2)) } } } sub hlist_remove { my($hlist, $k) = @_; $k = lc $k; for (my $i = @$hlist - 2; $i >= 0; $i -= 2) { next unless lc($hlist->[$i]) eq $k; splice(@$hlist, $i, 2); } } sub request { my($self, $request, $proxy, $arg, $size, $timeout) = @_; $size ||= 4096; # check method my $method = $request->method; unless ($method =~ /^[A-Za-z0-9_!\#\$%&\'*+\-.^\`|~]+$/) { # HTTP token return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'http:' URLs"); } my $url = $request->uri; # Proxying SSL with a http proxy needs issues a CONNECT request to build a # tunnel and then upgrades the tunnel to SSL. But when doing keep-alive the # https request does not need to be the first request in the connection, so # we need to distinguish between # - not yet connected (create socket and ssl upgrade) # - connected but not inside ssl tunnel (ssl upgrade) # - inside ssl tunnel to the target - once we are in the tunnel to the # target we cannot only reuse the tunnel for more https requests with the # same target my $ssl_tunnel = $proxy && $url->scheme eq 'https' && $url->host.":".$url->port; my ($host,$port) = $proxy ? ($proxy->host,$proxy->port) : ($url->host,$url->port); my $fullpath = $method eq 'CONNECT' ? $url->host . ":" . $url->port : $proxy && ! $ssl_tunnel ? $url->as_string : do { my $path = $url->path_query; $path = "/$path" if $path !~m{^/}; $path }; my $socket; my $conn_cache = $self->{ua}{conn_cache}; my $cache_key; if ( $conn_cache ) { $cache_key = "$host:$port"; # For https we reuse the socket immediately only if it has an established # tunnel to the target. Otherwise a CONNECT request followed by an SSL # upgrade need to be done first. The request itself might reuse an # existing non-ssl connection to the proxy $cache_key .= "!".$ssl_tunnel if $ssl_tunnel; if ( $socket = $conn_cache->withdraw($self->socket_type,$cache_key)) { if ($socket->can_read(0)) { # if the socket is readable, then either the peer has closed the # connection or there are some garbage bytes on it. In either # case we abandon it. $socket->close; $socket = undef; } # else use $socket else { $socket->timeout($timeout); } } } if ( ! $socket && $ssl_tunnel ) { my $proto_https = LWP::Protocol::create('https',$self->{ua}) or die "no support for scheme https found"; # only if ssl socket class is IO::Socket::SSL we can upgrade # a plain socket to SSL. In case of Net::SSL we fall back to # the old version if ( my $upgrade_sub = $proto_https->can('_upgrade_sock')) { my $response = $self->request( HTTP::Request->new('CONNECT',"http://$ssl_tunnel"), $proxy, undef,$size,$timeout ); $response->is_success or die "establishing SSL tunnel failed: ".$response->status_line; $socket = $upgrade_sub->($proto_https, $response->{client_socket},$url) or die "SSL upgrade failed: $@"; } else { $socket = $proto_https->_new_socket($url->host,$url->port,$timeout); } } if ( ! $socket ) { # connect to remote site w/o reusing established socket $socket = $self->_new_socket($host, $port, $timeout ); } my $http_version = ""; if (my $proto = $request->protocol) { if ($proto =~ /^(?:HTTP\/)?(1.\d+)$/) { $http_version = $1; $socket->http_version($http_version); $socket->send_te(0) if $http_version eq "1.0"; } } $self->_check_sock($request, $socket); my @h; my $request_headers = $request->headers->clone; $self->_fixup_header($request_headers, $url, $proxy); $request_headers->scan(sub { my($k, $v) = @_; $k =~ s/^://; $v =~ tr/\n/ /; push(@h, $k, $v); }); my $content_ref = $request->content_ref; $content_ref = $$content_ref if ref($$content_ref); my $chunked; my $has_content; if (ref($content_ref) eq 'CODE') { my $clen = $request_headers->header('Content-Length'); $has_content++ if $clen; unless (defined $clen) { push(@h, "Transfer-Encoding" => "chunked"); $has_content++; $chunked++; } } else { # Set (or override) Content-Length header my $clen = $request_headers->header('Content-Length'); if (defined($$content_ref) && length($$content_ref)) { $has_content = length($$content_ref); if (!defined($clen) || $clen ne $has_content) { if (defined $clen) { warn "Content-Length header value was wrong, fixed"; hlist_remove(\@h, 'Content-Length'); } push(@h, 'Content-Length' => $has_content); } } elsif ($clen) { warn "Content-Length set when there is no content, fixed"; hlist_remove(\@h, 'Content-Length'); } } my $write_wait = 0; $write_wait = 2 if ($request_headers->header("Expect") || "") =~ /100-continue/; my $req_buf = $socket->format_request($method, $fullpath, @h); #print "------\n$req_buf\n------\n"; if (!$has_content || $write_wait || $has_content > 8*1024) { WRITE: { # Since this just writes out the header block it should almost # always succeed to send the whole buffer in a single write call. my $n = $socket->syswrite($req_buf, length($req_buf)); unless (defined $n) { redo WRITE if $!{EINTR}; if ($!{EWOULDBLOCK} || $!{EAGAIN}) { select(undef, undef, undef, 0.1); redo WRITE; } die "write failed: $!"; } if ($n) { substr($req_buf, 0, $n, ""); } else { select(undef, undef, undef, 0.5); } redo WRITE if length $req_buf; } } my($code, $mess, @junk); my $drop_connection; if ($has_content) { my $eof; my $wbuf; my $woffset = 0; INITIAL_READ: if ($write_wait) { # skip filling $wbuf when waiting for 100-continue # because if the response is a redirect or auth required # the request will be cloned and there is no way # to reset the input stream # return here via the label after the 100-continue is read } elsif (ref($content_ref) eq 'CODE') { my $buf = &$content_ref(); $buf = "" unless defined($buf); $buf = sprintf "%x%s%s%s", length($buf), $CRLF, $buf, $CRLF if $chunked; substr($buf, 0, 0) = $req_buf if $req_buf; $wbuf = \$buf; } else { if ($req_buf) { my $buf = $req_buf . $$content_ref; $wbuf = \$buf; } else { $wbuf = $content_ref; } $eof = 1; } my $fbits = ''; vec($fbits, fileno($socket), 1) = 1; WRITE: while ($write_wait || $woffset < length($$wbuf)) { my $sel_timeout = $timeout; if ($write_wait) { $sel_timeout = $write_wait if $write_wait < $sel_timeout; } my $time_before; $time_before = time if $sel_timeout; my $rbits = $fbits; my $wbits = $write_wait ? undef : $fbits; my $sel_timeout_before = $sel_timeout; SELECT: { my $nfound = select($rbits, $wbits, undef, $sel_timeout); if ($nfound < 0) { if ($!{EINTR} || $!{EWOULDBLOCK} || $!{EAGAIN}) { if ($time_before) { $sel_timeout = $sel_timeout_before - (time - $time_before); $sel_timeout = 0 if $sel_timeout < 0; } redo SELECT; } die "select failed: $!"; } } if ($write_wait) { $write_wait -= time - $time_before; $write_wait = 0 if $write_wait < 0; } if (defined($rbits) && $rbits =~ /[^\0]/) { # readable my $buf = $socket->_rbuf; my $n = $socket->sysread($buf, 1024, length($buf)); unless (defined $n) { die "read failed: $!" unless $!{EINTR} || $!{EWOULDBLOCK} || $!{EAGAIN}; # if we get here the rest of the block will do nothing # and we will retry the read on the next round } elsif ($n == 0) { # the server closed the connection before we finished # writing all the request content. No need to write any more. $drop_connection++; last WRITE; } $socket->_rbuf($buf); if (!$code && $buf =~ /\015?\012\015?\012/) { # a whole response header is present, so we can read it without blocking ($code, $mess, @h) = $socket->read_response_headers(laxed => 1, junk_out => \@junk, ); if ($code eq "100") { $write_wait = 0; undef($code); goto INITIAL_READ; } else { $drop_connection++; last WRITE; # XXX should perhaps try to abort write in a nice way too } } } if (defined($wbits) && $wbits =~ /[^\0]/) { my $n = $socket->syswrite($$wbuf, length($$wbuf), $woffset); unless (defined $n) { die "write failed: $!" unless $!{EINTR} || $!{EWOULDBLOCK} || $!{EAGAIN}; $n = 0; # will retry write on the next round } elsif ($n == 0) { die "write failed: no bytes written"; } $woffset += $n; if (!$eof && $woffset >= length($$wbuf)) { # need to refill buffer from $content_ref code my $buf = &$content_ref(); $buf = "" unless defined($buf); $eof++ unless length($buf); $buf = sprintf "%x%s%s%s", length($buf), $CRLF, $buf, $CRLF if $chunked; $wbuf = \$buf; $woffset = 0; } } } # WRITE } ($code, $mess, @h) = $socket->read_response_headers(laxed => 1, junk_out => \@junk) unless $code; ($code, $mess, @h) = $socket->read_response_headers(laxed => 1, junk_out => \@junk) if $code eq "100"; my $response = HTTP::Response->new($code, $mess); my $peer_http_version = $socket->peer_http_version; $response->protocol("HTTP/$peer_http_version"); { local $HTTP::Headers::TRANSLATE_UNDERSCORE; $response->push_header(@h); } $response->push_header("Client-Junk" => \@junk) if @junk; $response->request($request); $self->_get_sock_info($response, $socket); if ($method eq "CONNECT") { $response->{client_socket} = $socket; # so it can be picked up return $response; } if (my @te = $response->remove_header('Transfer-Encoding')) { $response->push_header('Client-Transfer-Encoding', \@te); } $response->push_header('Client-Response-Num', scalar $socket->increment_response_count); my $complete; $response = $self->collect($arg, $response, sub { my $buf = ""; #prevent use of uninitialized value in SSLeay.xs my $n; READ: { $n = $socket->read_entity_body($buf, $size); unless (defined $n) { redo READ if $!{EINTR} || $!{EWOULDBLOCK} || $!{EAGAIN} || $!{ENOTTY}; die "read failed: $!"; } redo READ if $n == -1; } $complete++ if !$n; return \$buf; } ); $drop_connection++ unless $complete; @h = $socket->get_trailers; if (@h) { local $HTTP::Headers::TRANSLATE_UNDERSCORE; $response->push_header(@h); } # keep-alive support unless ($drop_connection) { if ($cache_key) { my %connection = map { (lc($_) => 1) } split(/\s*,\s*/, ($response->header("Connection") || "")); if (($peer_http_version eq "1.1" && !$connection{close}) || $connection{"keep-alive"}) { $conn_cache->deposit($self->socket_type, $cache_key, $socket); } } } $response; } #----------------------------------------------------------- package # hide from PAUSE LWP::Protocol::http::SocketMethods; sub ping { my $self = shift; !$self->can_read(0); } sub increment_response_count { my $self = shift; return ++${*$self}{'myhttp_response_count'}; } #----------------------------------------------------------- package # hide from PAUSE LWP::Protocol::http::Socket; use parent -norequire, qw(LWP::Protocol::http::SocketMethods Net::HTTP); 1; perl5/LWP/Protocol/cpan.pm000044400000002523152462503210011315 0ustar00package LWP::Protocol::cpan; use strict; use parent qw(LWP::Protocol); our $VERSION = '6.58'; require URI; require HTTP::Status; require HTTP::Response; our $CPAN; unless ($CPAN) { # Try to find local CPAN mirror via $CPAN::Config eval { require CPAN::Config; if($CPAN::Config) { my $urls = $CPAN::Config->{urllist}; if (ref($urls) eq "ARRAY") { my $file; for (@$urls) { if (/^file:/) { $file = $_; last; } } if ($file) { $CPAN = $file; } else { $CPAN = $urls->[0]; } } } }; $CPAN ||= "http://cpan.org/"; # last resort } # ensure that we don't chop of last part $CPAN .= "/" unless $CPAN =~ m,/$,; sub request { my($self, $request, $proxy, $arg, $size) = @_; # check proxy if (defined $proxy) { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'You can not proxy with cpan'); } # check method my $method = $request->method; unless ($method eq 'GET' || $method eq 'HEAD') { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'cpan:' URLs"); } my $path = $request->uri->path; $path =~ s,^/,,; my $response = HTTP::Response->new(HTTP::Status::RC_FOUND); $response->header("Location" => URI->new_abs($path, $CPAN)); $response; } 1; perl5/LWP/Protocol/https.pm000044400000015360152462503210011541 0ustar00package LWP::Protocol::https; use strict; our $VERSION = '6.10'; use base qw(LWP::Protocol::http); require Net::HTTPS; sub socket_type { return "https"; } sub _extra_sock_opts { my $self = shift; my %ssl_opts = %{$self->{ua}{ssl_opts} || {}}; if (delete $ssl_opts{verify_hostname}) { $ssl_opts{SSL_verify_mode} ||= 1; $ssl_opts{SSL_verifycn_scheme} = 'www'; } else { $ssl_opts{SSL_verify_mode} = 0; } if ($ssl_opts{SSL_verify_mode}) { unless (exists $ssl_opts{SSL_ca_file} || exists $ssl_opts{SSL_ca_path}) { eval { require Mozilla::CA; }; if ($@) { if ($@ =~ /^Can't locate Mozilla\/CA\.pm/) { $@ = <<'EOT'; Can't verify SSL peers without knowing which Certificate Authorities to trust This problem can be fixed by either setting the PERL_LWP_SSL_CA_FILE environment variable or by installing the Mozilla::CA module. To disable verification of SSL peers set the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0. If you do this you can't be sure that you communicate with the expected peer. EOT } die $@; } $ssl_opts{SSL_ca_file} = Mozilla::CA::SSL_ca_file(); } } $self->{ssl_opts} = \%ssl_opts; return (%ssl_opts, $self->SUPER::_extra_sock_opts); } #------------------------------------------------------------ # _cn_match($common_name, $san_name) # common_name: an IA5String # san_name: subjectAltName # initially we were only concerned with the dNSName # and the 'left-most' only wildcard as noted in # https://tools.ietf.org/html/rfc6125#section-6.4.3 # this method does not match any wildcarding in the # domain name as listed in section-6.4.3.3 # sub _cn_match { my( $me, $common_name, $san_name ) = @_; # /CN has a '*.' prefix # MUST be an FQDN -- fishing? return 0 if( $common_name =~ /^\*\./ ); my $re = q{}; # empty string # turn a leading "*." into a regex if( $san_name =~ /^\*\./ ) { $san_name =~ s/\*//; $re = "[^.]+"; } # quotemeta the rest and match anchored if( $common_name =~ /^$re\Q$san_name\E$/ ) { return 1; } return 0; } #------------------------------------------------------- # _in_san( cn, cert ) # 'cn' of the form /CN=host_to_check ( "Common Name" form ) # 'cert' any object that implements a peer_certificate('subjectAltNames') method # which will return an array of ( type-id, value ) pairings per # http://tools.ietf.org/html/rfc5280#section-4.2.1.6 # if there is no subjectAltNames there is nothing more to do. # currently we have a _cn_match() that will allow for simple compare. sub _in_san { my($me, $cn, $cert) = @_; # we can return early if there are no SAN options. my @sans = $cert->peer_certificate('subjectAltNames'); return unless scalar @sans; (my $common_name = $cn) =~ s/.*=//; # strip off the prefix. # get the ( type-id, value ) pairwise # currently only the basic CN to san_name check while( my ( $type_id, $value ) = splice( @sans, 0, 2 ) ) { return 'ok' if $me->_cn_match($common_name,$value); } return; } sub _check_sock { my($self, $req, $sock) = @_; my $check = $req->header("If-SSL-Cert-Subject"); if (defined $check) { my $cert = $sock->get_peer_certificate || die "Missing SSL certificate"; my $subject = $cert->subject_name; unless ( defined $subject && ( $subject =~ /$check/ ) ) { my $ok = $self->_in_san( $check, $cert); die "Bad SSL certificate subject: '$subject' !~ /$check/" unless $ok; } $req->remove_header("If-SSL-Cert-Subject"); # don't pass it on } } sub _get_sock_info { my $self = shift; $self->SUPER::_get_sock_info(@_); my($res, $sock) = @_; if ($sock->can('get_sslversion') and my $sslversion = $sock->get_sslversion) { $res->header("Client-SSL-Version" => $sslversion); } $res->header("Client-SSL-Cipher" => $sock->get_cipher); my $cert = $sock->get_peer_certificate; if ($cert) { $res->header("Client-SSL-Cert-Subject" => $cert->subject_name); $res->header("Client-SSL-Cert-Issuer" => $cert->issuer_name); } if (!$self->{ssl_opts}{SSL_verify_mode}) { $res->push_header("Client-SSL-Warning" => "Peer certificate not verified"); } elsif (!$self->{ssl_opts}{SSL_verifycn_scheme}) { $res->push_header("Client-SSL-Warning" => "Peer hostname match with certificate not verified"); } $res->header("Client-SSL-Socket-Class" => $Net::HTTPS::SSL_SOCKET_CLASS); } # upgrade plain socket to SSL, used for CONNECT tunnel when proxying https # will only work if the underlying socket class of Net::HTTPS is # IO::Socket::SSL, but code will only be called in this case if ( $Net::HTTPS::SSL_SOCKET_CLASS->can('start_SSL')) { *_upgrade_sock = sub { my ($self,$sock,$url) = @_; $sock = LWP::Protocol::https::Socket->start_SSL( $sock, SSL_verifycn_name => $url->host, SSL_hostname => $url->host, $self->_extra_sock_opts, ); $@ = LWP::Protocol::https::Socket->errstr if ! $sock; return $sock; } } #----------------------------------------------------------- package LWP::Protocol::https::Socket; use base qw(Net::HTTPS LWP::Protocol::http::SocketMethods); 1; __END__ =head1 NAME LWP::Protocol::https - Provide https support for LWP::UserAgent =head1 SYNOPSIS use LWP::UserAgent; $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 1 }); $res = $ua->get("https://www.example.com"); # specify a CA path $ua = LWP::UserAgent->new( ssl_opts => { SSL_ca_path => '/etc/ssl/certs', verify_hostname => 1, } ); =head1 DESCRIPTION The LWP::Protocol::https module provides support for using https schemed URLs with LWP. This module is a plug-in to the LWP protocol handling, so you don't use it directly. Once the module is installed LWP is able to access sites using HTTP over SSL/TLS. If hostname verification is requested by LWP::UserAgent's C, and neither C nor C is set, then C is implied to be the one provided by L. If the Mozilla::CA module isn't available SSL requests will fail. Either install this module, set up an alternative C or disable hostname verification. This module used to be bundled with the libwww-perl, but it was unbundled in v6.02 in order to be able to declare its dependencies properly for the CPAN tool-chain. Applications that need https support can just declare their dependency on LWP::Protocol::https and will no longer need to know what underlying modules to install. =head1 SEE ALSO L, L, L =head1 COPYRIGHT & LICENSE Copyright (c) 1997-2011 Gisle Aas. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/LWP/Protocol/mailto.pm000044400000010470152462503210011661 0ustar00package LWP::Protocol::mailto; # This module implements the mailto protocol. It is just a simple # frontend to the Unix sendmail program except on MacOS, where it uses # Mail::Internet. require HTTP::Request; require HTTP::Response; require HTTP::Status; use Carp; use strict; our $VERSION = '6.58'; use parent qw(LWP::Protocol); our $SENDMAIL; unless ($SENDMAIL = $ENV{SENDMAIL}) { for my $sm (qw(/usr/sbin/sendmail /usr/lib/sendmail /usr/ucblib/sendmail )) { if (-x $sm) { $SENDMAIL = $sm; last; } } die "Can't find the 'sendmail' program" unless $SENDMAIL; } sub request { my($self, $request, $proxy, $arg, $size) = @_; my ($mail, $addr) if $^O eq "MacOS"; my @text = () if $^O eq "MacOS"; # check proxy if (defined $proxy) { return HTTP::Response->new(HTTP::Status::RC_BAD_REQUEST, 'You can not proxy with mail'); } # check method my $method = $request->method; if ($method ne 'POST') { return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'mailto:' URLs"); } # check url my $url = $request->uri; my $scheme = $url->scheme; if ($scheme ne 'mailto') { return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "LWP::Protocol::mailto::request called for '$scheme'"); } if ($^O eq "MacOS") { eval { require Mail::Internet; }; if($@) { return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "You don't have MailTools installed"); } unless ($ENV{SMTPHOSTS}) { return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "You don't have SMTPHOSTS defined"); } } else { unless (-x $SENDMAIL) { return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "You don't have $SENDMAIL"); } } if ($^O eq "MacOS") { $mail = Mail::Internet->new or return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "Can't get a Mail::Internet object"); } else { open(SENDMAIL, "| $SENDMAIL -oi -t") or return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "Can't run $SENDMAIL: $!"); } if ($^O eq "MacOS") { $addr = $url->encoded822addr; } else { $request = $request->clone; # we modify a copy my @h = $url->headers; # URL headers override those in the request while (@h) { my $k = shift @h; my $v = shift @h; next unless defined $v; if (lc($k) eq "body") { $request->content($v); } else { $request->push_header($k => $v); } } } if ($^O eq "MacOS") { $mail->add(To => $addr); $mail->add(split(/[:\n]/,$request->headers_as_string)); } else { print SENDMAIL $request->headers_as_string; print SENDMAIL "\n"; } my $content = $request->content; if (defined $content) { my $contRef = ref($content) ? $content : \$content; if (ref($contRef) eq 'SCALAR') { if ($^O eq "MacOS") { @text = split("\n",$$contRef); foreach (@text) { $_ .= "\n"; } } else { print SENDMAIL $$contRef; } } elsif (ref($contRef) eq 'CODE') { # Callback provides data my $d; if ($^O eq "MacOS") { my $stuff = ""; while (length($d = &$contRef)) { $stuff .= $d; } @text = split("\n",$stuff); foreach (@text) { $_ .= "\n"; } } else { print SENDMAIL $d; } } } if ($^O eq "MacOS") { $mail->body(\@text); unless ($mail->smtpsend) { return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR, "Mail::Internet->smtpsend unable to send message to <$addr>"); } } else { unless (close(SENDMAIL)) { my $err = $! ? "$!" : "Exit status $?"; return HTTP::Response->new(HTTP::Status::RC_INTERNAL_SERVER_ERROR, "$SENDMAIL: $err"); } } my $response = HTTP::Response->new(HTTP::Status::RC_ACCEPTED, "Mail accepted"); $response->header('Content-Type', 'text/plain'); if ($^O eq "MacOS") { $response->header('Server' => "Mail::Internet $Mail::Internet::VERSION"); $response->content("Message sent to <$addr>\n"); } else { $response->header('Server' => $SENDMAIL); my $to = $request->header("To"); $response->content("Message sent to <$to>\n"); } return $response; } 1; perl5/LWP/Protocol/file.pm000044400000007405152462503210011317 0ustar00package LWP::Protocol::file; use parent qw(LWP::Protocol); use strict; our $VERSION = '6.58'; require LWP::MediaTypes; require HTTP::Request; require HTTP::Response; require HTTP::Status; require HTTP::Date; sub request { my($self, $request, $proxy, $arg, $size) = @_; $size = 4096 unless defined $size and $size > 0; # check proxy if (defined $proxy) { return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST, 'You can not proxy through the filesystem'); } # check method my $method = $request->method; unless ($method eq 'GET' || $method eq 'HEAD') { return HTTP::Response->new( HTTP::Status::RC_BAD_REQUEST, 'Library does not allow method ' . "$method for 'file:' URLs"); } # check url my $url = $request->uri; my $scheme = $url->scheme; if ($scheme ne 'file') { return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "LWP::Protocol::file::request called for '$scheme'"); } # URL OK, look at file my $path = $url->file; # test file exists and is readable unless (-e $path) { return HTTP::Response->new( HTTP::Status::RC_NOT_FOUND, "File `$path' does not exist"); } unless (-r _) { return HTTP::Response->new( HTTP::Status::RC_FORBIDDEN, 'User does not have read permission'); } # looks like file exists my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$filesize, $atime,$mtime,$ctime,$blksize,$blocks) = stat(_); # XXX should check Accept headers? # check if-modified-since my $ims = $request->header('If-Modified-Since'); if (defined $ims) { my $time = HTTP::Date::str2time($ims); if (defined $time and $time >= $mtime) { return HTTP::Response->new( HTTP::Status::RC_NOT_MODIFIED, "$method $path"); } } # Ok, should be an OK response by now... my $response = HTTP::Response->new( HTTP::Status::RC_OK ); # fill in response headers $response->header('Last-Modified', HTTP::Date::time2str($mtime)); if (-d _) { # If the path is a directory, process it # generate the HTML for directory opendir(D, $path) or return HTTP::Response->new( HTTP::Status::RC_INTERNAL_SERVER_ERROR, "Cannot read directory '$path': $!"); my(@files) = sort readdir(D); closedir(D); # Make directory listing require URI::Escape; require HTML::Entities; my $pathe = $path . ( $^O eq 'MacOS' ? ':' : '/'); for (@files) { my $furl = URI::Escape::uri_escape($_); if ( -d "$pathe$_" ) { $furl .= '/'; $_ .= '/'; } my $desc = HTML::Entities::encode($_); $_ = qq{
  • $desc}; } # Ensure that the base URL is "/" terminated my $base = $url->clone; unless ($base->path =~ m|/$|) { $base->path($base->path . "/"); } my $html = join("\n", "\n", "Directory $path", "", "\n", "

    Directory listing of $path

    ", "
      ", @files, "
    ", "\n\n"); $response->header('Content-Type', 'text/html'); $response->header('Content-Length', length $html); $html = "" if $method eq "HEAD"; return $self->collect_once($arg, $response, $html); } # path is a regular file $response->header('Content-Length', $filesize); LWP::MediaTypes::guess_media_type($path, $response); # read the file if ($method ne "HEAD") { open(my $fh, '<', $path) or return new HTTP::Response(HTTP::Status::RC_INTERNAL_SERVER_ERROR, "Cannot read file '$path': $!"); binmode($fh); $response = $self->collect($arg, $response, sub { my $content = ""; my $bytes = sysread($fh, $content, $size); return \$content if $bytes > 0; return \ ""; }); close($fh); } $response; } 1; perl5/Canary/Stability.pm000044400000015452152462503210011317 0ustar00=head1 NAME Canary::Stability - canary to check perl compatibility for schmorp's modules =head1 SYNOPSIS # in Makefile.PL use Canary::Stability DISTNAME => 2001, MINIMUM_PERL_VERSION; =head1 DESCRIPTION This module is used by Schmorp's modules during configuration stage to test the installed perl for compatibility with his modules. It's not, at this stage, meant as a tool for other module authors, although in principle nothing prevents them from subscribing to the same ideas. See the F in L or L for usage examples. =cut package Canary::Stability; BEGIN { $VERSION = 2013; } sub sgr { # we just assume ANSI almost everywhere # red 31, yellow 33, green 32 local $| = 1; $ENV{PERL_CANARY_STABILITY_COLOUR} ne 0 and ((-t STDOUT and length $ENV{TERM}) or $ENV{PERL_CANARY_STABILITY_COLOUR}) and print "\e[$_[0]m"; } sub import { my (undef, $distname, $minvers, $minperl) = @_; $ENV{PERL_CANARY_STABILITY_DISABLE} and return; $minperl ||= 5.008002; print < $VERSION) { sgr 33; print < Do not prompt the user on alert messages. =item C Disable use of colour. =item C Force use of colour. =item C Disable this modules functionality completely. =item C When this variable is set to a true value and the perl minimum version requirement is not met, the module will exit, which should skip testing under automated testing environments. This is done to avoid false failure or success reports when the chances of success are already quite low and the failures are not supported by the author. =back =head1 AUTHOR Marc Lehmann http://software.schmorp.de/pkg/Canary-Stability.html =cut 1 perl5/Mozilla/mk-ca-bundle.pl000055500000051622152462503210012005 0ustar00#!/usr/bin/env perl # *************************************************************************** # * _ _ ____ _ # * Project ___| | | | _ \| | # * / __| | | | |_) | | # * | (__| |_| | _ <| |___ # * \___|\___/|_| \_\_____| # * # * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. # * # * This software is licensed as described in the file COPYING, which # * you should have received as part of this distribution. The terms # * are also available at https://curl.se/docs/copyright.html. # * # * You may opt to use, copy, modify, merge, publish, distribute and/or sell # * copies of the Software, and permit persons to whom the Software is # * furnished to do so, under the terms of the COPYING file. # * # * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # * KIND, either express or implied. # * # *************************************************************************** # This Perl script creates a fresh ca-bundle.crt file for use with libcurl. # It downloads certdata.txt from Mozilla's source tree (see URL below), # then parses certdata.txt and extracts CA Root Certificates into PEM format. # These are then processed with the OpenSSL commandline tool to produce the # final ca-bundle.crt file. # The script is based on the parse-certs script written by Roland Krikava. # This Perl script works on almost any platform since its only external # dependency is the OpenSSL commandline tool for optional text listing. # Hacked by Guenter Knauf. # use Encode; use Getopt::Std; use MIME::Base64; use strict; use warnings; use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_k $opt_l $opt_m $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w); use List::Util; use Text::Wrap; use Time::Local; my $MOD_SHA = "Digest::SHA"; eval "require $MOD_SHA"; if ($@) { $MOD_SHA = "Digest::SHA::PurePerl"; eval "require $MOD_SHA"; } eval "require LWP::UserAgent"; my %urls = ( 'nss' => 'https://hg.mozilla.org/projects/nss/raw-file/default/lib/ckfw/builtins/certdata.txt', 'central' => 'https://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', 'beta' => 'https://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', 'release' => 'https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt', ); $opt_d = 'release'; # If the OpenSSL commandline is not in search path you can configure it here! my $openssl = 'openssl'; my $version = '1.28'; $opt_w = 76; # default base64 encoded lines length # default cert types to include in the output (default is to include CAs which may issue SSL server certs) my $default_mozilla_trust_purposes = "SERVER_AUTH"; my $default_mozilla_trust_levels = "TRUSTED_DELEGATOR"; $opt_p = $default_mozilla_trust_purposes . ":" . $default_mozilla_trust_levels; my @valid_mozilla_trust_purposes = ( "DIGITAL_SIGNATURE", "NON_REPUDIATION", "KEY_ENCIPHERMENT", "DATA_ENCIPHERMENT", "KEY_AGREEMENT", "KEY_CERT_SIGN", "CRL_SIGN", "SERVER_AUTH", "CLIENT_AUTH", "CODE_SIGNING", "EMAIL_PROTECTION", "IPSEC_END_SYSTEM", "IPSEC_TUNNEL", "IPSEC_USER", "TIME_STAMPING", "STEP_UP_APPROVED" ); my @valid_mozilla_trust_levels = ( "TRUSTED_DELEGATOR", # CAs "NOT_TRUSTED", # Don't trust these certs. "MUST_VERIFY_TRUST", # This explicitly tells us that it ISN'T a CA but is otherwise ok. In other words, this should tell the app to ignore any other sources that claim this is a CA. "TRUSTED" # This cert is trusted, but only for itself and not for delegates (i.e. it is not a CA). ); my $default_signature_algorithms = $opt_s = "MD5"; my @valid_signature_algorithms = ( "MD5", "SHA1", "SHA256", "SHA384", "SHA512" ); $0 =~ s@.*(/|\\)@@; $Getopt::Std::STANDARD_HELP_VERSION = 1; getopts('bd:fhiklmnp:qs:tuvw:'); if(!defined($opt_d)) { # to make plain "-d" use not cause warnings, and actually still work $opt_d = 'release'; } # Use predefined URL or else custom URL specified on command line. my $url; if(defined($urls{$opt_d})) { $url = $urls{$opt_d}; if(!$opt_k && $url !~ /^https:\/\//i) { die "The URL for '$opt_d' is not HTTPS. Use -k to override (insecure).\n"; } } else { $url = $opt_d; } my $curl = `curl -V`; if ($opt_i) { print ("=" x 78 . "\n"); print "Script Version : $version\n"; print "Perl Version : $]\n"; print "Operating System Name : $^O\n"; print "Getopt::Std.pm Version : ${Getopt::Std::VERSION}\n"; print "Encode::Encoding.pm Version : ${Encode::Encoding::VERSION}\n"; print "MIME::Base64.pm Version : ${MIME::Base64::VERSION}\n"; print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n" if($LWP::UserAgent::VERSION); print "LWP.pm Version : ${LWP::VERSION}\n" if($LWP::VERSION); print "Digest::SHA.pm Version : ${Digest::SHA::VERSION}\n" if ($Digest::SHA::VERSION); print "Digest::SHA::PurePerl.pm Version : ${Digest::SHA::PurePerl::VERSION}\n" if ($Digest::SHA::PurePerl::VERSION); print ("=" x 78 . "\n"); } sub warning_message() { if ( $opt_d =~ m/^risk$/i ) { # Long Form Warning and Exit print "Warning: Use of this script may pose some risk:\n"; print "\n"; print " 1) If you use HTTP URLs they are subject to a man in the middle attack\n"; print " 2) Default to 'release', but more recent updates may be found in other trees\n"; print " 3) certdata.txt file format may change, lag time to update this script\n"; print " 4) Generally unwise to blindly trust CAs without manual review & verification\n"; print " 5) Mozilla apps use additional security checks aren't represented in certdata\n"; print " 6) Use of this script will make a security engineer grind his teeth and\n"; print " swear at you. ;)\n"; exit; } else { # Short Form Warning print "Warning: Use of this script may pose some risk, -d risk for more details.\n"; } } sub HELP_MESSAGE() { print "Usage:\t${0} [-b] [-d] [-f] [-i] [-k] [-l] [-n] [-p] [-q] [-s] [-t] [-u] [-v] [-w] []\n"; print "\t-b\tbackup an existing version of ca-bundle.crt\n"; print "\t-d\tspecify Mozilla tree to pull certdata.txt or custom URL\n"; print "\t\t Valid names are:\n"; print "\t\t ", join( ", ", map { ( $_ =~ m/$opt_d/ ) ? "$_ (default)" : "$_" } sort keys %urls ), "\n"; print "\t-f\tforce rebuild even if certdata.txt is current\n"; print "\t-i\tprint version info about used modules\n"; print "\t-k\tallow URLs other than HTTPS, enable HTTP fallback (insecure)\n"; print "\t-l\tprint license info about certdata.txt\n"; print "\t-m\tinclude meta data in output\n"; print "\t-n\tno download of certdata.txt (to use existing)\n"; print wrap("\t","\t\t", "-p\tlist of Mozilla trust purposes and levels for certificates to include in output. Takes the form of a comma separated list of purposes, a colon, and a comma separated list of levels. (default: $default_mozilla_trust_purposes:$default_mozilla_trust_levels)"), "\n"; print "\t\t Valid purposes are:\n"; print wrap("\t\t ","\t\t ", join( ", ", "ALL", @valid_mozilla_trust_purposes ) ), "\n"; print "\t\t Valid levels are:\n"; print wrap("\t\t ","\t\t ", join( ", ", "ALL", @valid_mozilla_trust_levels ) ), "\n"; print "\t-q\tbe really quiet (no progress output at all)\n"; print wrap("\t","\t\t", "-s\tcomma separated list of certificate signatures/hashes to output in plain text mode. (default: $default_signature_algorithms)\n"); print "\t\t Valid signature algorithms are:\n"; print wrap("\t\t ","\t\t ", join( ", ", "ALL", @valid_signature_algorithms ) ), "\n"; print "\t-t\tinclude plain text listing of certificates\n"; print "\t-u\tunlink (remove) certdata.txt after processing\n"; print "\t-v\tbe verbose and print out processed CAs\n"; print "\t-w \twrap base64 output lines after chars (default: ${opt_w})\n"; exit; } sub VERSION_MESSAGE() { print "${0} version ${version} running Perl ${]} on ${^O}\n"; } warning_message() unless ($opt_q || $url =~ m/^(ht|f)tps:/i ); HELP_MESSAGE() if ($opt_h); sub report($@) { my $output = shift; print STDERR $output . "\n" unless $opt_q; } sub is_in_list($@) { my $target = shift; return defined(List::Util::first { $target eq $_ } @_); } # Parses $param_string as a case insensitive comma separated list with optional whitespace # validates that only allowed parameters are supplied sub parse_csv_param($$@) { my $description = shift; my $param_string = shift; my @valid_values = @_; my @values = map { s/^\s+//; # strip leading spaces s/\s+$//; # strip trailing spaces uc $_ # return the modified string as upper case } split( ',', $param_string ); # Find all values which are not in the list of valid values or "ALL" my @invalid = grep { !is_in_list($_,"ALL",@valid_values) } @values; if ( scalar(@invalid) > 0 ) { # Tell the user which parameters were invalid and print the standard help message which will exit print "Error: Invalid ", $description, scalar(@invalid) == 1 ? ": " : "s: ", join( ", ", map { "\"$_\"" } @invalid ), "\n"; HELP_MESSAGE(); } @values = @valid_values if ( is_in_list("ALL",@values) ); return @values; } sub sha256 { my $result; if ($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION) { open(FILE, $_[0]) or die "Can't open '$_[0]': $!"; binmode(FILE); $result = $MOD_SHA->new(256)->addfile(*FILE)->hexdigest; close(FILE); } else { # Use OpenSSL command if Perl Digest::SHA modules not available $result = `"$openssl" dgst -r -sha256 "$_[0]"`; $result =~ s/^([0-9a-f]{64}) .+/$1/is; } return $result; } sub oldhash { my $hash = ""; open(C, "<$_[0]") || return 0; while() { chomp; if($_ =~ /^\#\# SHA256: (.*)/) { $hash = $1; last; } } close(C); return $hash; } if ( $opt_p !~ m/:/ ) { print "Error: Mozilla trust identifier list must include both purposes and levels\n"; HELP_MESSAGE(); } (my $included_mozilla_trust_purposes_string, my $included_mozilla_trust_levels_string) = split( ':', $opt_p ); my @included_mozilla_trust_purposes = parse_csv_param( "trust purpose", $included_mozilla_trust_purposes_string, @valid_mozilla_trust_purposes ); my @included_mozilla_trust_levels = parse_csv_param( "trust level", $included_mozilla_trust_levels_string, @valid_mozilla_trust_levels ); my @included_signature_algorithms = parse_csv_param( "signature algorithm", $opt_s, @valid_signature_algorithms ); sub should_output_cert(%) { my %trust_purposes_by_level = @_; foreach my $level (@included_mozilla_trust_levels) { # for each level we want to output, see if any of our desired purposes are included return 1 if ( defined( List::Util::first { is_in_list( $_, @included_mozilla_trust_purposes ) } @{$trust_purposes_by_level{$level}} ) ); } return 0; } my $crt = $ARGV[0] || 'ca-bundle.crt'; (my $txt = $url) =~ s@(.*/|\?.*)@@g; my $stdout = $crt eq '-'; my $resp; my $fetched; my $oldhash = oldhash($crt); report "SHA256 of old file: $oldhash"; if(!$opt_n) { report "Downloading $txt ..."; # If we have an HTTPS URL then use curl if($url =~ /^https:\/\//i) { if($curl) { if($curl =~ /^Protocols:.* https( |$)/m) { report "Get certdata with curl!"; my $proto = !$opt_k ? "--proto =https" : ""; my $quiet = $opt_q ? "-s" : ""; my @out = `curl -w %{response_code} $proto $quiet -o "$txt" "$url"`; if(!$? && @out && $out[0] == 200) { $fetched = 1; report "Downloaded $txt"; } else { report "Failed downloading via HTTPS with curl"; if(-e $txt && !unlink($txt)) { report "Failed to remove '$txt': $!"; } } } else { report "curl lacks https support"; } } else { report "curl not found"; } } # If nothing was fetched then use LWP if(!$fetched) { if($url =~ /^https:\/\//i) { report "Falling back to HTTP"; $url =~ s/^https:\/\//http:\/\//i; } if(!$opt_k) { report "URLs other than HTTPS are disabled by default, to enable use -k"; exit 1; } report "Get certdata with LWP!"; if(!defined(${LWP::UserAgent::VERSION})) { report "LWP is not available (LWP::UserAgent not found)"; exit 1; } my $ua = new LWP::UserAgent(agent => "$0/$version"); $ua->env_proxy(); $resp = $ua->mirror($url, $txt); if($resp && $resp->code eq '304') { report "Not modified"; exit 0 if -e $crt && !$opt_f; } else { $fetched = 1; report "Downloaded $txt"; } if(!$resp || $resp->code !~ /^(?:200|304)$/) { report "Unable to download latest data: " . ($resp? $resp->code . ' - ' . $resp->message : "LWP failed"); exit 1 if -e $crt || ! -r $txt; } } } my $filedate = $resp ? $resp->last_modified : (stat($txt))[9]; my $datesrc = "as of"; if(!$filedate) { # mxr.mozilla.org gave us a time, hg.mozilla.org does not! $filedate = time(); $datesrc="downloaded on"; } # get the hash from the download file my $newhash= sha256($txt); if(!$opt_f && $oldhash eq $newhash) { report "Downloaded file identical to previous run\'s source file. Exiting"; if($opt_u && -e $txt && !unlink($txt)) { report "Failed to remove $txt: $!\n"; } exit; } report "SHA256 of new file: $newhash"; my $currentdate = scalar gmtime($filedate); my $format = $opt_t ? "plain text and " : ""; if( $stdout ) { open(CRT, '> -') or die "Couldn't open STDOUT: $!\n"; } else { open(CRT,">$crt.~") or die "Couldn't open $crt.~: $!\n"; } print CRT <) { if (/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) { print CRT; print if ($opt_l); while () { print CRT; print if ($opt_l); last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/); } } # Not Valid After : Thu Sep 30 14:01:15 2021 elsif(/^# Not Valid After : (.*)/) { my $stamp = $1; use Time::Piece; my $t = Time::Piece->strptime ($stamp, "%a %b %d %H:%M:%S %Y"); my $delta = ($t->epoch - time()); # negative means no longer valid if($delta < 0) { $skipnum++; report "Skipping: $caname is not valid anymore" if ($opt_v); $valid = 0; } else { $valid = 1; } next; } elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) { push @precert, $_; next; } elsif(/^#|^\s*$/) { undef @precert; next; } chomp; # Example: # CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL # \062\060\060\066\061\067\060\060\060\060\060\060\132 # END if (/^CKA_NSS_SERVER_DISTRUST_AFTER (CK_BBOOL CK_FALSE|MULTILINE_OCTAL)/) { if($1 eq "MULTILINE_OCTAL") { my @timestamp; while () { last if (/^END/); chomp; my @octets = split(/\\/); shift @octets; for (@octets) { push @timestamp, chr(oct); } } # A trailing Z in the timestamp signifies UTC if($timestamp[12] ne "Z") { report "distrust date stamp is not using UTC"; } # Example date: 200617000000Z # Means 2020-06-17 00:00:00 UTC my $distrustat = timegm($timestamp[10] . $timestamp[11], # second $timestamp[8] . $timestamp[9], # minute $timestamp[6] . $timestamp[7], # hour $timestamp[4] . $timestamp[5], # day ($timestamp[2] . $timestamp[3]) - 1, # month "20" . $timestamp[0] . $timestamp[1]); # year if(time >= $distrustat) { # not trusted anymore $skipnum++; report "Skipping: $caname is not trusted anymore" if ($opt_v); $valid = 0; } else { # still trusted } } next; } # this is a match for the start of a certificate if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) { $start_of_cert = 1 } if ($start_of_cert && /^CKA_LABEL UTF8 \"(.*)\"/) { $caname = $1; } my %trust_purposes_by_level; if ($start_of_cert && /^CKA_VALUE MULTILINE_OCTAL/) { $cka_value=""; while () { last if (/^END/); chomp; my @octets = split(/\\/); shift @octets; for (@octets) { $cka_value .= chr(oct); } } } if(/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/ && $valid) { # now scan the trust part to determine how we should trust this cert while () { last if (/^#/); if (/^CKA_TRUST_([A-Z_]+)\s+CK_TRUST\s+CKT_NSS_([A-Z_]+)\s*$/) { if ( !is_in_list($1,@valid_mozilla_trust_purposes) ) { report "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2"; } elsif ( !is_in_list($2,@valid_mozilla_trust_levels) ) { report "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2"; } else { push @{$trust_purposes_by_level{$2}}, $1; } } } if ( !should_output_cert(%trust_purposes_by_level) ) { $skipnum ++; report "Skipping: $caname" if ($opt_v); } else { my $data = $cka_value; $cka_value = ""; if(!length($data)) { # if empty, skip next; } my $encoded = MIME::Base64::encode_base64($data, ''); $encoded =~ s/(.{1,${opt_w}})/$1\n/g; my $pem = "-----BEGIN CERTIFICATE-----\n" . $encoded . "-----END CERTIFICATE-----\n"; print CRT "\n$caname\n"; print CRT @precert if($opt_m); my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK | Encode::LEAVE_SRC)); if ($opt_t) { foreach my $key (sort keys %trust_purposes_by_level) { my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}}); $maxStringLength = List::Util::max( length($string), $maxStringLength ); print CRT $string . "\n"; } } print CRT ("=" x $maxStringLength . "\n"); if (!$opt_t) { print CRT $pem; } else { my $pipe = ""; foreach my $hash (@included_signature_algorithms) { $pipe = "|$openssl x509 -" . $hash . " -fingerprint -noout -inform PEM"; if (!$stdout) { $pipe .= " >> $crt.~"; close(CRT) or die "Couldn't close $crt.~: $!"; } open(TMP, $pipe) or die "Couldn't open openssl pipe: $!"; print TMP $pem; close(TMP) or die "Couldn't close openssl pipe: $!"; if (!$stdout) { open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; } } $pipe = "|$openssl x509 -text -inform PEM"; if (!$stdout) { $pipe .= " >> $crt.~"; close(CRT) or die "Couldn't close $crt.~: $!"; } open(TMP, $pipe) or die "Couldn't open openssl pipe: $!"; print TMP $pem; close(TMP) or die "Couldn't close openssl pipe: $!"; if (!$stdout) { open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; } } report "Parsing: $caname" if ($opt_v); $certnum ++; $start_of_cert = 0; } undef @precert; } } close(TXT) or die "Couldn't close $txt: $!\n"; close(CRT) or die "Couldn't close $crt.~: $!\n"; unless( $stdout ) { if ($opt_b && -e $crt) { my $bk = 1; while (-e "$crt.~${bk}~") { $bk++; } rename $crt, "$crt.~${bk}~" or die "Failed to create backup $crt.~$bk}~: $!\n"; } elsif( -e $crt ) { unlink( $crt ) or die "Failed to remove $crt: $!\n"; } rename "$crt.~", $crt or die "Failed to rename $crt.~ to $crt: $!\n"; } if($opt_u && -e $txt && !unlink($txt)) { report "Failed to remove $txt: $!\n"; } report "Done ($certnum CA certs processed, $skipnum skipped)."; perl5/Mozilla/CA/cacert.pem000044400000614377152462503210011451 0ustar00## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Fri Oct 1 13:46:52 2021 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates ## file (certdata.txt). This file can be found in the mozilla source tree: ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.28. ## SHA256: c8f6733d1ff4e6a4769c182971a1234f95ae079247a9c439a13423fe8ba5c24f ## GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- GlobalSign Root CA - R2 ======================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= -----END CERTIFICATE----- Baltimore CyberTrust Root ========================= -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- Entrust Root Certification Authority ==================================== -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- Comodo AAA Services root ======================== -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- QuoVadis Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- QuoVadis Root CA 3 ================== -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- Security Communication Root CA ============================== -----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi FL39vmwLAw== -----END CERTIFICATE----- XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- Go Daddy Class 2 CA =================== -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b vZ8= -----END CERTIFICATE----- Starfield Class 2 CA ==================== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- DigiCert Assured ID Root CA =========================== -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- DigiCert Global Root CA ======================= -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- DigiCert High Assurance EV Root CA ================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K -----END CERTIFICATE----- SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- SwissSign Silver CA - G2 ======================== -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- SecureTrust CA ============== -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- Secure Global CA ================ -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- COMODO Certification Authority ============================== -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== -----END CERTIFICATE----- Network Solutions Certificate Authority ======================================= -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- Certigna ======== -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- Cybertrust Global Root ====================== -----BEGIN CERTIFICATE----- MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW WL1WMRJOEcgh4LMRkWXbtKaIOM5V -----END CERTIFICATE----- ePKI Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- certSIGN ROOT CA ================ -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD -----END CERTIFICATE----- NetLock Arany (Class Gold) Főtanúsítvány ======================================== -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- Hongkong Post Root CA 1 ======================= -----BEGIN CERTIFICATE----- MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== -----END CERTIFICATE----- SecureSign RootCA11 =================== -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= -----END CERTIFICATE----- Microsec e-Szigno Root CA 2009 ============================== -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi LXpUq3DDfSJlgnCW -----END CERTIFICATE----- GlobalSign Root CA - R3 ======================= -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r kpeDMdmztcpHWD9f -----END CERTIFICATE----- Autoridad de Certificacion Firmaprofesional CIF A62634068 ========================================================= -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -----END CERTIFICATE----- Izenpe.com ========== -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- Go Daddy Root Certificate Authority - G2 ======================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 -----END CERTIFICATE----- Starfield Root Certificate Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- Starfield Services Root Certificate Authority - G2 ================================================== -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 -----END CERTIFICATE----- AffirmTrust Commercial ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- AffirmTrust Networking ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- AffirmTrust Premium =================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== -----END CERTIFICATE----- AffirmTrust Premium ECC ======================= -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM eQ== -----END CERTIFICATE----- Certum Trusted Network CA ========================= -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- Security Communication RootCA2 ============================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- EC-ACC ====== -----BEGIN CERTIFICATE----- MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D 5EI= -----END CERTIFICATE----- Hellenic Academic and Research Institutions RootCA 2011 ======================================================= -----BEGIN CERTIFICATE----- MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 -----END CERTIFICATE----- Actalis Authentication Root CA ============================== -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- Buypass Class 2 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN rJgWVqA= -----END CERTIFICATE----- Buypass Class 3 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi Cp/HuZc= -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 3 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 2009 ============================== -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 EV 2009 ================================= -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv w9y4AyHqnxbxLFS1 -----END CERTIFICATE----- CA Disig Root R2 ================ -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV 7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- ACCVRAIZ1 ========= -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p EfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- TWCA Global Root CA =================== -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= -----END CERTIFICATE----- TeliaSonera Root CA v1 ====================== -----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- E-Tugra Certification Authority =============================== -----BEGIN CERTIFICATE----- MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G C7TbO6Orb1wdtn7os4I07QZcJA== -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 2 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== -----END CERTIFICATE----- Atos TrustedRoot 2011 ===================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- QuoVadis Root CA 1 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV hMJKzRwuJIczYOXD -----END CERTIFICATE----- QuoVadis Root CA 2 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr O3jtZsSOeWmD3n+M -----END CERTIFICATE----- QuoVadis Root CA 3 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- DigiCert Assured ID Root G2 =========================== -----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- DigiCert Assured ID Root G3 =========================== -----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy 1vUhZscv6pZjamVFkpUBtA== -----END CERTIFICATE----- DigiCert Global Root G2 ======================= -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- DigiCert Global Root G3 ======================= -----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 VOKa5Vt8sycX -----END CERTIFICATE----- DigiCert Trusted Root G4 ======================== -----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP 82Z+ -----END CERTIFICATE----- COMODO RSA Certification Authority ================================== -----BEGIN CERTIFICATE----- MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I LaZRfyHBNVOFBkpdn627G190 -----END CERTIFICATE----- USERTrust RSA Certification Authority ===================================== -----BEGIN CERTIFICATE----- MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- USERTrust ECC Certification Authority ===================================== -----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -----END CERTIFICATE----- GlobalSign ECC Root CA - R4 =========================== -----BEGIN CERTIFICATE----- MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= -----END CERTIFICATE----- GlobalSign ECC Root CA - R5 =========================== -----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- Staat der Nederlanden EV Root CA ================================ -----BEGIN CERTIFICATE----- MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== -----END CERTIFICATE----- IdenTrust Commercial Root CA 1 ============================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R cGzM7vRX+Bi6hG6H -----END CERTIFICATE----- IdenTrust Public Sector Root CA 1 ================================= -----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ 3Wl9af0AVqW3rLatt8o+Ae+c -----END CERTIFICATE----- Entrust Root Certification Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO e4pIb4tF9g== -----END CERTIFICATE----- Entrust Root Certification Authority - EC1 ========================================== -----BEGIN CERTIFICATE----- MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G -----END CERTIFICATE----- CFCA EV ROOT ============ -----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- OISTE WISeKey Global Root GB CA =============================== -----BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -----END CERTIFICATE----- SZAFIR ROOT CA2 =============== -----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== -----END CERTIFICATE----- Certum Trusted Network CA 2 =========================== -----BEGIN CERTIFICATE----- MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 zAYspsbiDrW5viSP -----END CERTIFICATE----- Hellenic Academic and Research Institutions RootCA 2015 ======================================================= -----BEGIN CERTIFICATE----- MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q p/UsQu0yrbYhnr68 -----END CERTIFICATE----- Hellenic Academic and Research Institutions ECC RootCA 2015 =========================================================== -----BEGIN CERTIFICATE----- MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- ISRG Root X1 ============ -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ m+kXQ99b21/+jh5Xos1AnX5iItreGCc= -----END CERTIFICATE----- AC RAIZ FNMT-RCM ================ -----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= -----END CERTIFICATE----- Amazon Root CA 1 ================ -----BEGIN CERTIFICATE----- MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 -----END CERTIFICATE----- Amazon Root CA 2 ================ -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= -----END CERTIFICATE----- Amazon Root CA 3 ================ -----BEGIN CERTIFICATE----- MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== -----END CERTIFICATE----- Amazon Root CA 4 ================ -----BEGIN CERTIFICATE----- MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== -----END CERTIFICATE----- TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 ============================================= -----BEGIN CERTIFICATE----- MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= -----END CERTIFICATE----- GDCA TrustAUTH R5 ROOT ====================== -----BEGIN CERTIFICATE----- MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== -----END CERTIFICATE----- TrustCor RootCert CA-1 ====================== -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw /Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P 3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= -----END CERTIFICATE----- TrustCor RootCert CA-2 ====================== -----BEGIN CERTIFICATE----- MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0 eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0 IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1 oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1 /p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh 8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU 2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv 2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3 S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ -----END CERTIFICATE----- TrustCor ECA-1 ============== -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u /ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== -----END CERTIFICATE----- SSL.com Root Certification Authority RSA ======================================== -----BEGIN CERTIFICATE----- MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= -----END CERTIFICATE----- SSL.com Root Certification Authority ECC ======================================== -----BEGIN CERTIFICATE----- MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl -----END CERTIFICATE----- SSL.com EV Root Certification Authority RSA R2 ============================================== -----BEGIN CERTIFICATE----- MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== -----END CERTIFICATE----- SSL.com EV Root Certification Authority ECC =========================================== -----BEGIN CERTIFICATE----- MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== -----END CERTIFICATE----- GlobalSign Root CA - R6 ======================= -----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE 3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP 0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr 3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= -----END CERTIFICATE----- OISTE WISeKey Global Root GC CA =============================== -----BEGIN CERTIFICATE----- MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 -----END CERTIFICATE----- GTS Root R1 =========== -----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx 9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly 4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr 06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om 3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq 4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0 sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql CFF1pkgl -----END CERTIFICATE----- GTS Root R2 =========== -----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo 7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy 5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ +YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ 7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld o/DUhgkC -----END CERTIFICATE----- GTS Root R3 =========== -----BEGIN CERTIFICATE----- MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP 0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0 glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa KaqW04MjyaR7YbPMAuhd -----END CERTIFICATE----- GTS Root R4 =========== -----BEGIN CERTIFICATE----- MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa 6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV 2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x zPKwTdb+mciUqXWi4w== -----END CERTIFICATE----- UCA Global G2 Root ================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV 8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa 4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo 5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== -----END CERTIFICATE----- UCA Extended Validation Root ============================ -----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR 59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH 0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS 3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb +7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr dhh2n1ax -----END CERTIFICATE----- Certigna Root CA ================ -----BEGIN CERTIFICATE----- MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq 4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ /TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of 1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq 7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd 8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS 6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= -----END CERTIFICATE----- emSign Root CA - G1 =================== -----BEGIN CERTIFICATE----- MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ 6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q +Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx iN66zB+Afko= -----END CERTIFICATE----- emSign ECC Root CA - G3 ======================= -----BEGIN CERTIFICATE----- MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc 58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj -----END CERTIFICATE----- emSign Root CA - C1 =================== -----BEGIN CERTIFICATE----- MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp /6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= -----END CERTIFICATE----- emSign ECC Root CA - C3 ======================= -----BEGIN CERTIFICATE----- MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd 6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== -----END CERTIFICATE----- Hongkong Post Root CA 3 ======================= -----BEGIN CERTIFICATE----- MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim 5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj 0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h +bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov +BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw 9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB 60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq dBb9HxEGmpv0 -----END CERTIFICATE----- Entrust Root Certification Authority - G4 ========================================= -----BEGIN CERTIFICATE----- MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV 3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds 8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV 7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht 7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G +TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT kcpG2om3PVODLAgfi49T3f+sHw== -----END CERTIFICATE----- Microsoft ECC Root Certificate Authority 2017 ============================================= -----BEGIN CERTIFICATE----- MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM +Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= -----END CERTIFICATE----- Microsoft RSA Root Certificate Authority 2017 ============================================= -----BEGIN CERTIFICATE----- MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml 7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ 0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og 6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk +ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex /2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE 7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D 5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E -----END CERTIFICATE----- e-Szigno Root CA 2017 ===================== -----BEGIN CERTIFICATE----- MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO svxyqltZ+efcMQ== -----END CERTIFICATE----- certSIGN Root CA G2 =================== -----BEGIN CERTIFICATE----- MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf 95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB /AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N 0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= -----END CERTIFICATE----- Trustwave Global Certification Authority ======================================== -----BEGIN CERTIFICATE----- MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm +9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla 4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O 856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu 3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP 29FpHOTKyeC2nOnOcXHebD8WpHk= -----END CERTIFICATE----- Trustwave Global ECC P256 Certification Authority ================================================= -----BEGIN CERTIFICATE----- MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj 43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt 0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 -----END CERTIFICATE----- Trustwave Global ECC P384 Certification Authority ================================================= -----BEGIN CERTIFICATE----- MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr /TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== -----END CERTIFICATE----- NAVER Global Root Certification Authority ========================================= -----BEGIN CERTIFICATE----- MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW +j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK 21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg kpzNNIaRkPpkUZ3+/uul9XXeifdy -----END CERTIFICATE----- AC RAIZ FNMT-RCM SERVIDORES SEGUROS =================================== -----BEGIN CERTIFICATE----- MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= -----END CERTIFICATE----- GlobalSign Root R46 =================== -----BEGIN CERTIFICATE----- MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje 2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 QEUxeCp6 -----END CERTIFICATE----- GlobalSign Root E46 =================== -----BEGIN CERTIFICATE----- MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ CAezNIm8BZ/3Hobui3A= -----END CERTIFICATE----- GLOBALTRUST 2020 ================ -----BEGIN CERTIFICATE----- MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw 4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS 8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== -----END CERTIFICATE----- ANF Secure Server Root CA ========================= -----BEGIN CERTIFICATE----- MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4 NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j 7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe 8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM 5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb 5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54 EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3 r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= -----END CERTIFICATE----- Certum EC-384 CA ================ -----BEGIN CERTIFICATE----- MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= -----END CERTIFICATE----- Certum Trusted Root CA ====================== -----BEGIN CERTIFICATE----- MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52 HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2 fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4 NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8 CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA 4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj 6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb -----END CERTIFICATE----- perl5/Mozilla/CA.pm000044400000002764152462503210010032 0ustar00package Mozilla::CA; use strict; our $VERSION = '20211001'; use Cwd (); use File::Spec (); use File::Basename qw(dirname); sub SSL_ca_file { my $file = File::Spec->catfile(dirname(__FILE__), "CA", "cacert.pem"); if (!File::Spec->file_name_is_absolute($file)) { $file = File::Spec->catfile(Cwd::cwd(), $file); } return $file; } 1; __END__ =head1 NAME Mozilla::CA - Mozilla's CA cert bundle in PEM format =head1 SYNOPSIS use IO::Socket::SSL; use Mozilla::CA; my $host = "www.paypal.com"; my $client = IO::Socket::SSL->new( PeerHost => "$host:443", SSL_verify_mode => 0x02, SSL_ca_file => Mozilla::CA::SSL_ca_file(), ) || die "Can't connect: $@"; $client->verify_hostname($host, "http") || die "hostname verification failure"; =head1 DESCRIPTION Mozilla::CA provides a copy of Mozilla's bundle of Certificate Authority certificates in a form that can be consumed by modules and libraries based on OpenSSL. The module provide a single function: =over =item SSL_ca_file() Returns the absolute path to the Mozilla's CA cert bundle PEM file. =back =head1 SEE ALSO L =head1 LICENSE For the bundled Mozilla CA PEM file the following applies: =over This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. =back The Mozilla::CA distribution itself is available under the same license. perl5/JSON/PP.pm000044400000304257152462503210007232 0ustar00package JSON::PP; # JSON-2.0 use 5.005; use strict; use Exporter (); BEGIN { @JSON::PP::ISA = ('Exporter') } use overload (); use JSON::PP::Boolean; use Carp (); #use Devel::Peek; $JSON::PP::VERSION = '4.06'; @JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json); # instead of hash-access, i tried index-access for speed. # but this method is not faster than what i expected. so it will be changed. use constant P_ASCII => 0; use constant P_LATIN1 => 1; use constant P_UTF8 => 2; use constant P_INDENT => 3; use constant P_CANONICAL => 4; use constant P_SPACE_BEFORE => 5; use constant P_SPACE_AFTER => 6; use constant P_ALLOW_NONREF => 7; use constant P_SHRINK => 8; use constant P_ALLOW_BLESSED => 9; use constant P_CONVERT_BLESSED => 10; use constant P_RELAXED => 11; use constant P_LOOSE => 12; use constant P_ALLOW_BIGNUM => 13; use constant P_ALLOW_BAREKEY => 14; use constant P_ALLOW_SINGLEQUOTE => 15; use constant P_ESCAPE_SLASH => 16; use constant P_AS_NONBLESSED => 17; use constant P_ALLOW_UNKNOWN => 18; use constant P_ALLOW_TAGS => 19; use constant OLD_PERL => $] < 5.008 ? 1 : 0; use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0; BEGIN { if (USE_B) { require B; } } BEGIN { my @xs_compati_bit_properties = qw( latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink allow_blessed convert_blessed relaxed allow_unknown allow_tags ); my @pp_bit_properties = qw( allow_singlequote allow_bignum loose allow_barekey escape_slash as_nonblessed ); # Perl version check, Unicode handling is enabled? # Helper module sets @JSON::PP::_properties. if ( OLD_PERL ) { my $helper = $] >= 5.006 ? 'JSON::PP::Compat5006' : 'JSON::PP::Compat5005'; eval qq| require $helper |; if ($@) { Carp::croak $@; } } for my $name (@xs_compati_bit_properties, @pp_bit_properties) { my $property_id = 'P_' . uc($name); eval qq/ sub $name { my \$enable = defined \$_[1] ? \$_[1] : 1; if (\$enable) { \$_[0]->{PROPS}->[$property_id] = 1; } else { \$_[0]->{PROPS}->[$property_id] = 0; } \$_[0]; } sub get_$name { \$_[0]->{PROPS}->[$property_id] ? 1 : ''; } /; } } # Functions my $JSON; # cache sub encode_json ($) { # encode ($JSON ||= __PACKAGE__->new->utf8)->encode(@_); } sub decode_json { # decode ($JSON ||= __PACKAGE__->new->utf8)->decode(@_); } # Obsoleted sub to_json($) { Carp::croak ("JSON::PP::to_json has been renamed to encode_json."); } sub from_json($) { Carp::croak ("JSON::PP::from_json has been renamed to decode_json."); } # Methods sub new { my $class = shift; my $self = { max_depth => 512, max_size => 0, indent_length => 3, }; $self->{PROPS}[P_ALLOW_NONREF] = 1; bless $self, $class; } sub encode { return $_[0]->PP_encode_json($_[1]); } sub decode { return $_[0]->PP_decode_json($_[1], 0x00000000); } sub decode_prefix { return $_[0]->PP_decode_json($_[1], 0x00000001); } # accessor # pretty printing sub pretty { my ($self, $v) = @_; my $enable = defined $v ? $v : 1; if ($enable) { # indent_length(3) for JSON::XS compatibility $self->indent(1)->space_before(1)->space_after(1); } else { $self->indent(0)->space_before(0)->space_after(0); } $self; } # etc sub max_depth { my $max = defined $_[1] ? $_[1] : 0x80000000; $_[0]->{max_depth} = $max; $_[0]; } sub get_max_depth { $_[0]->{max_depth}; } sub max_size { my $max = defined $_[1] ? $_[1] : 0; $_[0]->{max_size} = $max; $_[0]; } sub get_max_size { $_[0]->{max_size}; } sub boolean_values { my $self = shift; if (@_) { my ($false, $true) = @_; $self->{false} = $false; $self->{true} = $true; } else { delete $self->{false}; delete $self->{true}; } return $self; } sub get_boolean_values { my $self = shift; if (exists $self->{true} and exists $self->{false}) { return @$self{qw/false true/}; } return; } sub filter_json_object { if (defined $_[1] and ref $_[1] eq 'CODE') { $_[0]->{cb_object} = $_[1]; } else { delete $_[0]->{cb_object}; } $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0; $_[0]; } sub filter_json_single_key_object { if (@_ == 1 or @_ > 3) { Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)"); } if (defined $_[2] and ref $_[2] eq 'CODE') { $_[0]->{cb_sk_object}->{$_[1]} = $_[2]; } else { delete $_[0]->{cb_sk_object}->{$_[1]}; delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}}; } $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0; $_[0]; } sub indent_length { if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) { Carp::carp "The acceptable range of indent_length() is 0 to 15."; } else { $_[0]->{indent_length} = $_[1]; } $_[0]; } sub get_indent_length { $_[0]->{indent_length}; } sub sort_by { $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1; $_[0]; } sub allow_bigint { Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead."); $_[0]->allow_bignum; } ############################### ### ### Perl => JSON ### { # Convert my $max_depth; my $indent; my $ascii; my $latin1; my $utf8; my $space_before; my $space_after; my $canonical; my $allow_blessed; my $convert_blessed; my $indent_length; my $escape_slash; my $bignum; my $as_nonblessed; my $allow_tags; my $depth; my $indent_count; my $keysort; sub PP_encode_json { my $self = shift; my $obj = shift; $indent_count = 0; $depth = 0; my $props = $self->{PROPS}; ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed, $convert_blessed, $escape_slash, $bignum, $as_nonblessed, $allow_tags) = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED, P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS]; ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/}; $keysort = $canonical ? sub { $a cmp $b } : undef; if ($self->{sort_by}) { $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by} : $self->{sort_by} =~ /\D+/ ? $self->{sort_by} : sub { $a cmp $b }; } encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)") if(!ref $obj and !$props->[ P_ALLOW_NONREF ]); my $str = $self->object_to_json($obj); $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible unless ($ascii or $latin1 or $utf8) { utf8::upgrade($str); } if ($props->[ P_SHRINK ]) { utf8::downgrade($str, 1); } return $str; } sub object_to_json { my ($self, $obj) = @_; my $type = ref($obj); if($type eq 'HASH'){ return $self->hash_to_json($obj); } elsif($type eq 'ARRAY'){ return $self->array_to_json($obj); } elsif ($type) { # blessed object? if (blessed($obj)) { return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') ); if ( $allow_tags and $obj->can('FREEZE') ) { my $obj_class = ref $obj || $obj; $obj = bless $obj, $obj_class; my @results = $obj->FREEZE('JSON'); if ( @results and ref $results[0] ) { if ( refaddr( $obj ) eq refaddr( $results[0] ) ) { encode_error( sprintf( "%s::FREEZE method returned same object as was passed instead of a new one", ref $obj ) ); } } return '("'.$obj_class.'")['.join(',', @results).']'; } if ( $convert_blessed and $obj->can('TO_JSON') ) { my $result = $obj->TO_JSON(); if ( defined $result and ref( $result ) ) { if ( refaddr( $obj ) eq refaddr( $result ) ) { encode_error( sprintf( "%s::TO_JSON method returned same object as was passed instead of a new one", ref $obj ) ); } } return $self->object_to_json( $result ); } return "$obj" if ( $bignum and _is_bignum($obj) ); if ($allow_blessed) { return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed. return 'null'; } encode_error( sprintf("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", $obj) ); } else { return $self->value_to_json($obj); } } else{ return $self->value_to_json($obj); } } sub hash_to_json { my ($self, $obj) = @_; my @res; encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)") if (++$depth > $max_depth); my ($pre, $post) = $indent ? $self->_up_indent() : ('', ''); my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : ''); for my $k ( _sort( $obj ) ) { if ( OLD_PERL ) { utf8::decode($k) } # key for Perl 5.6 / be optimized push @res, $self->string_to_json( $k ) . $del . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) ); } --$depth; $self->_down_indent() if ($indent); return '{}' unless @res; return '{' . $pre . join( ",$pre", @res ) . $post . '}'; } sub array_to_json { my ($self, $obj) = @_; my @res; encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)") if (++$depth > $max_depth); my ($pre, $post) = $indent ? $self->_up_indent() : ('', ''); for my $v (@$obj){ push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v); } --$depth; $self->_down_indent() if ($indent); return '[]' unless @res; return '[' . $pre . join( ",$pre", @res ) . $post . ']'; } sub _looks_like_number { my $value = shift; if (USE_B) { my $b_obj = B::svref_2object(\$value); my $flags = $b_obj->FLAGS; return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() ); return; } else { no warnings 'numeric'; # if the utf8 flag is on, it almost certainly started as a string return if utf8::is_utf8($value); # detect numbers # string & "" -> "" # number & "" -> 0 (with warning) # nan and inf can detect as numbers, so check with * 0 return unless length((my $dummy = "") & $value); return unless 0 + $value eq $value; return 1 if $value * 0 == 0; return -1; # inf/nan } } sub value_to_json { my ($self, $value) = @_; return 'null' if(!defined $value); my $type = ref($value); if (!$type) { if (_looks_like_number($value)) { return $value; } return $self->string_to_json($value); } elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){ return $$value == 1 ? 'true' : 'false'; } else { if ((overload::StrVal($value) =~ /=(\w+)/)[0]) { return $self->value_to_json("$value"); } if ($type eq 'SCALAR' and defined $$value) { return $$value eq '1' ? 'true' : $$value eq '0' ? 'false' : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null' : encode_error("cannot encode reference to scalar"); } if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) { return 'null'; } else { if ( $type eq 'SCALAR' or $type eq 'REF' ) { encode_error("cannot encode reference to scalar"); } else { encode_error("encountered $value, but JSON can only represent references to arrays or hashes"); } } } } my %esc = ( "\n" => '\n', "\r" => '\r', "\t" => '\t', "\f" => '\f', "\b" => '\b', "\"" => '\"', "\\" => '\\\\', "\'" => '\\\'', ); sub string_to_json { my ($self, $arg) = @_; $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g; $arg =~ s/\//\\\//g if ($escape_slash); $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg; if ($ascii) { $arg = JSON_PP_encode_ascii($arg); } if ($latin1) { $arg = JSON_PP_encode_latin1($arg); } if ($utf8) { utf8::encode($arg); } return '"' . $arg . '"'; } sub blessed_to_json { my $reftype = reftype($_[1]) || ''; if ($reftype eq 'HASH') { return $_[0]->hash_to_json($_[1]); } elsif ($reftype eq 'ARRAY') { return $_[0]->array_to_json($_[1]); } else { return 'null'; } } sub encode_error { my $error = shift; Carp::croak "$error"; } sub _sort { defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]}; } sub _up_indent { my $self = shift; my $space = ' ' x $indent_length; my ($pre,$post) = ('',''); $post = "\n" . $space x $indent_count; $indent_count++; $pre = "\n" . $space x $indent_count; return ($pre,$post); } sub _down_indent { $indent_count--; } sub PP_encode_box { { depth => $depth, indent_count => $indent_count, }; } } # Convert sub _encode_ascii { join('', map { $_ <= 127 ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); } unpack('U*', $_[0]) ); } sub _encode_latin1 { join('', map { $_ <= 255 ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); } unpack('U*', $_[0]) ); } sub _encode_surrogates { # from perlunicode my $uni = $_[0] - 0x10000; return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00); } sub _is_bignum { $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat'); } # # JSON => Perl # my $max_intsize; BEGIN { my $checkint = 1111; for my $d (5..64) { $checkint .= 1; my $int = eval qq| $checkint |; if ($int =~ /[eE]/) { $max_intsize = $d - 1; last; } } } { # PARSE my %escapes = ( # by Jeremy Muhlich b => "\x8", t => "\x9", n => "\xA", f => "\xC", r => "\xD", '\\' => '\\', '"' => '"', '/' => '/', ); my $text; # json data my $at; # offset my $ch; # first character my $len; # text length (changed according to UTF8 or NON UTF8) # INTERNAL my $depth; # nest counter my $encoding; # json text encoding my $is_valid_utf8; # temp variable my $utf8_len; # utf8 byte length # FLAGS my $utf8; # must be utf8 my $max_depth; # max nest number of objects and arrays my $max_size; my $relaxed; my $cb_object; my $cb_sk_object; my $F_HOOK; my $allow_bignum; # using Math::BigInt/BigFloat my $singlequote; # loosely quoting my $loose; # my $allow_barekey; # bareKey my $allow_tags; my $alt_true; my $alt_false; sub _detect_utf_encoding { my $text = shift; my @octets = unpack('C4', $text); return 'unknown' unless defined $octets[3]; return ( $octets[0] and $octets[1]) ? 'UTF-8' : (!$octets[0] and $octets[1]) ? 'UTF-16BE' : (!$octets[0] and !$octets[1]) ? 'UTF-32BE' : ( $octets[2] ) ? 'UTF-16LE' : (!$octets[2] ) ? 'UTF-32LE' : 'unknown'; } sub PP_decode_json { my ($self, $want_offset); ($self, $text, $want_offset) = @_; ($at, $ch, $depth) = (0, '', 0); if ( !defined $text or ref $text ) { decode_error("malformed JSON string, neither array, object, number, string or atom"); } my $props = $self->{PROPS}; ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags) = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS]; ($alt_true, $alt_false) = @$self{qw/true false/}; if ( $utf8 ) { $encoding = _detect_utf_encoding($text); if ($encoding ne 'UTF-8' and $encoding ne 'unknown') { require Encode; Encode::from_to($text, $encoding, 'utf-8'); } else { utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry"); } } else { utf8::upgrade( $text ); utf8::encode( $text ); } $len = length $text; ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK) = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/}; if ($max_size > 1) { use bytes; my $bytes = length $text; decode_error( sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s" , $bytes, $max_size), 1 ) if ($bytes > $max_size); } white(); # remove head white space decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $ch; # Is there a first character for JSON structure? my $result = value(); if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) { decode_error( 'JSON text must be an object or array (but found number, string, true, false or null,' . ' use allow_nonref to allow this)', 1); } Carp::croak('something wrong.') if $len < $at; # we won't arrive here. my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length white(); # remove tail white space return ( $result, $consumed ) if $want_offset; # all right if decode_prefix decode_error("garbage after JSON object") if defined $ch; $result; } sub next_chr { return $ch = undef if($at >= $len); $ch = substr($text, $at++, 1); } sub value { white(); return if(!defined $ch); return object() if($ch eq '{'); return array() if($ch eq '['); return tag() if($ch eq '('); return string() if($ch eq '"' or ($singlequote and $ch eq "'")); return number() if($ch =~ /[0-9]/ or $ch eq '-'); return word(); } sub string { my $utf16; my $is_utf8; ($is_valid_utf8, $utf8_len) = ('', 0); my $s = ''; # basically UTF8 flag on if($ch eq '"' or ($singlequote and $ch eq "'")){ my $boundChar = $ch; OUTER: while( defined(next_chr()) ){ if($ch eq $boundChar){ next_chr(); if ($utf16) { decode_error("missing low surrogate character in surrogate pair"); } utf8::decode($s) if($is_utf8); return $s; } elsif($ch eq '\\'){ next_chr(); if(exists $escapes{$ch}){ $s .= $escapes{$ch}; } elsif($ch eq 'u'){ # UNICODE handling my $u = ''; for(1..4){ $ch = next_chr(); last OUTER if($ch !~ /[0-9a-fA-F]/); $u .= $ch; } # U+D800 - U+DBFF if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate? $utf16 = $u; } # U+DC00 - U+DFFF elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate? unless (defined $utf16) { decode_error("missing high surrogate character in surrogate pair"); } $is_utf8 = 1; $s .= JSON_PP_decode_surrogates($utf16, $u) || next; $utf16 = undef; } else { if (defined $utf16) { decode_error("surrogate pair expected"); } if ( ( my $hex = hex( $u ) ) > 127 ) { $is_utf8 = 1; $s .= JSON_PP_decode_unicode($u) || next; } else { $s .= chr $hex; } } } else{ unless ($loose) { $at -= 2; decode_error('illegal backslash escape sequence in string'); } $s .= $ch; } } else{ if ( ord $ch > 127 ) { unless( $ch = is_valid_utf8($ch) ) { $at -= 1; decode_error("malformed UTF-8 character in JSON string"); } else { $at += $utf8_len - 1; } $is_utf8 = 1; } if (!$loose) { if ($ch =~ /[\x00-\x1f\x22\x5c]/) { # '/' ok if (!$relaxed or $ch ne "\t") { $at--; decode_error('invalid character encountered while parsing JSON string'); } } } $s .= $ch; } } } decode_error("unexpected end of string while parsing JSON string"); } sub white { while( defined $ch ){ if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){ next_chr(); } elsif($relaxed and $ch eq '/'){ next_chr(); if(defined $ch and $ch eq '/'){ 1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r"); } elsif(defined $ch and $ch eq '*'){ next_chr(); while(1){ if(defined $ch){ if($ch eq '*'){ if(defined(next_chr()) and $ch eq '/'){ next_chr(); last; } } else{ next_chr(); } } else{ decode_error("Unterminated comment"); } } next; } else{ $at--; decode_error("malformed JSON string, neither array, object, number, string or atom"); } } else{ if ($relaxed and $ch eq '#') { # correctly? pos($text) = $at; $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g; $at = pos($text); next_chr; next; } last; } } } sub array { my $a = $_[0] || []; # you can use this code to use another array ref object. decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)') if (++$depth > $max_depth); next_chr(); white(); if(defined $ch and $ch eq ']'){ --$depth; next_chr(); return $a; } else { while(defined($ch)){ push @$a, value(); white(); if (!defined $ch) { last; } if($ch eq ']'){ --$depth; next_chr(); return $a; } if($ch ne ','){ last; } next_chr(); white(); if ($relaxed and $ch eq ']') { --$depth; next_chr(); return $a; } } } $at-- if defined $ch and $ch ne ''; decode_error(", or ] expected while parsing array"); } sub tag { decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags; next_chr(); white(); my $tag = value(); return unless defined $tag; decode_error('malformed JSON string, (tag) must be a string') if ref $tag; white(); if (!defined $ch or $ch ne ')') { decode_error(') expected after tag'); } next_chr(); white(); my $val = value(); return unless defined $val; decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY'; if (!eval { $tag->can('THAW') }) { decode_error('cannot decode perl-object (package does not exist)') if $@; decode_error('cannot decode perl-object (package does not have a THAW method)'); } $tag->THAW('JSON', @$val); } sub object { my $o = $_[0] || {}; # you can use this code to use another hash ref object. my $k; decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)') if (++$depth > $max_depth); next_chr(); white(); if(defined $ch and $ch eq '}'){ --$depth; next_chr(); if ($F_HOOK) { return _json_object_hook($o); } return $o; } else { while (defined $ch) { $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string(); white(); if(!defined $ch or $ch ne ':'){ $at--; decode_error("':' expected"); } next_chr(); $o->{$k} = value(); white(); last if (!defined $ch); if($ch eq '}'){ --$depth; next_chr(); if ($F_HOOK) { return _json_object_hook($o); } return $o; } if($ch ne ','){ last; } next_chr(); white(); if ($relaxed and $ch eq '}') { --$depth; next_chr(); if ($F_HOOK) { return _json_object_hook($o); } return $o; } } } $at-- if defined $ch and $ch ne ''; decode_error(", or } expected while parsing object/hash"); } sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition my $key; while($ch =~ /[^\x00-\x23\x25-\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/){ $key .= $ch; next_chr(); } return $key; } sub word { my $word = substr($text,$at-1,4); if($word eq 'true'){ $at += 3; next_chr; return defined $alt_true ? $alt_true : $JSON::PP::true; } elsif($word eq 'null'){ $at += 3; next_chr; return undef; } elsif($word eq 'fals'){ $at += 3; if(substr($text,$at,1) eq 'e'){ $at++; next_chr; return defined $alt_false ? $alt_false : $JSON::PP::false; } } $at--; # for decode_error report decode_error("'null' expected") if ($word =~ /^n/); decode_error("'true' expected") if ($word =~ /^t/); decode_error("'false' expected") if ($word =~ /^f/); decode_error("malformed JSON string, neither array, object, number, string or atom"); } sub number { my $n = ''; my $v; my $is_dec; my $is_exp; if($ch eq '-'){ $n = '-'; next_chr; if (!defined $ch or $ch !~ /\d/) { decode_error("malformed number (no digits after initial minus)"); } } # According to RFC4627, hex or oct digits are invalid. if($ch eq '0'){ my $peek = substr($text,$at,1); if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential) decode_error("malformed number (leading zero must not be followed by another digit)"); } $n .= $ch; next_chr; } while(defined $ch and $ch =~ /\d/){ $n .= $ch; next_chr; } if(defined $ch and $ch eq '.'){ $n .= '.'; $is_dec = 1; next_chr; if (!defined $ch or $ch !~ /\d/) { decode_error("malformed number (no digits after decimal point)"); } else { $n .= $ch; } while(defined(next_chr) and $ch =~ /\d/){ $n .= $ch; } } if(defined $ch and ($ch eq 'e' or $ch eq 'E')){ $n .= $ch; $is_exp = 1; next_chr; if(defined($ch) and ($ch eq '+' or $ch eq '-')){ $n .= $ch; next_chr; if (!defined $ch or $ch =~ /\D/) { decode_error("malformed number (no digits after exp sign)"); } $n .= $ch; } elsif(defined($ch) and $ch =~ /\d/){ $n .= $ch; } else { decode_error("malformed number (no digits after exp sign)"); } while(defined(next_chr) and $ch =~ /\d/){ $n .= $ch; } } $v .= $n; if ($is_dec or $is_exp) { if ($allow_bignum) { require Math::BigFloat; return Math::BigFloat->new($v); } } else { if (length $v > $max_intsize) { if ($allow_bignum) { # from Adam Sussman require Math::BigInt; return Math::BigInt->new($v); } else { return "$v"; } } } return $is_dec ? $v/1.0 : 0+$v; } sub is_valid_utf8 { $utf8_len = $_[0] =~ /[\x00-\x7F]/ ? 1 : $_[0] =~ /[\xC2-\xDF]/ ? 2 : $_[0] =~ /[\xE0-\xEF]/ ? 3 : $_[0] =~ /[\xF0-\xF4]/ ? 4 : 0 ; return unless $utf8_len; my $is_valid_utf8 = substr($text, $at - 1, $utf8_len); return ( $is_valid_utf8 =~ /^(?: [\x00-\x7F] |[\xC2-\xDF][\x80-\xBF] |[\xE0][\xA0-\xBF][\x80-\xBF] |[\xE1-\xEC][\x80-\xBF][\x80-\xBF] |[\xED][\x80-\x9F][\x80-\xBF] |[\xEE-\xEF][\x80-\xBF][\x80-\xBF] |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF] |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF] |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF] )$/x ) ? $is_valid_utf8 : ''; } sub decode_error { my $error = shift; my $no_rep = shift; my $str = defined $text ? substr($text, $at) : ''; my $mess = ''; my $type = 'U*'; if ( OLD_PERL ) { my $type = $] < 5.006 ? 'C*' : utf8::is_utf8( $str ) ? 'U*' # 5.6 : 'C*' ; } for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ? $mess .= $c == 0x07 ? '\a' : $c == 0x09 ? '\t' : $c == 0x0a ? '\n' : $c == 0x0d ? '\r' : $c == 0x0c ? '\f' : $c < 0x20 ? sprintf('\x{%x}', $c) : $c == 0x5c ? '\\\\' : $c < 0x80 ? chr($c) : sprintf('\x{%x}', $c) ; if ( length $mess >= 20 ) { $mess .= '...'; last; } } unless ( length $mess ) { $mess = '(end of string)'; } Carp::croak ( $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")" ); } sub _json_object_hook { my $o = $_[0]; my @ks = keys %{$o}; if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) { my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} ); if (@val == 0) { return $o; } elsif (@val == 1) { return $val[0]; } else { Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar"); } } my @val = $cb_object->($o) if ($cb_object); if (@val == 0) { return $o; } elsif (@val == 1) { return $val[0]; } else { Carp::croak("filter_json_object callbacks must not return more than one scalar"); } } sub PP_decode_box { { text => $text, at => $at, ch => $ch, len => $len, depth => $depth, encoding => $encoding, is_valid_utf8 => $is_valid_utf8, }; } } # PARSE sub _decode_surrogates { # from perlunicode my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00); my $un = pack('U*', $uni); utf8::encode( $un ); return $un; } sub _decode_unicode { my $un = pack('U', hex shift); utf8::encode( $un ); return $un; } # # Setup for various Perl versions (the code from JSON::PP58) # BEGIN { unless ( defined &utf8::is_utf8 ) { require Encode; *utf8::is_utf8 = *Encode::is_utf8; } if ( !OLD_PERL ) { *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates; *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode; if ($] < 5.008003) { # join() in 5.8.0 - 5.8.2 is broken. package JSON::PP; require subs; subs->import('join'); eval q| sub join { return '' if (@_ < 2); my $j = shift; my $str = shift; for (@_) { $str .= $j . $_; } return $str; } |; } } sub JSON::PP::incr_parse { local $Carp::CarpLevel = 1; ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ ); } sub JSON::PP::incr_skip { ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip; } sub JSON::PP::incr_reset { ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset; } eval q{ sub JSON::PP::incr_text : lvalue { $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new; if ( $_[0]->{_incr_parser}->{incr_pos} ) { Carp::croak("incr_text cannot be called when the incremental parser already started parsing"); } $_[0]->{_incr_parser}->{incr_text}; } } if ( $] >= 5.006 ); } # Setup for various Perl versions (the code from JSON::PP58) ############################### # Utilities # BEGIN { eval 'require Scalar::Util'; unless($@){ *JSON::PP::blessed = \&Scalar::Util::blessed; *JSON::PP::reftype = \&Scalar::Util::reftype; *JSON::PP::refaddr = \&Scalar::Util::refaddr; } else{ # This code is from Scalar::Util. # warn $@; eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }'; *JSON::PP::blessed = sub { local($@, $SIG{__DIE__}, $SIG{__WARN__}); ref($_[0]) ? eval { $_[0]->a_sub_not_likely_to_be_here } : undef; }; require B; my %tmap = qw( B::NULL SCALAR B::HV HASH B::AV ARRAY B::CV CODE B::IO IO B::GV GLOB B::REGEXP REGEXP ); *JSON::PP::reftype = sub { my $r = shift; return undef unless length(ref($r)); my $t = ref(B::svref_2object($r)); return exists $tmap{$t} ? $tmap{$t} : length(ref($$r)) ? 'REF' : 'SCALAR'; }; *JSON::PP::refaddr = sub { return undef unless length(ref($_[0])); my $addr; if(defined(my $pkg = blessed($_[0]))) { $addr .= bless $_[0], 'Scalar::Util::Fake'; bless $_[0], $pkg; } else { $addr .= $_[0] } $addr =~ /0x(\w+)/; local $^W; #no warnings 'portable'; hex($1); } } } # shamelessly copied and modified from JSON::XS code. $JSON::PP::true = do { bless \(my $dummy = 1), "JSON::PP::Boolean" }; $JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" }; sub is_bool { blessed $_[0] and ( $_[0]->isa("JSON::PP::Boolean") or $_[0]->isa("Types::Serialiser::BooleanBase") or $_[0]->isa("JSON::XS::Boolean") ); } sub true { $JSON::PP::true } sub false { $JSON::PP::false } sub null { undef; } ############################### package JSON::PP::IncrParser; use strict; use constant INCR_M_WS => 0; # initial whitespace skipping use constant INCR_M_STR => 1; # inside string use constant INCR_M_BS => 2; # inside backslash use constant INCR_M_JSON => 3; # outside anything, count nesting use constant INCR_M_C0 => 4; use constant INCR_M_C1 => 5; use constant INCR_M_TFN => 6; use constant INCR_M_NUM => 7; $JSON::PP::IncrParser::VERSION = '1.01'; sub new { my ( $class ) = @_; bless { incr_nest => 0, incr_text => undef, incr_pos => 0, incr_mode => 0, }, $class; } sub incr_parse { my ( $self, $coder, $text ) = @_; $self->{incr_text} = '' unless ( defined $self->{incr_text} ); if ( defined $text ) { if ( utf8::is_utf8( $text ) and !utf8::is_utf8( $self->{incr_text} ) ) { utf8::upgrade( $self->{incr_text} ) ; utf8::decode( $self->{incr_text} ) ; } $self->{incr_text} .= $text; } if ( defined wantarray ) { my $max_size = $coder->get_max_size; my $p = $self->{incr_pos}; my @ret; { do { unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) { $self->_incr_parse( $coder ); if ( $max_size and $self->{incr_pos} > $max_size ) { Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size"); } unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) { # as an optimisation, do not accumulate white space in the incr buffer if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) { $self->{incr_pos} = 0; $self->{incr_text} = ''; } last; } } my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 ); push @ret, $obj; use bytes; $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 ); $self->{incr_pos} = 0; $self->{incr_nest} = 0; $self->{incr_mode} = 0; last unless wantarray; } while ( wantarray ); } if ( wantarray ) { return @ret; } else { # in scalar context return defined $ret[0] ? $ret[0] : undef; } } } sub _incr_parse { my ($self, $coder) = @_; my $text = $self->{incr_text}; my $len = length $text; my $p = $self->{incr_pos}; INCR_PARSE: while ( $len > $p ) { my $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; my $mode = $self->{incr_mode}; if ( $mode == INCR_M_WS ) { while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; if ( ord($s) > 0x20 ) { if ( $s eq '#' ) { $self->{incr_mode} = INCR_M_C0; redo INCR_PARSE; } else { $self->{incr_mode} = INCR_M_JSON; redo INCR_PARSE; } } $p++; } } elsif ( $mode == INCR_M_BS ) { $p++; $self->{incr_mode} = INCR_M_STR; redo INCR_PARSE; } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) { while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; if ( $s eq "\n" ) { $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON; last; } $p++; } next; } elsif ( $mode == INCR_M_TFN ) { while ( $len > $p ) { $s = substr( $text, $p++, 1 ); next if defined $s and $s =~ /[rueals]/; last; } $p--; $self->{incr_mode} = INCR_M_JSON; last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $mode == INCR_M_NUM ) { while ( $len > $p ) { $s = substr( $text, $p++, 1 ); next if defined $s and $s =~ /[0-9eE.+\-]/; last; } $p--; $self->{incr_mode} = INCR_M_JSON; last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $mode == INCR_M_STR ) { while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; if ( $s eq '"' ) { $p++; $self->{incr_mode} = INCR_M_JSON; last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $s eq '\\' ) { $p++; if ( !defined substr($text, $p, 1) ) { $self->{incr_mode} = INCR_M_BS; last INCR_PARSE; } } $p++; } } elsif ( $mode == INCR_M_JSON ) { while ( $len > $p ) { $s = substr( $text, $p++, 1 ); if ( $s eq "\x00" ) { $p--; last INCR_PARSE; } elsif ( $s eq "\x09" or $s eq "\x0a" or $s eq "\x0d" or $s eq "\x20" ) { if ( !$self->{incr_nest} ) { $p--; # do not eat the whitespace, let the next round do it last INCR_PARSE; } next; } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) { $self->{incr_mode} = INCR_M_TFN; redo INCR_PARSE; } elsif ( $s =~ /^[0-9\-]$/ ) { $self->{incr_mode} = INCR_M_NUM; redo INCR_PARSE; } elsif ( $s eq '"' ) { $self->{incr_mode} = INCR_M_STR; redo INCR_PARSE; } elsif ( $s eq '[' or $s eq '{' ) { if ( ++$self->{incr_nest} > $coder->get_max_depth ) { Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)'); } next; } elsif ( $s eq ']' or $s eq '}' ) { if ( --$self->{incr_nest} <= 0 ) { last INCR_PARSE; } } elsif ( $s eq '#' ) { $self->{incr_mode} = INCR_M_C1; redo INCR_PARSE; } } } } $self->{incr_pos} = $p; $self->{incr_parsing} = $p ? 1 : 0; # for backward compatibility } sub incr_text { if ( $_[0]->{incr_pos} ) { Carp::croak("incr_text cannot be called when the incremental parser already started parsing"); } $_[0]->{incr_text}; } sub incr_skip { my $self = shift; $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} ); $self->{incr_pos} = 0; $self->{incr_mode} = 0; $self->{incr_nest} = 0; } sub incr_reset { my $self = shift; $self->{incr_text} = undef; $self->{incr_pos} = 0; $self->{incr_mode} = 0; $self->{incr_nest} = 0; } ############################### 1; __END__ =pod =head1 NAME JSON::PP - JSON::XS compatible pure-Perl module. =head1 SYNOPSIS use JSON::PP; # exported functions, they croak on error # and expect/generate UTF-8 $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; # OO-interface $json = JSON::PP->new->ascii->pretty->allow_nonref; $pretty_printed_json_text = $json->encode( $perl_scalar ); $perl_scalar = $json->decode( $json_text ); # Note that JSON version 2.0 and above will automatically use # JSON::XS or JSON::PP, so you should be able to just: use JSON; =head1 VERSION 4.05 =head1 DESCRIPTION JSON::PP is a pure perl JSON decoder/encoder, and (almost) compatible to much faster L written by Marc Lehmann in C. JSON::PP works as a fallback module when you use L module without having installed JSON::XS. Because of this fallback feature of JSON.pm, JSON::PP tries not to be more JavaScript-friendly than JSON::XS (i.e. not to escape extra characters such as U+2028 and U+2029, etc), in order for you not to lose such JavaScript-friendliness silently when you use JSON.pm and install JSON::XS for speed or by accident. If you need JavaScript-friendly RFC7159-compliant pure perl module, try L, which is derived from L web framework and is also smaller and faster than JSON::PP. JSON::PP has been in the Perl core since Perl 5.14, mainly for CPAN toolchain modules to parse META.json. =head1 FUNCTIONAL INTERFACE This section is taken from JSON::XS almost verbatim. C and C are exported by default. =head2 encode_json $json_text = encode_json $perl_scalar Converts the given Perl data structure to a UTF-8 encoded, binary string (that is, the string contains octets only). Croaks on error. This function call is functionally identical to: $json_text = JSON::PP->new->utf8->encode($perl_scalar) Except being faster. =head2 decode_json $perl_scalar = decode_json $json_text The opposite of C: expects an UTF-8 (binary) string and tries to parse that as an UTF-8 encoded JSON text, returning the resulting reference. Croaks on error. This function call is functionally identical to: $perl_scalar = JSON::PP->new->utf8->decode($json_text) Except being faster. =head2 JSON::PP::is_bool $is_boolean = JSON::PP::is_bool($scalar) Returns true if the passed scalar represents either JSON::PP::true or JSON::PP::false, two constants that act like C<1> and C<0> respectively and are also used to represent JSON C and C in Perl strings. See L, below, for more information on how JSON values are mapped to Perl. =head1 OBJECT-ORIENTED INTERFACE This section is also taken from JSON::XS. The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. =head2 new $json = JSON::PP->new Creates a new JSON::PP object that can be used to de/encode JSON strings. All boolean flags described below are by default I (with the exception of C, which defaults to I since version C<4.0>). The mutators for flags all return the JSON::PP object again and thus calls can be chained: my $json = JSON::PP->new->utf8->space_after->encode({a => [1,2]}) => {"a": [1, 2]} =head2 ascii $json = $json->ascii([$enable]) $enabled = $json->get_ascii If C<$enable> is true (or missing), then the C method will not generate characters outside the code range C<0..127> (which is ASCII). Any Unicode characters outside that range will be escaped using either a single \uXXXX (BMP characters) or a double \uHHHH\uLLLLL escape sequence, as per RFC4627. The resulting encoded JSON text can be treated as a native Unicode string, an ascii-encoded, latin1-encoded or UTF-8 encoded string, or any other superset of ASCII. If C<$enable> is false, then the C method will not escape Unicode characters unless required by the JSON syntax or other flags. This results in a faster and more compact format. See also the section I later in this document. The main use for this flag is to produce JSON texts that can be transmitted over a 7-bit channel, as the encoded JSON texts will not contain any 8 bit characters. JSON::PP->new->ascii(1)->encode([chr 0x10401]) => ["\ud801\udc01"] =head2 latin1 $json = $json->latin1([$enable]) $enabled = $json->get_latin1 If C<$enable> is true (or missing), then the C method will encode the resulting JSON text as latin1 (or iso-8859-1), escaping any characters outside the code range C<0..255>. The resulting string can be treated as a latin1-encoded JSON text or a native Unicode string. The C method will not be affected in any way by this flag, as C by default expects Unicode, which is a strict superset of latin1. If C<$enable> is false, then the C method will not escape Unicode characters unless required by the JSON syntax or other flags. See also the section I later in this document. The main use for this flag is efficiently encoding binary data as JSON text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting JSON text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for JSON. It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other JSON encoders/decoders. JSON::PP->new->latin1->encode (["\x{89}\x{abc}"] => ["\x{89}\\u0abc"] # (perl syntax, U+abc escaped, U+89 not) =head2 utf8 $json = $json->utf8([$enable]) $enabled = $json->get_utf8 If C<$enable> is true (or missing), then the C method will encode the JSON result into UTF-8, as required by many protocols, while the C method expects to be handled an UTF-8-encoded string. Please note that UTF-8-encoded strings do not contain any characters outside the range C<0..255>, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the UTF-16 and UTF-32 encoding families, as described in RFC4627. If C<$enable> is false, then the C method will return the JSON string as a (non-encoded) Unicode string, while C expects thus a Unicode string. Any decoding or encoding (e.g. to UTF-8 or UTF-16) needs to be done yourself, e.g. using the Encode module. See also the section I later in this document. Example, output UTF-16BE-encoded JSON: use Encode; $jsontext = encode "UTF-16BE", JSON::PP->new->encode ($object); Example, decode UTF-32LE-encoded JSON: use Encode; $object = JSON::PP->new->decode (decode "UTF-32LE", $jsontext); =head2 pretty $json = $json->pretty([$enable]) This enables (or disables) all of the C, C and C (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. =head2 indent $json = $json->indent([$enable]) $enabled = $json->get_indent If C<$enable> is true (or missing), then the C method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. If C<$enable> is false, no newlines or indenting will be produced, and the resulting JSON text is guaranteed not to contain any C. This setting has no effect when decoding JSON texts. The default indent space length is three. You can use C to change the length. =head2 space_before $json = $json->space_before([$enable]) $enabled = $json->get_space_before If C<$enable> is true (or missing), then the C method will add an extra optional space before the C<:> separating keys from values in JSON objects. If C<$enable> is false, then the C method will not add any extra space at those places. This setting has no effect when decoding JSON texts. You will also most likely combine this setting with C. Example, space_before enabled, space_after and indent disabled: {"key" :"value"} =head2 space_after $json = $json->space_after([$enable]) $enabled = $json->get_space_after If C<$enable> is true (or missing), then the C method will add an extra optional space after the C<:> separating keys from values in JSON objects and extra whitespace after the C<,> separating key-value pairs and array members. If C<$enable> is false, then the C method will not add any extra space at those places. This setting has no effect when decoding JSON texts. Example, space_before and indent disabled, space_after enabled: {"key": "value"} =head2 relaxed $json = $json->relaxed([$enable]) $enabled = $json->get_relaxed If C<$enable> is true (or missing), then C will accept some extensions to normal JSON syntax (see below). C will not be affected in anyway. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. Currently accepted extensions are: =over 4 =item * list items can have an end-comma JSON I array elements and key-value pairs with commas. This can be annoying if you write JSON texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: [ 1, 2, <- this comma not normally allowed ] { "k1": "v1", "k2": "v2", <- this comma not normally allowed } =item * shell-style '#'-comments Whenever JSON allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. [ 1, # this comment not allowed in JSON # neither this one... ] =item * C-style multiple-line '/* */'-comments (JSON::PP only) Whenever JSON allows whitespace, C-style multiple-line comments are additionally allowed. Everything between C and C<*/> is a comment, after which more white-space and comments are allowed. [ 1, /* this comment not allowed in JSON */ /* neither this one... */ ] =item * C++-style one-line '//'-comments (JSON::PP only) Whenever JSON allows whitespace, C++-style one-line comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. [ 1, // this comment not allowed in JSON // neither this one... ] =item * literal ASCII TAB characters in strings Literal ASCII TAB characters are now allowed in strings (and treated as C<\t>). [ "Hello\tWorld", "HelloWorld", # literal would not normally be allowed ] =back =head2 canonical $json = $json->canonical([$enable]) $enabled = $json->get_canonical If C<$enable> is true (or missing), then the C method will output JSON objects by sorting their keys. This is adding a comparatively high overhead. If C<$enable> is false, then the C method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). This option is useful if you want the same data structure to be encoded as the same JSON text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. This setting has no effect when decoding JSON texts. This setting has currently no effect on tied hashes. =head2 allow_nonref $json = $json->allow_nonref([$enable]) $enabled = $json->get_allow_nonref Unlike other boolean options, this opotion is enabled by default beginning with version C<4.0>. If C<$enable> is true (or missing), then the C method can convert a non-reference into its corresponding string, number or null JSON value, which is an extension to RFC4627. Likewise, C will accept those JSON values instead of croaking. If C<$enable> is false, then the C method will croak if it isn't passed an arrayref or hashref, as JSON texts must either be an object or array. Likewise, C will croak if given something that is not a JSON object or array. Example, encode a Perl scalar as JSON value without enabled C, resulting in an error: JSON::PP->new->allow_nonref(0)->encode ("Hello, World!") => hash- or arrayref expected... =head2 allow_unknown $json = $json->allow_unknown([$enable]) $enabled = $json->get_allow_unknown If C<$enable> is true (or missing), then C will I throw an exception when it encounters values it cannot represent in JSON (for example, filehandles) but instead will encode a JSON C value. Note that blessed objects are not included here and are handled separately by c. If C<$enable> is false (the default), then C will throw an exception when it encounters anything it cannot encode as JSON. This option does not affect C in any way, and it is recommended to leave it off unless you know your communications partner. =head2 allow_blessed $json = $json->allow_blessed([$enable]) $enabled = $json->get_allow_blessed See L for details. If C<$enable> is true (or missing), then the C method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a JSON C value is encoded instead of the object. If C<$enable> is false (the default), then C will throw an exception when it encounters a blessed object that it cannot convert otherwise. This setting has no effect on C. =head2 convert_blessed $json = $json->convert_blessed([$enable]) $enabled = $json->get_convert_blessed See L for details. If C<$enable> is true (or missing), then C, upon encountering a blessed object, will check for the availability of the C method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. The C method may safely call die if it wants. If C returns other blessed objects, those will be handled in the same way. C must take care of not causing an endless recursion cycle (== crash) in this case. The name of C was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any C function or method. If C<$enable> is false (the default), then C will not consider this type of conversion. This setting has no effect on C. =head2 allow_tags $json = $json->allow_tags([$enable]) $enabled = $json->get_allow_tags See L for details. If C<$enable> is true (or missing), then C, upon encountering a blessed object, will check for the availability of the C method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged JSON value (that JSON decoders cannot decode). It also causes C to parse such tagged JSON values and deserialise them via a call to the C method. If C<$enable> is false (the default), then C will not consider this type of conversion, and tagged JSON values will cause a parse error in C, as if tags were not part of the grammar. =head2 boolean_values $json->boolean_values([$false, $true]) ($false, $true) = $json->get_boolean_values By default, JSON booleans will be decoded as overloaded C<$JSON::PP::false> and C<$JSON::PP::true> objects. With this method you can specify your own boolean values for decoding - on decode, JSON C will be decoded as a copy of C<$false>, and JSON C will be decoded as C<$true> ("copy" here is the same thing as assigning a value to another variable, i.e. C<$copy = $false>). This is useful when you want to pass a decoded data structure directly to other serialisers like YAML, Data::MessagePack and so on. Note that this works only when you C. You can set incompatible boolean objects (like L), but when you C a data structure with such boolean objects, you still need to enable C (and add a C method if necessary). Calling this method without any arguments will reset the booleans to their default values. C will return both C<$false> and C<$true> values, or the empty list when they are set to the default. =head2 filter_json_object $json = $json->filter_json_object([$coderef]) When C<$coderef> is specified, it will be called from C each time it decodes a JSON object. The only argument is a reference to the newly-created hash. If the code references returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (NOTE: I C, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. When C<$coderef> is omitted or undefined, any existing callback will be removed and C will not change the deserialised hash in any way. Example, convert all JSON objects into the integer 5: my $js = JSON::PP->new->filter_json_object(sub { 5 }); # returns [5] $js->decode('[{}]'); # returns 5 $js->decode('{"a":1, "b":2}'); =head2 filter_json_single_key_object $json = $json->filter_json_single_key_object($key [=> $coderef]) Works remotely similar to C, but is only called for JSON objects having a single key named C<$key>. This C<$coderef> is called before the one specified via C, if any. It gets passed the single value in the JSON object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even C but the empty list), the callback from C will be called next, as if no single-key callback were specified. If C<$coderef> is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. As this callback gets called less often then the C one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key JSON objects are as close to the type-tagged value concept as JSON gets (it's basically an ID/VALUE tuple). Of course, JSON does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. Typical names for the single object key are C<__class_whatever__>, or C<$__dollars_are_rarely_used__$> or C<}ugly_brace_placement>, or even things like C<__class_md5sum(classname)__>, to reduce the risk of clashing with real hashes. Example, decode JSON objects of the form C<< { "__widget__" => } >> into the corresponding C<< $WIDGET{} >> object: # return whatever is in $WIDGET{5}: JSON::PP ->new ->filter_json_single_key_object (__widget__ => sub { $WIDGET{ $_[0] } }) ->decode ('{"__widget__": 5') # this can be used with a TO_JSON method in some "widget" class # for serialisation to json: sub WidgetBase::TO_JSON { my ($self) = @_; unless ($self->{id}) { $self->{id} = ..get..some..id..; $WIDGET{$self->{id}} = $self; } { __widget__ => $self->{id} } } =head2 shrink $json = $json->shrink([$enable]) $enabled = $json->get_shrink If C<$enable> is true (or missing), the string returned by C will be shrunk (i.e. downgraded if possible). The actual definition of what shrink does might change in future versions, but it will always try to save space at the expense of time. If C<$enable> is false, then JSON::PP does nothing. =head2 max_depth $json = $json->max_depth([$maximum_nesting_depth]) $max_depth = $json->get_max_depth Sets the maximum nesting level (default C<512>) accepted while encoding or decoding. If a higher nesting level is detected in JSON text or a Perl data structure, then the encoder and decoder will stop and croak at that point. Nesting level is defined by number of hash- or arrayrefs that the encoder needs to traverse to reach a given point or the number of C<{> or C<[> characters without their matching closing parenthesis crossed to reach a given character in a string. Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. If no argument is given, the highest possible setting will be used, which is rarely useful. See L for more info on why this is useful. =head2 max_size $json = $json->max_size([$maximum_string_size]) $max_size = $json->get_max_size Set the maximum length a JSON text may have (in bytes) where decoding is being attempted. The default is C<0>, meaning no limit. When C is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on C (yet). If no argument is given, the limit check will be deactivated (same as when C<0> is specified). See L for more info on why this is useful. =head2 encode $json_text = $json->encode($perl_scalar) Converts the given Perl value or data structure to its JSON representation. Croaks on error. =head2 decode $perl_scalar = $json->decode($json_text) The opposite of C: expects a JSON text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. =head2 decode_prefix ($perl_scalar, $characters) = $json->decode_prefix($json_text) This works like the C method, but instead of raising an exception when there is trailing garbage after the first JSON object, it will silently stop parsing there and return the number of characters consumed so far. This is useful if your JSON texts are not delimited by an outer protocol and you need to know where the JSON text ends. JSON::PP->new->decode_prefix ("[1] the tail") => ([1], 3) =head1 FLAGS FOR JSON::PP ONLY The following flags and properties are for JSON::PP only. If you use any of these, you can't make your application run faster by replacing JSON::PP with JSON::XS. If you need these and also speed boost, you might want to try L, a fork of JSON::XS by Reini Urban, which supports some of these (with a different set of incompatibilities). Most of these historical flags are only kept for backward compatibility, and should not be used in a new application. =head2 allow_singlequote $json = $json->allow_singlequote([$enable]) $enabled = $json->get_allow_singlequote If C<$enable> is true (or missing), then C will accept invalid JSON texts that contain strings that begin and end with single quotation marks. C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. $json->allow_singlequote->decode(qq|{"foo":'bar'}|); $json->allow_singlequote->decode(qq|{'foo':"bar"}|); $json->allow_singlequote->decode(qq|{'foo':'bar'}|); =head2 allow_barekey $json = $json->allow_barekey([$enable]) $enabled = $json->get_allow_barekey If C<$enable> is true (or missing), then C will accept invalid JSON texts that contain JSON objects whose names don't begin and end with quotation marks. C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. $json->allow_barekey->decode(qq|{foo:"bar"}|); =head2 allow_bignum $json = $json->allow_bignum([$enable]) $enabled = $json->get_allow_bignum If C<$enable> is true (or missing), then C will convert big integers Perl cannot handle as integer into L objects and convert floating numbers into L objects. C will convert C and C objects into JSON numbers. $json->allow_nonref->allow_bignum; $bigfloat = $json->decode('2.000000000000000000000000001'); print $json->encode($bigfloat); # => 2.000000000000000000000000001 See also L. =head2 loose $json = $json->loose([$enable]) $enabled = $json->get_loose If C<$enable> is true (or missing), then C will accept invalid JSON texts that contain unescaped [\x00-\x1f\x22\x5c] characters. C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. $json->loose->decode(qq|["abc def"]|); =head2 escape_slash $json = $json->escape_slash([$enable]) $enabled = $json->get_escape_slash If C<$enable> is true (or missing), then C will explicitly escape I (solidus; C) characters to reduce the risk of XSS (cross site scripting) that may be caused by C<< >> in a JSON text, with the cost of bloating the size of JSON texts. This option may be useful when you embed JSON in HTML, but embedding arbitrary JSON in HTML (by some HTML template toolkit or by string interpolation) is risky in general. You must escape necessary characters in correct order, depending on the context. C will not be affected in any way. =head2 indent_length $json = $json->indent_length($number_of_spaces) $length = $json->get_indent_length This option is only useful when you also enable C or C. JSON::XS indents with three spaces when you C (if requested by C or C), and the number cannot be changed. JSON::PP allows you to change/get the number of indent spaces with these mutator/accessor. The default number of spaces is three (the same as JSON::XS), and the acceptable range is from C<0> (no indentation; it'd be better to disable indentation by C) to C<15>. =head2 sort_by $json = $json->sort_by($code_ref) $json = $json->sort_by($subroutine_name) If you just want to sort keys (names) in JSON objects when you C, enable C option (see above) that allows you to sort object keys alphabetically. If you do need to sort non-alphabetically for whatever reasons, you can give a code reference (or a subroutine name) to C, then the argument will be passed to Perl's C built-in function. As the sorting is done in the JSON::PP scope, you usually need to prepend C to the subroutine name, and the special variables C<$a> and C<$b> used in the subrontine used by C function. Example: my %ORDER = (id => 1, class => 2, name => 3); $json->sort_by(sub { ($ORDER{$JSON::PP::a} // 999) <=> ($ORDER{$JSON::PP::b} // 999) or $JSON::PP::a cmp $JSON::PP::b }); print $json->encode([ {name => 'CPAN', id => 1, href => 'http://cpan.org'} ]); # [{"id":1,"name":"CPAN","href":"http://cpan.org"}] Note that C affects all the plain hashes in the data structure. If you need finer control, C necessary hashes with a module that implements ordered hash (such as L and L). C and C don't affect the key order in Cd hashes. use Hash::Ordered; tie my %hash, 'Hash::Ordered', (name => 'CPAN', id => 1, href => 'http://cpan.org'); print $json->encode([\%hash]); # [{"name":"CPAN","id":1,"href":"http://cpan.org"}] # order is kept =head1 INCREMENTAL PARSING This section is also taken from JSON::XS. In some cases, there is the need for incremental parsing of JSON texts. While this module always has to keep both JSON text and resulting Perl data structure in memory at one time, it does allow you to parse a JSON stream incrementally. It does so by accumulating text until it has a full JSON object, which it then can decode. This process is similar to using C to see if a full JSON object is available, but is much more efficient (and can be implemented with a minimum of method calls). JSON::PP will only attempt to parse the JSON text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid JSON text has been seen. This means you need to set resource limits (e.g. C) to ensure the parser will stop parsing in the presence if syntax errors. The following methods implement this incremental parser. =head2 incr_parse $json->incr_parse( [$string] ) # void context $obj_or_undef = $json->incr_parse( [$string] ) # scalar context @obj_or_empty = $json->incr_parse( [$string] ) # list context This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). If C<$string> is given, then this string is appended to the already existing JSON fragment stored in the C<$json> object. After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. If the method is called in scalar context, then it will try to extract exactly I JSON object. If that is successful, it will return this object, otherwise it will return C. If there is a parse error, this method will croak just as C would do (one can then use C to skip the erroneous part). This is the most common way of using the method. And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the JSON objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed JSON texts will be lost. Example: Parse some JSON arrays/objects in a given string and return them. my @objs = JSON::PP->new->incr_parse ("[5][7][1,2]"); =head2 incr_text $lvalue_string = $json->incr_text This method returns the currently stored JSON fragment as an lvalue, that is, you can manipulate it. This I works when a preceding call to C in I successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it I fail under real world conditions). As a special exception, you can also call this method before having parsed anything. That means you can only use this function to look at or manipulate text before or after complete JSON objects, not while the parser is in the middle of parsing a JSON object. This function is useful in two cases: a) finding the trailing text after a JSON object or b) parsing multiple JSON objects separated by non-JSON text (such as commas). =head2 incr_skip $json->incr_skip This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after C died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. The difference to C is that only text until the parse error occurred is removed. =head2 incr_reset $json->incr_reset This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. This is useful if you want to repeatedly parse JSON objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. =head1 MAPPING Most of this section is also taken from JSON::XS. This section describes how JSON::PP maps Perl values to JSON values and vice versa. These mappings are designed to "do the right thing" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). For the more enlightened: note that in the following descriptions, lowercase I refers to the Perl interpreter, while uppercase I refers to the abstract Perl language itself. =head2 JSON -> PERL =over 4 =item object A JSON object becomes a reference to a hash in Perl. No ordering of object keys is preserved (JSON does not preserve object key ordering itself). =item array A JSON array becomes a reference to an array in Perl. =item string A JSON string becomes a string scalar in Perl - Unicode codepoints in JSON are represented by the same codepoints in the Perl string, so no manual decoding is necessary. =item number A JSON number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. If the number consists of digits only, JSON::PP will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the JSON number will be re-encoded to a JSON string). Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the JSON number will still be re-encoded as a JSON number). Note that precision is not accuracy - binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, JSON::PP only guarantees precision up to but not including the least significant bit. When C is enabled, big integer values and any numeric values will be converted into L and L objects respectively, without becoming string scalars or losing precision. =item true, false These JSON atoms become C and C, respectively. They are overloaded to act almost exactly like the numbers C<1> and C<0>. You can check whether a scalar is a JSON boolean by using the C function. =item null A JSON null atom becomes C in Perl. =item shell-style comments (C<< # I >>) As a nonstandard extension to the JSON syntax that is enabled by the C setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. =item tagged values (C<< (I)I >>). Another nonstandard extension to the JSON syntax, enabled with the C setting, are tagged values. In this implementation, the I must be a perl package/class name encoded as a JSON string, and the I must be a JSON array encoding optional constructor arguments. See L, below, for details. =back =head2 PERL -> JSON The mapping from Perl to JSON is slightly more difficult, as Perl is a truly typeless language, so we can only guess which JSON type is meant by a Perl value. =over 4 =item hash references Perl hash references become JSON objects. As there is no inherent ordering in hash keys (or JSON objects), they will usually be encoded in a pseudo-random order. JSON::PP can optionally sort the hash keys (determined by the I flag and/or I property), so the same data structure will serialise to the same JSON text (given same settings and version of JSON::PP), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some JSON text against another for equality. =item array references Perl array references become JSON arrays. =item other references Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers C<0> and C<1>, which get turned into C and C atoms in JSON. You can also use C and C to improve readability. to_json [\0, JSON::PP::true] # yields [false,true] =item JSON::PP::true, JSON::PP::false These special values become JSON true and JSON false values, respectively. You can also use C<\1> and C<\0> directly if you want. =item JSON::PP::null This special value becomes JSON null. =item blessed objects Blessed objects are not directly representable in JSON, but C allows various ways of handling objects. See L, below, for details. =item simple scalars Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: JSON::PP will encode undefined scalars as JSON C values, scalars that have last been used in a string context before encoding as JSON strings, and anything else as number value: # dump as number encode_json [2] # yields [2] encode_json [-3.0e17] # yields [-3e+17] my $value = 5; encode_json [$value] # yields [5] # used as string, so dump as string print $value; encode_json [$value] # yields ["5"] # undef becomes null encode_json [undef] # yields [null] You can force the type to be a JSON string by stringifying it: my $x = 3.1; # some variable containing a number "$x"; # stringified $x .= ""; # another, more awkward way to stringify print $x; # perl does it for you, too, quite often # (but for older perls) You can force the type to be a JSON number by numifying it: my $x = "3"; # some variable containing a string $x += 0; # numify it, ensuring it will be dumped as a number $x *= 1; # same thing, the choice is yours. You can not currently force the type in other, less obscure, ways. Since version 2.91_01, JSON::PP uses a different number detection logic that converts a scalar that is possible to turn into a number safely. The new logic is slightly faster, and tends to help people who use older perl or who want to encode complicated data structure. However, this may results in a different JSON text from the one JSON::XS encodes (and thus may break tests that compare entire JSON texts). If you do need the previous behavior for compatibility or for finer control, set PERL_JSON_PP_USE_B environmental variable to true before you C JSON::PP (or JSON.pm). Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's - these cannot be represented in JSON, and it is an error to pass those in. JSON::PP (and JSON::XS) trusts what you pass to C method (or C function) is a clean, validated data structure with values that can be represented as valid JSON values only, because it's not from an external data source (as opposed to JSON texts you pass to C or C, which JSON::PP considers tainted and doesn't trust). As JSON::PP doesn't know exactly what you and consumers of your JSON texts want the unexpected values to be (you may want to convert them into null, or to stringify them with or without normalisation (string representation of infinities/NaN may vary depending on platforms), or to croak without conversion), you're advised to do what you and your consumers need before you encode, and also not to numify values that may start with values that look like a number (including infinities/NaN), without validating. =back =head2 OBJECT SERIALISATION As JSON cannot directly represent Perl objects, you have to choose between a pure JSON representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the JSON syntax, tagged values. =head3 SERIALISATION What happens when C encounters a Perl object depends on the C, C, C and C settings, which are used in this order: =over 4 =item 1. C is enabled and the object has a C method. In this case, C creates a tagged JSON value, using a nonstandard extension to the JSON syntax. This works by invoking the C method on the object, with the first argument being the object to serialise, and the second argument being the constant string C to distinguish it from other serialisers. The C method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged JSON value in the following format: ("classname")[FREEZE return values...] e.g.: ("URI")["http://www.google.com/"] ("MyDate")[2013,10,29] ("ImageData::JPEG")["Z3...VlCg=="] For example, the hypothetical C C method might use the objects C and C members to encode the object: sub My::Object::FREEZE { my ($self, $serialiser) = @_; ($self->{type}, $self->{id}) } =item 2. C is enabled and the object has a C method. In this case, the C method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into JSON. This scalar replaces the object in the JSON text. For example, the following C method will convert all L objects to JSON strings when serialised. The fact that these values originally were L objects is lost. sub URI::TO_JSON { my ($uri) = @_; $uri->as_string } =item 3. C is enabled and the object is a C or C. The object will be serialised as a JSON number value. =item 4. C is enabled. The object will be serialised as a JSON null value. =item 5. none of the above If none of the settings are enabled or the respective methods are missing, C throws an exception. =back =head3 DESERIALISATION For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case C decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the C or C callbacks to get some real objects our of your JSON. This section only considers the tagged value case: a tagged JSON object is encountered during decoding and C is disabled, a parse error will result (as if tagged values were not part of the grammar). If C is enabled, C will look up the C method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. Otherwise, the C method is invoked with the classname as first argument, the constant string C as second argument, and all the values from the JSON array (the values originally returned by the C method) as remaining arguments. The method must then return the object. While technically you can return any Perl scalar, you might have to enable the C setting to make that work in all cases, so better return an actual blessed reference. As an example, let's implement a C function that regenerates the C from the C example earlier: sub My::Object::THAW { my ($class, $serialiser, $type, $id) = @_; $class->new (type => $type, id => $id) } =head1 ENCODING/CODESET FLAG NOTES This section is taken from JSON::XS. The interested reader might have seen a number of flags that signify encodings or codesets - C, C and C. There seems to be some confusion on what these do, so here is a short comparison: C controls whether the JSON text created by C (and expected by C) is UTF-8 encoded or not, while C and C only control whether C escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. Care has been taken to make all flags symmetrical with respect to C and C, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used - in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. Below comes a verbose discussion of these flags. Note that a "codeset" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and I them, in our case into octets. Unicode is (among other things) a codeset, UTF-8 is an encoding, and ISO-8859-1 (= latin 1) and ASCII are both codesets I encodings at the same time, which can be confusing. =over 4 =item C flag disabled When C is disabled (the default), then C/C generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except "(re-)interpreting" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). This is useful when you want to do the encoding yourself (e.g. when you want to have UTF-16 encoded JSON texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to UTF-8 you certainly do NOT want to UTF-8 encode your data first and have Perl encode it another time). =item C flag enabled If the C-flag is enabled, C/C will encode all characters using the corresponding UTF-8 multi-byte sequence, and will expect your input strings to be encoded as UTF-8, that is, no "character" of the input string must have any value > 255, as UTF-8 does not allow that. The C flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get an UTF-8 encoded octet/binary string in Perl. =item C or C flags enabled With C (or C) enabled, C will escape characters with ordinal values > 255 (> 127 with C) and encode the remaining characters as specified by the C flag. If C is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a ISO-8859-1 string, and a Unicode string with all character values < 128 is the same thing as an ASCII string in Perl). If C is enabled, you still get a correct UTF-8-encoded string, regardless of these flags, just some more characters will be escaped using C<\uXXXX> then before. Note that ISO-8859-1-I strings are not compatible with UTF-8 encoding, while ASCII-encoded strings are. That is because the ISO-8859-1 encoding is NOT a subset of UTF-8 (despite the ISO-8859-1 I being a subset of Unicode), while ASCII is. Surprisingly, C will ignore these flags and so treat all input values as governed by the C flag. If it is disabled, this allows you to decode ISO-8859-1- and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode UTF-8 encoded strings. So neither C nor C are incompatible with the C flag - they only govern when the JSON output engine escapes a character or not. The main use for C is to relatively efficiently store binary data as JSON, at the expense of breaking compatibility with most JSON decoders. The main use for C is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as UTF-8, ISO-8859-1, ASCII, KOI8-R or most about any character set and 8-bit-encoding, and still get the same data structure back. This is useful when your channel for JSON transfer is not 8-bit clean or the encoding might be mangled in between (e.g. in mail), and works because ASCII is a proper subset of most 8-bit and multibyte encodings in use in the world. =back =head1 BUGS Please report bugs on a specific behavior of this module to RT or GitHub issues (preferred): L L As for new features and requests to change common behaviors, please ask the author of JSON::XS (Marc Lehmann, Eschmorp[at]schmorp.deE) first, by email (important!), to keep compatibility among JSON.pm backends. Generally speaking, if you need something special for you, you are advised to create a new module, maybe based on L, which is smaller and written in a much cleaner way than this module. =head1 SEE ALSO The F command line utility for quick experiments. L, L, and L for faster alternatives. L and L for easy migration. L and L for older perl users. RFC4627 (L) RFC7159 (L) RFC8259 (L) =head1 AUTHOR Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE =head1 CURRENT MAINTAINER Kenichi Ishigaki, Eishigaki[at]cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2007-2016 by Makamaka Hannyaharamitu Most of the documentation is taken from JSON::XS by Marc Lehmann This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/JSON/backportPP.pm000044400000304502152462503210010751 0ustar00package # This is JSON::backportPP JSON::PP; # JSON-2.0 use 5.005; use strict; use Exporter (); BEGIN { @JSON::backportPP::ISA = ('Exporter') } use overload (); use JSON::backportPP::Boolean; use Carp (); #use Devel::Peek; $JSON::backportPP::VERSION = '4.06'; @JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json); # instead of hash-access, i tried index-access for speed. # but this method is not faster than what i expected. so it will be changed. use constant P_ASCII => 0; use constant P_LATIN1 => 1; use constant P_UTF8 => 2; use constant P_INDENT => 3; use constant P_CANONICAL => 4; use constant P_SPACE_BEFORE => 5; use constant P_SPACE_AFTER => 6; use constant P_ALLOW_NONREF => 7; use constant P_SHRINK => 8; use constant P_ALLOW_BLESSED => 9; use constant P_CONVERT_BLESSED => 10; use constant P_RELAXED => 11; use constant P_LOOSE => 12; use constant P_ALLOW_BIGNUM => 13; use constant P_ALLOW_BAREKEY => 14; use constant P_ALLOW_SINGLEQUOTE => 15; use constant P_ESCAPE_SLASH => 16; use constant P_AS_NONBLESSED => 17; use constant P_ALLOW_UNKNOWN => 18; use constant P_ALLOW_TAGS => 19; use constant OLD_PERL => $] < 5.008 ? 1 : 0; use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0; BEGIN { if (USE_B) { require B; } } BEGIN { my @xs_compati_bit_properties = qw( latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink allow_blessed convert_blessed relaxed allow_unknown allow_tags ); my @pp_bit_properties = qw( allow_singlequote allow_bignum loose allow_barekey escape_slash as_nonblessed ); # Perl version check, Unicode handling is enabled? # Helper module sets @JSON::PP::_properties. if ( OLD_PERL ) { my $helper = $] >= 5.006 ? 'JSON::backportPP::Compat5006' : 'JSON::backportPP::Compat5005'; eval qq| require $helper |; if ($@) { Carp::croak $@; } } for my $name (@xs_compati_bit_properties, @pp_bit_properties) { my $property_id = 'P_' . uc($name); eval qq/ sub $name { my \$enable = defined \$_[1] ? \$_[1] : 1; if (\$enable) { \$_[0]->{PROPS}->[$property_id] = 1; } else { \$_[0]->{PROPS}->[$property_id] = 0; } \$_[0]; } sub get_$name { \$_[0]->{PROPS}->[$property_id] ? 1 : ''; } /; } } # Functions my $JSON; # cache sub encode_json ($) { # encode ($JSON ||= __PACKAGE__->new->utf8)->encode(@_); } sub decode_json { # decode ($JSON ||= __PACKAGE__->new->utf8)->decode(@_); } # Obsoleted sub to_json($) { Carp::croak ("JSON::PP::to_json has been renamed to encode_json."); } sub from_json($) { Carp::croak ("JSON::PP::from_json has been renamed to decode_json."); } # Methods sub new { my $class = shift; my $self = { max_depth => 512, max_size => 0, indent_length => 3, }; $self->{PROPS}[P_ALLOW_NONREF] = 1; bless $self, $class; } sub encode { return $_[0]->PP_encode_json($_[1]); } sub decode { return $_[0]->PP_decode_json($_[1], 0x00000000); } sub decode_prefix { return $_[0]->PP_decode_json($_[1], 0x00000001); } # accessor # pretty printing sub pretty { my ($self, $v) = @_; my $enable = defined $v ? $v : 1; if ($enable) { # indent_length(3) for JSON::XS compatibility $self->indent(1)->space_before(1)->space_after(1); } else { $self->indent(0)->space_before(0)->space_after(0); } $self; } # etc sub max_depth { my $max = defined $_[1] ? $_[1] : 0x80000000; $_[0]->{max_depth} = $max; $_[0]; } sub get_max_depth { $_[0]->{max_depth}; } sub max_size { my $max = defined $_[1] ? $_[1] : 0; $_[0]->{max_size} = $max; $_[0]; } sub get_max_size { $_[0]->{max_size}; } sub boolean_values { my $self = shift; if (@_) { my ($false, $true) = @_; $self->{false} = $false; $self->{true} = $true; } else { delete $self->{false}; delete $self->{true}; } return $self; } sub get_boolean_values { my $self = shift; if (exists $self->{true} and exists $self->{false}) { return @$self{qw/false true/}; } return; } sub filter_json_object { if (defined $_[1] and ref $_[1] eq 'CODE') { $_[0]->{cb_object} = $_[1]; } else { delete $_[0]->{cb_object}; } $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0; $_[0]; } sub filter_json_single_key_object { if (@_ == 1 or @_ > 3) { Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)"); } if (defined $_[2] and ref $_[2] eq 'CODE') { $_[0]->{cb_sk_object}->{$_[1]} = $_[2]; } else { delete $_[0]->{cb_sk_object}->{$_[1]}; delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}}; } $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0; $_[0]; } sub indent_length { if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) { Carp::carp "The acceptable range of indent_length() is 0 to 15."; } else { $_[0]->{indent_length} = $_[1]; } $_[0]; } sub get_indent_length { $_[0]->{indent_length}; } sub sort_by { $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1; $_[0]; } sub allow_bigint { Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead."); $_[0]->allow_bignum; } ############################### ### ### Perl => JSON ### { # Convert my $max_depth; my $indent; my $ascii; my $latin1; my $utf8; my $space_before; my $space_after; my $canonical; my $allow_blessed; my $convert_blessed; my $indent_length; my $escape_slash; my $bignum; my $as_nonblessed; my $allow_tags; my $depth; my $indent_count; my $keysort; sub PP_encode_json { my $self = shift; my $obj = shift; $indent_count = 0; $depth = 0; my $props = $self->{PROPS}; ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed, $convert_blessed, $escape_slash, $bignum, $as_nonblessed, $allow_tags) = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED, P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS]; ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/}; $keysort = $canonical ? sub { $a cmp $b } : undef; if ($self->{sort_by}) { $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by} : $self->{sort_by} =~ /\D+/ ? $self->{sort_by} : sub { $a cmp $b }; } encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)") if(!ref $obj and !$props->[ P_ALLOW_NONREF ]); my $str = $self->object_to_json($obj); $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible unless ($ascii or $latin1 or $utf8) { utf8::upgrade($str); } if ($props->[ P_SHRINK ]) { utf8::downgrade($str, 1); } return $str; } sub object_to_json { my ($self, $obj) = @_; my $type = ref($obj); if($type eq 'HASH'){ return $self->hash_to_json($obj); } elsif($type eq 'ARRAY'){ return $self->array_to_json($obj); } elsif ($type) { # blessed object? if (blessed($obj)) { return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') ); if ( $allow_tags and $obj->can('FREEZE') ) { my $obj_class = ref $obj || $obj; $obj = bless $obj, $obj_class; my @results = $obj->FREEZE('JSON'); if ( @results and ref $results[0] ) { if ( refaddr( $obj ) eq refaddr( $results[0] ) ) { encode_error( sprintf( "%s::FREEZE method returned same object as was passed instead of a new one", ref $obj ) ); } } return '("'.$obj_class.'")['.join(',', @results).']'; } if ( $convert_blessed and $obj->can('TO_JSON') ) { my $result = $obj->TO_JSON(); if ( defined $result and ref( $result ) ) { if ( refaddr( $obj ) eq refaddr( $result ) ) { encode_error( sprintf( "%s::TO_JSON method returned same object as was passed instead of a new one", ref $obj ) ); } } return $self->object_to_json( $result ); } return "$obj" if ( $bignum and _is_bignum($obj) ); if ($allow_blessed) { return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed. return 'null'; } encode_error( sprintf("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", $obj) ); } else { return $self->value_to_json($obj); } } else{ return $self->value_to_json($obj); } } sub hash_to_json { my ($self, $obj) = @_; my @res; encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)") if (++$depth > $max_depth); my ($pre, $post) = $indent ? $self->_up_indent() : ('', ''); my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : ''); for my $k ( _sort( $obj ) ) { if ( OLD_PERL ) { utf8::decode($k) } # key for Perl 5.6 / be optimized push @res, $self->string_to_json( $k ) . $del . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) ); } --$depth; $self->_down_indent() if ($indent); return '{}' unless @res; return '{' . $pre . join( ",$pre", @res ) . $post . '}'; } sub array_to_json { my ($self, $obj) = @_; my @res; encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)") if (++$depth > $max_depth); my ($pre, $post) = $indent ? $self->_up_indent() : ('', ''); for my $v (@$obj){ push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v); } --$depth; $self->_down_indent() if ($indent); return '[]' unless @res; return '[' . $pre . join( ",$pre", @res ) . $post . ']'; } sub _looks_like_number { my $value = shift; if (USE_B) { my $b_obj = B::svref_2object(\$value); my $flags = $b_obj->FLAGS; return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() ); return; } else { no warnings 'numeric'; # if the utf8 flag is on, it almost certainly started as a string return if utf8::is_utf8($value); # detect numbers # string & "" -> "" # number & "" -> 0 (with warning) # nan and inf can detect as numbers, so check with * 0 return unless length((my $dummy = "") & $value); return unless 0 + $value eq $value; return 1 if $value * 0 == 0; return -1; # inf/nan } } sub value_to_json { my ($self, $value) = @_; return 'null' if(!defined $value); my $type = ref($value); if (!$type) { if (_looks_like_number($value)) { return $value; } return $self->string_to_json($value); } elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){ return $$value == 1 ? 'true' : 'false'; } else { if ((overload::StrVal($value) =~ /=(\w+)/)[0]) { return $self->value_to_json("$value"); } if ($type eq 'SCALAR' and defined $$value) { return $$value eq '1' ? 'true' : $$value eq '0' ? 'false' : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null' : encode_error("cannot encode reference to scalar"); } if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) { return 'null'; } else { if ( $type eq 'SCALAR' or $type eq 'REF' ) { encode_error("cannot encode reference to scalar"); } else { encode_error("encountered $value, but JSON can only represent references to arrays or hashes"); } } } } my %esc = ( "\n" => '\n', "\r" => '\r', "\t" => '\t', "\f" => '\f', "\b" => '\b', "\"" => '\"', "\\" => '\\\\', "\'" => '\\\'', ); sub string_to_json { my ($self, $arg) = @_; $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g; $arg =~ s/\//\\\//g if ($escape_slash); $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg; if ($ascii) { $arg = JSON_PP_encode_ascii($arg); } if ($latin1) { $arg = JSON_PP_encode_latin1($arg); } if ($utf8) { utf8::encode($arg); } return '"' . $arg . '"'; } sub blessed_to_json { my $reftype = reftype($_[1]) || ''; if ($reftype eq 'HASH') { return $_[0]->hash_to_json($_[1]); } elsif ($reftype eq 'ARRAY') { return $_[0]->array_to_json($_[1]); } else { return 'null'; } } sub encode_error { my $error = shift; Carp::croak "$error"; } sub _sort { defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]}; } sub _up_indent { my $self = shift; my $space = ' ' x $indent_length; my ($pre,$post) = ('',''); $post = "\n" . $space x $indent_count; $indent_count++; $pre = "\n" . $space x $indent_count; return ($pre,$post); } sub _down_indent { $indent_count--; } sub PP_encode_box { { depth => $depth, indent_count => $indent_count, }; } } # Convert sub _encode_ascii { join('', map { $_ <= 127 ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); } unpack('U*', $_[0]) ); } sub _encode_latin1 { join('', map { $_ <= 255 ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); } unpack('U*', $_[0]) ); } sub _encode_surrogates { # from perlunicode my $uni = $_[0] - 0x10000; return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00); } sub _is_bignum { $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat'); } # # JSON => Perl # my $max_intsize; BEGIN { my $checkint = 1111; for my $d (5..64) { $checkint .= 1; my $int = eval qq| $checkint |; if ($int =~ /[eE]/) { $max_intsize = $d - 1; last; } } } { # PARSE my %escapes = ( # by Jeremy Muhlich b => "\x8", t => "\x9", n => "\xA", f => "\xC", r => "\xD", '\\' => '\\', '"' => '"', '/' => '/', ); my $text; # json data my $at; # offset my $ch; # first character my $len; # text length (changed according to UTF8 or NON UTF8) # INTERNAL my $depth; # nest counter my $encoding; # json text encoding my $is_valid_utf8; # temp variable my $utf8_len; # utf8 byte length # FLAGS my $utf8; # must be utf8 my $max_depth; # max nest number of objects and arrays my $max_size; my $relaxed; my $cb_object; my $cb_sk_object; my $F_HOOK; my $allow_bignum; # using Math::BigInt/BigFloat my $singlequote; # loosely quoting my $loose; # my $allow_barekey; # bareKey my $allow_tags; my $alt_true; my $alt_false; sub _detect_utf_encoding { my $text = shift; my @octets = unpack('C4', $text); return 'unknown' unless defined $octets[3]; return ( $octets[0] and $octets[1]) ? 'UTF-8' : (!$octets[0] and $octets[1]) ? 'UTF-16BE' : (!$octets[0] and !$octets[1]) ? 'UTF-32BE' : ( $octets[2] ) ? 'UTF-16LE' : (!$octets[2] ) ? 'UTF-32LE' : 'unknown'; } sub PP_decode_json { my ($self, $want_offset); ($self, $text, $want_offset) = @_; ($at, $ch, $depth) = (0, '', 0); if ( !defined $text or ref $text ) { decode_error("malformed JSON string, neither array, object, number, string or atom"); } my $props = $self->{PROPS}; ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags) = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS]; ($alt_true, $alt_false) = @$self{qw/true false/}; if ( $utf8 ) { $encoding = _detect_utf_encoding($text); if ($encoding ne 'UTF-8' and $encoding ne 'unknown') { require Encode; Encode::from_to($text, $encoding, 'utf-8'); } else { utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry"); } } else { utf8::upgrade( $text ); utf8::encode( $text ); } $len = length $text; ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK) = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/}; if ($max_size > 1) { use bytes; my $bytes = length $text; decode_error( sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s" , $bytes, $max_size), 1 ) if ($bytes > $max_size); } white(); # remove head white space decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $ch; # Is there a first character for JSON structure? my $result = value(); if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) { decode_error( 'JSON text must be an object or array (but found number, string, true, false or null,' . ' use allow_nonref to allow this)', 1); } Carp::croak('something wrong.') if $len < $at; # we won't arrive here. my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length white(); # remove tail white space return ( $result, $consumed ) if $want_offset; # all right if decode_prefix decode_error("garbage after JSON object") if defined $ch; $result; } sub next_chr { return $ch = undef if($at >= $len); $ch = substr($text, $at++, 1); } sub value { white(); return if(!defined $ch); return object() if($ch eq '{'); return array() if($ch eq '['); return tag() if($ch eq '('); return string() if($ch eq '"' or ($singlequote and $ch eq "'")); return number() if($ch =~ /[0-9]/ or $ch eq '-'); return word(); } sub string { my $utf16; my $is_utf8; ($is_valid_utf8, $utf8_len) = ('', 0); my $s = ''; # basically UTF8 flag on if($ch eq '"' or ($singlequote and $ch eq "'")){ my $boundChar = $ch; OUTER: while( defined(next_chr()) ){ if($ch eq $boundChar){ next_chr(); if ($utf16) { decode_error("missing low surrogate character in surrogate pair"); } utf8::decode($s) if($is_utf8); return $s; } elsif($ch eq '\\'){ next_chr(); if(exists $escapes{$ch}){ $s .= $escapes{$ch}; } elsif($ch eq 'u'){ # UNICODE handling my $u = ''; for(1..4){ $ch = next_chr(); last OUTER if($ch !~ /[0-9a-fA-F]/); $u .= $ch; } # U+D800 - U+DBFF if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate? $utf16 = $u; } # U+DC00 - U+DFFF elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate? unless (defined $utf16) { decode_error("missing high surrogate character in surrogate pair"); } $is_utf8 = 1; $s .= JSON_PP_decode_surrogates($utf16, $u) || next; $utf16 = undef; } else { if (defined $utf16) { decode_error("surrogate pair expected"); } if ( ( my $hex = hex( $u ) ) > 127 ) { $is_utf8 = 1; $s .= JSON_PP_decode_unicode($u) || next; } else { $s .= chr $hex; } } } else{ unless ($loose) { $at -= 2; decode_error('illegal backslash escape sequence in string'); } $s .= $ch; } } else{ if ( ord $ch > 127 ) { unless( $ch = is_valid_utf8($ch) ) { $at -= 1; decode_error("malformed UTF-8 character in JSON string"); } else { $at += $utf8_len - 1; } $is_utf8 = 1; } if (!$loose) { if ($ch =~ /[\x00-\x1f\x22\x5c]/) { # '/' ok if (!$relaxed or $ch ne "\t") { $at--; decode_error('invalid character encountered while parsing JSON string'); } } } $s .= $ch; } } } decode_error("unexpected end of string while parsing JSON string"); } sub white { while( defined $ch ){ if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){ next_chr(); } elsif($relaxed and $ch eq '/'){ next_chr(); if(defined $ch and $ch eq '/'){ 1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r"); } elsif(defined $ch and $ch eq '*'){ next_chr(); while(1){ if(defined $ch){ if($ch eq '*'){ if(defined(next_chr()) and $ch eq '/'){ next_chr(); last; } } else{ next_chr(); } } else{ decode_error("Unterminated comment"); } } next; } else{ $at--; decode_error("malformed JSON string, neither array, object, number, string or atom"); } } else{ if ($relaxed and $ch eq '#') { # correctly? pos($text) = $at; $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g; $at = pos($text); next_chr; next; } last; } } } sub array { my $a = $_[0] || []; # you can use this code to use another array ref object. decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)') if (++$depth > $max_depth); next_chr(); white(); if(defined $ch and $ch eq ']'){ --$depth; next_chr(); return $a; } else { while(defined($ch)){ push @$a, value(); white(); if (!defined $ch) { last; } if($ch eq ']'){ --$depth; next_chr(); return $a; } if($ch ne ','){ last; } next_chr(); white(); if ($relaxed and $ch eq ']') { --$depth; next_chr(); return $a; } } } $at-- if defined $ch and $ch ne ''; decode_error(", or ] expected while parsing array"); } sub tag { decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags; next_chr(); white(); my $tag = value(); return unless defined $tag; decode_error('malformed JSON string, (tag) must be a string') if ref $tag; white(); if (!defined $ch or $ch ne ')') { decode_error(') expected after tag'); } next_chr(); white(); my $val = value(); return unless defined $val; decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY'; if (!eval { $tag->can('THAW') }) { decode_error('cannot decode perl-object (package does not exist)') if $@; decode_error('cannot decode perl-object (package does not have a THAW method)'); } $tag->THAW('JSON', @$val); } sub object { my $o = $_[0] || {}; # you can use this code to use another hash ref object. my $k; decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)') if (++$depth > $max_depth); next_chr(); white(); if(defined $ch and $ch eq '}'){ --$depth; next_chr(); if ($F_HOOK) { return _json_object_hook($o); } return $o; } else { while (defined $ch) { $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string(); white(); if(!defined $ch or $ch ne ':'){ $at--; decode_error("':' expected"); } next_chr(); $o->{$k} = value(); white(); last if (!defined $ch); if($ch eq '}'){ --$depth; next_chr(); if ($F_HOOK) { return _json_object_hook($o); } return $o; } if($ch ne ','){ last; } next_chr(); white(); if ($relaxed and $ch eq '}') { --$depth; next_chr(); if ($F_HOOK) { return _json_object_hook($o); } return $o; } } } $at-- if defined $ch and $ch ne ''; decode_error(", or } expected while parsing object/hash"); } sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition my $key; while($ch =~ /[^\x00-\x23\x25-\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/){ $key .= $ch; next_chr(); } return $key; } sub word { my $word = substr($text,$at-1,4); if($word eq 'true'){ $at += 3; next_chr; return defined $alt_true ? $alt_true : $JSON::PP::true; } elsif($word eq 'null'){ $at += 3; next_chr; return undef; } elsif($word eq 'fals'){ $at += 3; if(substr($text,$at,1) eq 'e'){ $at++; next_chr; return defined $alt_false ? $alt_false : $JSON::PP::false; } } $at--; # for decode_error report decode_error("'null' expected") if ($word =~ /^n/); decode_error("'true' expected") if ($word =~ /^t/); decode_error("'false' expected") if ($word =~ /^f/); decode_error("malformed JSON string, neither array, object, number, string or atom"); } sub number { my $n = ''; my $v; my $is_dec; my $is_exp; if($ch eq '-'){ $n = '-'; next_chr; if (!defined $ch or $ch !~ /\d/) { decode_error("malformed number (no digits after initial minus)"); } } # According to RFC4627, hex or oct digits are invalid. if($ch eq '0'){ my $peek = substr($text,$at,1); if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential) decode_error("malformed number (leading zero must not be followed by another digit)"); } $n .= $ch; next_chr; } while(defined $ch and $ch =~ /\d/){ $n .= $ch; next_chr; } if(defined $ch and $ch eq '.'){ $n .= '.'; $is_dec = 1; next_chr; if (!defined $ch or $ch !~ /\d/) { decode_error("malformed number (no digits after decimal point)"); } else { $n .= $ch; } while(defined(next_chr) and $ch =~ /\d/){ $n .= $ch; } } if(defined $ch and ($ch eq 'e' or $ch eq 'E')){ $n .= $ch; $is_exp = 1; next_chr; if(defined($ch) and ($ch eq '+' or $ch eq '-')){ $n .= $ch; next_chr; if (!defined $ch or $ch =~ /\D/) { decode_error("malformed number (no digits after exp sign)"); } $n .= $ch; } elsif(defined($ch) and $ch =~ /\d/){ $n .= $ch; } else { decode_error("malformed number (no digits after exp sign)"); } while(defined(next_chr) and $ch =~ /\d/){ $n .= $ch; } } $v .= $n; if ($is_dec or $is_exp) { if ($allow_bignum) { require Math::BigFloat; return Math::BigFloat->new($v); } } else { if (length $v > $max_intsize) { if ($allow_bignum) { # from Adam Sussman require Math::BigInt; return Math::BigInt->new($v); } else { return "$v"; } } } return $is_dec ? $v/1.0 : 0+$v; } sub is_valid_utf8 { $utf8_len = $_[0] =~ /[\x00-\x7F]/ ? 1 : $_[0] =~ /[\xC2-\xDF]/ ? 2 : $_[0] =~ /[\xE0-\xEF]/ ? 3 : $_[0] =~ /[\xF0-\xF4]/ ? 4 : 0 ; return unless $utf8_len; my $is_valid_utf8 = substr($text, $at - 1, $utf8_len); return ( $is_valid_utf8 =~ /^(?: [\x00-\x7F] |[\xC2-\xDF][\x80-\xBF] |[\xE0][\xA0-\xBF][\x80-\xBF] |[\xE1-\xEC][\x80-\xBF][\x80-\xBF] |[\xED][\x80-\x9F][\x80-\xBF] |[\xEE-\xEF][\x80-\xBF][\x80-\xBF] |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF] |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF] |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF] )$/x ) ? $is_valid_utf8 : ''; } sub decode_error { my $error = shift; my $no_rep = shift; my $str = defined $text ? substr($text, $at) : ''; my $mess = ''; my $type = 'U*'; if ( OLD_PERL ) { my $type = $] < 5.006 ? 'C*' : utf8::is_utf8( $str ) ? 'U*' # 5.6 : 'C*' ; } for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ? $mess .= $c == 0x07 ? '\a' : $c == 0x09 ? '\t' : $c == 0x0a ? '\n' : $c == 0x0d ? '\r' : $c == 0x0c ? '\f' : $c < 0x20 ? sprintf('\x{%x}', $c) : $c == 0x5c ? '\\\\' : $c < 0x80 ? chr($c) : sprintf('\x{%x}', $c) ; if ( length $mess >= 20 ) { $mess .= '...'; last; } } unless ( length $mess ) { $mess = '(end of string)'; } Carp::croak ( $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")" ); } sub _json_object_hook { my $o = $_[0]; my @ks = keys %{$o}; if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) { my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} ); if (@val == 0) { return $o; } elsif (@val == 1) { return $val[0]; } else { Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar"); } } my @val = $cb_object->($o) if ($cb_object); if (@val == 0) { return $o; } elsif (@val == 1) { return $val[0]; } else { Carp::croak("filter_json_object callbacks must not return more than one scalar"); } } sub PP_decode_box { { text => $text, at => $at, ch => $ch, len => $len, depth => $depth, encoding => $encoding, is_valid_utf8 => $is_valid_utf8, }; } } # PARSE sub _decode_surrogates { # from perlunicode my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00); my $un = pack('U*', $uni); utf8::encode( $un ); return $un; } sub _decode_unicode { my $un = pack('U', hex shift); utf8::encode( $un ); return $un; } # # Setup for various Perl versions (the code from JSON::PP58) # BEGIN { unless ( defined &utf8::is_utf8 ) { require Encode; *utf8::is_utf8 = *Encode::is_utf8; } if ( !OLD_PERL ) { *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates; *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode; if ($] < 5.008003) { # join() in 5.8.0 - 5.8.2 is broken. package # hide from PAUSE JSON::PP; require subs; subs->import('join'); eval q| sub join { return '' if (@_ < 2); my $j = shift; my $str = shift; for (@_) { $str .= $j . $_; } return $str; } |; } } sub JSON::PP::incr_parse { local $Carp::CarpLevel = 1; ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ ); } sub JSON::PP::incr_skip { ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip; } sub JSON::PP::incr_reset { ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset; } eval q{ sub JSON::PP::incr_text : lvalue { $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new; if ( $_[0]->{_incr_parser}->{incr_pos} ) { Carp::croak("incr_text cannot be called when the incremental parser already started parsing"); } $_[0]->{_incr_parser}->{incr_text}; } } if ( $] >= 5.006 ); } # Setup for various Perl versions (the code from JSON::PP58) ############################### # Utilities # BEGIN { eval 'require Scalar::Util'; unless($@){ *JSON::PP::blessed = \&Scalar::Util::blessed; *JSON::PP::reftype = \&Scalar::Util::reftype; *JSON::PP::refaddr = \&Scalar::Util::refaddr; } else{ # This code is from Scalar::Util. # warn $@; eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }'; *JSON::PP::blessed = sub { local($@, $SIG{__DIE__}, $SIG{__WARN__}); ref($_[0]) ? eval { $_[0]->a_sub_not_likely_to_be_here } : undef; }; require B; my %tmap = qw( B::NULL SCALAR B::HV HASH B::AV ARRAY B::CV CODE B::IO IO B::GV GLOB B::REGEXP REGEXP ); *JSON::PP::reftype = sub { my $r = shift; return undef unless length(ref($r)); my $t = ref(B::svref_2object($r)); return exists $tmap{$t} ? $tmap{$t} : length(ref($$r)) ? 'REF' : 'SCALAR'; }; *JSON::PP::refaddr = sub { return undef unless length(ref($_[0])); my $addr; if(defined(my $pkg = blessed($_[0]))) { $addr .= bless $_[0], 'Scalar::Util::Fake'; bless $_[0], $pkg; } else { $addr .= $_[0] } $addr =~ /0x(\w+)/; local $^W; #no warnings 'portable'; hex($1); } } } # shamelessly copied and modified from JSON::XS code. $JSON::PP::true = do { bless \(my $dummy = 1), "JSON::PP::Boolean" }; $JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" }; sub is_bool { blessed $_[0] and ( $_[0]->isa("JSON::PP::Boolean") or $_[0]->isa("Types::Serialiser::BooleanBase") or $_[0]->isa("JSON::XS::Boolean") ); } sub true { $JSON::PP::true } sub false { $JSON::PP::false } sub null { undef; } ############################### package # hide from PAUSE JSON::PP::IncrParser; use strict; use constant INCR_M_WS => 0; # initial whitespace skipping use constant INCR_M_STR => 1; # inside string use constant INCR_M_BS => 2; # inside backslash use constant INCR_M_JSON => 3; # outside anything, count nesting use constant INCR_M_C0 => 4; use constant INCR_M_C1 => 5; use constant INCR_M_TFN => 6; use constant INCR_M_NUM => 7; $JSON::backportPP::IncrParser::VERSION = '1.01'; sub new { my ( $class ) = @_; bless { incr_nest => 0, incr_text => undef, incr_pos => 0, incr_mode => 0, }, $class; } sub incr_parse { my ( $self, $coder, $text ) = @_; $self->{incr_text} = '' unless ( defined $self->{incr_text} ); if ( defined $text ) { if ( utf8::is_utf8( $text ) and !utf8::is_utf8( $self->{incr_text} ) ) { utf8::upgrade( $self->{incr_text} ) ; utf8::decode( $self->{incr_text} ) ; } $self->{incr_text} .= $text; } if ( defined wantarray ) { my $max_size = $coder->get_max_size; my $p = $self->{incr_pos}; my @ret; { do { unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) { $self->_incr_parse( $coder ); if ( $max_size and $self->{incr_pos} > $max_size ) { Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size"); } unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) { # as an optimisation, do not accumulate white space in the incr buffer if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) { $self->{incr_pos} = 0; $self->{incr_text} = ''; } last; } } my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 ); push @ret, $obj; use bytes; $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 ); $self->{incr_pos} = 0; $self->{incr_nest} = 0; $self->{incr_mode} = 0; last unless wantarray; } while ( wantarray ); } if ( wantarray ) { return @ret; } else { # in scalar context return defined $ret[0] ? $ret[0] : undef; } } } sub _incr_parse { my ($self, $coder) = @_; my $text = $self->{incr_text}; my $len = length $text; my $p = $self->{incr_pos}; INCR_PARSE: while ( $len > $p ) { my $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; my $mode = $self->{incr_mode}; if ( $mode == INCR_M_WS ) { while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; if ( ord($s) > 0x20 ) { if ( $s eq '#' ) { $self->{incr_mode} = INCR_M_C0; redo INCR_PARSE; } else { $self->{incr_mode} = INCR_M_JSON; redo INCR_PARSE; } } $p++; } } elsif ( $mode == INCR_M_BS ) { $p++; $self->{incr_mode} = INCR_M_STR; redo INCR_PARSE; } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) { while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; if ( $s eq "\n" ) { $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON; last; } $p++; } next; } elsif ( $mode == INCR_M_TFN ) { while ( $len > $p ) { $s = substr( $text, $p++, 1 ); next if defined $s and $s =~ /[rueals]/; last; } $p--; $self->{incr_mode} = INCR_M_JSON; last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $mode == INCR_M_NUM ) { while ( $len > $p ) { $s = substr( $text, $p++, 1 ); next if defined $s and $s =~ /[0-9eE.+\-]/; last; } $p--; $self->{incr_mode} = INCR_M_JSON; last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $mode == INCR_M_STR ) { while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; if ( $s eq '"' ) { $p++; $self->{incr_mode} = INCR_M_JSON; last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $s eq '\\' ) { $p++; if ( !defined substr($text, $p, 1) ) { $self->{incr_mode} = INCR_M_BS; last INCR_PARSE; } } $p++; } } elsif ( $mode == INCR_M_JSON ) { while ( $len > $p ) { $s = substr( $text, $p++, 1 ); if ( $s eq "\x00" ) { $p--; last INCR_PARSE; } elsif ( $s eq "\x09" or $s eq "\x0a" or $s eq "\x0d" or $s eq "\x20" ) { if ( !$self->{incr_nest} ) { $p--; # do not eat the whitespace, let the next round do it last INCR_PARSE; } next; } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) { $self->{incr_mode} = INCR_M_TFN; redo INCR_PARSE; } elsif ( $s =~ /^[0-9\-]$/ ) { $self->{incr_mode} = INCR_M_NUM; redo INCR_PARSE; } elsif ( $s eq '"' ) { $self->{incr_mode} = INCR_M_STR; redo INCR_PARSE; } elsif ( $s eq '[' or $s eq '{' ) { if ( ++$self->{incr_nest} > $coder->get_max_depth ) { Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)'); } next; } elsif ( $s eq ']' or $s eq '}' ) { if ( --$self->{incr_nest} <= 0 ) { last INCR_PARSE; } } elsif ( $s eq '#' ) { $self->{incr_mode} = INCR_M_C1; redo INCR_PARSE; } } } } $self->{incr_pos} = $p; $self->{incr_parsing} = $p ? 1 : 0; # for backward compatibility } sub incr_text { if ( $_[0]->{incr_pos} ) { Carp::croak("incr_text cannot be called when the incremental parser already started parsing"); } $_[0]->{incr_text}; } sub incr_skip { my $self = shift; $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} ); $self->{incr_pos} = 0; $self->{incr_mode} = 0; $self->{incr_nest} = 0; } sub incr_reset { my $self = shift; $self->{incr_text} = undef; $self->{incr_pos} = 0; $self->{incr_mode} = 0; $self->{incr_nest} = 0; } ############################### 1; __END__ =pod =head1 NAME JSON::PP - JSON::XS compatible pure-Perl module. =head1 SYNOPSIS use JSON::PP; # exported functions, they croak on error # and expect/generate UTF-8 $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; # OO-interface $json = JSON::PP->new->ascii->pretty->allow_nonref; $pretty_printed_json_text = $json->encode( $perl_scalar ); $perl_scalar = $json->decode( $json_text ); # Note that JSON version 2.0 and above will automatically use # JSON::XS or JSON::PP, so you should be able to just: use JSON; =head1 VERSION 4.05 =head1 DESCRIPTION JSON::PP is a pure perl JSON decoder/encoder, and (almost) compatible to much faster L written by Marc Lehmann in C. JSON::PP works as a fallback module when you use L module without having installed JSON::XS. Because of this fallback feature of JSON.pm, JSON::PP tries not to be more JavaScript-friendly than JSON::XS (i.e. not to escape extra characters such as U+2028 and U+2029, etc), in order for you not to lose such JavaScript-friendliness silently when you use JSON.pm and install JSON::XS for speed or by accident. If you need JavaScript-friendly RFC7159-compliant pure perl module, try L, which is derived from L web framework and is also smaller and faster than JSON::PP. JSON::PP has been in the Perl core since Perl 5.14, mainly for CPAN toolchain modules to parse META.json. =head1 FUNCTIONAL INTERFACE This section is taken from JSON::XS almost verbatim. C and C are exported by default. =head2 encode_json $json_text = encode_json $perl_scalar Converts the given Perl data structure to a UTF-8 encoded, binary string (that is, the string contains octets only). Croaks on error. This function call is functionally identical to: $json_text = JSON::PP->new->utf8->encode($perl_scalar) Except being faster. =head2 decode_json $perl_scalar = decode_json $json_text The opposite of C: expects an UTF-8 (binary) string and tries to parse that as an UTF-8 encoded JSON text, returning the resulting reference. Croaks on error. This function call is functionally identical to: $perl_scalar = JSON::PP->new->utf8->decode($json_text) Except being faster. =head2 JSON::PP::is_bool $is_boolean = JSON::PP::is_bool($scalar) Returns true if the passed scalar represents either JSON::PP::true or JSON::PP::false, two constants that act like C<1> and C<0> respectively and are also used to represent JSON C and C in Perl strings. See L, below, for more information on how JSON values are mapped to Perl. =head1 OBJECT-ORIENTED INTERFACE This section is also taken from JSON::XS. The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. =head2 new $json = JSON::PP->new Creates a new JSON::PP object that can be used to de/encode JSON strings. All boolean flags described below are by default I (with the exception of C, which defaults to I since version C<4.0>). The mutators for flags all return the JSON::PP object again and thus calls can be chained: my $json = JSON::PP->new->utf8->space_after->encode({a => [1,2]}) => {"a": [1, 2]} =head2 ascii $json = $json->ascii([$enable]) $enabled = $json->get_ascii If C<$enable> is true (or missing), then the C method will not generate characters outside the code range C<0..127> (which is ASCII). Any Unicode characters outside that range will be escaped using either a single \uXXXX (BMP characters) or a double \uHHHH\uLLLLL escape sequence, as per RFC4627. The resulting encoded JSON text can be treated as a native Unicode string, an ascii-encoded, latin1-encoded or UTF-8 encoded string, or any other superset of ASCII. If C<$enable> is false, then the C method will not escape Unicode characters unless required by the JSON syntax or other flags. This results in a faster and more compact format. See also the section I later in this document. The main use for this flag is to produce JSON texts that can be transmitted over a 7-bit channel, as the encoded JSON texts will not contain any 8 bit characters. JSON::PP->new->ascii(1)->encode([chr 0x10401]) => ["\ud801\udc01"] =head2 latin1 $json = $json->latin1([$enable]) $enabled = $json->get_latin1 If C<$enable> is true (or missing), then the C method will encode the resulting JSON text as latin1 (or iso-8859-1), escaping any characters outside the code range C<0..255>. The resulting string can be treated as a latin1-encoded JSON text or a native Unicode string. The C method will not be affected in any way by this flag, as C by default expects Unicode, which is a strict superset of latin1. If C<$enable> is false, then the C method will not escape Unicode characters unless required by the JSON syntax or other flags. See also the section I later in this document. The main use for this flag is efficiently encoding binary data as JSON text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting JSON text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for JSON. It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other JSON encoders/decoders. JSON::PP->new->latin1->encode (["\x{89}\x{abc}"] => ["\x{89}\\u0abc"] # (perl syntax, U+abc escaped, U+89 not) =head2 utf8 $json = $json->utf8([$enable]) $enabled = $json->get_utf8 If C<$enable> is true (or missing), then the C method will encode the JSON result into UTF-8, as required by many protocols, while the C method expects to be handled an UTF-8-encoded string. Please note that UTF-8-encoded strings do not contain any characters outside the range C<0..255>, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the UTF-16 and UTF-32 encoding families, as described in RFC4627. If C<$enable> is false, then the C method will return the JSON string as a (non-encoded) Unicode string, while C expects thus a Unicode string. Any decoding or encoding (e.g. to UTF-8 or UTF-16) needs to be done yourself, e.g. using the Encode module. See also the section I later in this document. Example, output UTF-16BE-encoded JSON: use Encode; $jsontext = encode "UTF-16BE", JSON::PP->new->encode ($object); Example, decode UTF-32LE-encoded JSON: use Encode; $object = JSON::PP->new->decode (decode "UTF-32LE", $jsontext); =head2 pretty $json = $json->pretty([$enable]) This enables (or disables) all of the C, C and C (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. =head2 indent $json = $json->indent([$enable]) $enabled = $json->get_indent If C<$enable> is true (or missing), then the C method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. If C<$enable> is false, no newlines or indenting will be produced, and the resulting JSON text is guaranteed not to contain any C. This setting has no effect when decoding JSON texts. The default indent space length is three. You can use C to change the length. =head2 space_before $json = $json->space_before([$enable]) $enabled = $json->get_space_before If C<$enable> is true (or missing), then the C method will add an extra optional space before the C<:> separating keys from values in JSON objects. If C<$enable> is false, then the C method will not add any extra space at those places. This setting has no effect when decoding JSON texts. You will also most likely combine this setting with C. Example, space_before enabled, space_after and indent disabled: {"key" :"value"} =head2 space_after $json = $json->space_after([$enable]) $enabled = $json->get_space_after If C<$enable> is true (or missing), then the C method will add an extra optional space after the C<:> separating keys from values in JSON objects and extra whitespace after the C<,> separating key-value pairs and array members. If C<$enable> is false, then the C method will not add any extra space at those places. This setting has no effect when decoding JSON texts. Example, space_before and indent disabled, space_after enabled: {"key": "value"} =head2 relaxed $json = $json->relaxed([$enable]) $enabled = $json->get_relaxed If C<$enable> is true (or missing), then C will accept some extensions to normal JSON syntax (see below). C will not be affected in anyway. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. Currently accepted extensions are: =over 4 =item * list items can have an end-comma JSON I array elements and key-value pairs with commas. This can be annoying if you write JSON texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: [ 1, 2, <- this comma not normally allowed ] { "k1": "v1", "k2": "v2", <- this comma not normally allowed } =item * shell-style '#'-comments Whenever JSON allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. [ 1, # this comment not allowed in JSON # neither this one... ] =item * C-style multiple-line '/* */'-comments (JSON::PP only) Whenever JSON allows whitespace, C-style multiple-line comments are additionally allowed. Everything between C and C<*/> is a comment, after which more white-space and comments are allowed. [ 1, /* this comment not allowed in JSON */ /* neither this one... */ ] =item * C++-style one-line '//'-comments (JSON::PP only) Whenever JSON allows whitespace, C++-style one-line comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. [ 1, // this comment not allowed in JSON // neither this one... ] =item * literal ASCII TAB characters in strings Literal ASCII TAB characters are now allowed in strings (and treated as C<\t>). [ "Hello\tWorld", "HelloWorld", # literal would not normally be allowed ] =back =head2 canonical $json = $json->canonical([$enable]) $enabled = $json->get_canonical If C<$enable> is true (or missing), then the C method will output JSON objects by sorting their keys. This is adding a comparatively high overhead. If C<$enable> is false, then the C method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). This option is useful if you want the same data structure to be encoded as the same JSON text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. This setting has no effect when decoding JSON texts. This setting has currently no effect on tied hashes. =head2 allow_nonref $json = $json->allow_nonref([$enable]) $enabled = $json->get_allow_nonref Unlike other boolean options, this opotion is enabled by default beginning with version C<4.0>. If C<$enable> is true (or missing), then the C method can convert a non-reference into its corresponding string, number or null JSON value, which is an extension to RFC4627. Likewise, C will accept those JSON values instead of croaking. If C<$enable> is false, then the C method will croak if it isn't passed an arrayref or hashref, as JSON texts must either be an object or array. Likewise, C will croak if given something that is not a JSON object or array. Example, encode a Perl scalar as JSON value without enabled C, resulting in an error: JSON::PP->new->allow_nonref(0)->encode ("Hello, World!") => hash- or arrayref expected... =head2 allow_unknown $json = $json->allow_unknown([$enable]) $enabled = $json->get_allow_unknown If C<$enable> is true (or missing), then C will I throw an exception when it encounters values it cannot represent in JSON (for example, filehandles) but instead will encode a JSON C value. Note that blessed objects are not included here and are handled separately by c. If C<$enable> is false (the default), then C will throw an exception when it encounters anything it cannot encode as JSON. This option does not affect C in any way, and it is recommended to leave it off unless you know your communications partner. =head2 allow_blessed $json = $json->allow_blessed([$enable]) $enabled = $json->get_allow_blessed See L for details. If C<$enable> is true (or missing), then the C method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a JSON C value is encoded instead of the object. If C<$enable> is false (the default), then C will throw an exception when it encounters a blessed object that it cannot convert otherwise. This setting has no effect on C. =head2 convert_blessed $json = $json->convert_blessed([$enable]) $enabled = $json->get_convert_blessed See L for details. If C<$enable> is true (or missing), then C, upon encountering a blessed object, will check for the availability of the C method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. The C method may safely call die if it wants. If C returns other blessed objects, those will be handled in the same way. C must take care of not causing an endless recursion cycle (== crash) in this case. The name of C was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any C function or method. If C<$enable> is false (the default), then C will not consider this type of conversion. This setting has no effect on C. =head2 allow_tags $json = $json->allow_tags([$enable]) $enabled = $json->get_allow_tags See L for details. If C<$enable> is true (or missing), then C, upon encountering a blessed object, will check for the availability of the C method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged JSON value (that JSON decoders cannot decode). It also causes C to parse such tagged JSON values and deserialise them via a call to the C method. If C<$enable> is false (the default), then C will not consider this type of conversion, and tagged JSON values will cause a parse error in C, as if tags were not part of the grammar. =head2 boolean_values $json->boolean_values([$false, $true]) ($false, $true) = $json->get_boolean_values By default, JSON booleans will be decoded as overloaded C<$JSON::PP::false> and C<$JSON::PP::true> objects. With this method you can specify your own boolean values for decoding - on decode, JSON C will be decoded as a copy of C<$false>, and JSON C will be decoded as C<$true> ("copy" here is the same thing as assigning a value to another variable, i.e. C<$copy = $false>). This is useful when you want to pass a decoded data structure directly to other serialisers like YAML, Data::MessagePack and so on. Note that this works only when you C. You can set incompatible boolean objects (like L), but when you C a data structure with such boolean objects, you still need to enable C (and add a C method if necessary). Calling this method without any arguments will reset the booleans to their default values. C will return both C<$false> and C<$true> values, or the empty list when they are set to the default. =head2 filter_json_object $json = $json->filter_json_object([$coderef]) When C<$coderef> is specified, it will be called from C each time it decodes a JSON object. The only argument is a reference to the newly-created hash. If the code references returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (NOTE: I C, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. When C<$coderef> is omitted or undefined, any existing callback will be removed and C will not change the deserialised hash in any way. Example, convert all JSON objects into the integer 5: my $js = JSON::PP->new->filter_json_object(sub { 5 }); # returns [5] $js->decode('[{}]'); # returns 5 $js->decode('{"a":1, "b":2}'); =head2 filter_json_single_key_object $json = $json->filter_json_single_key_object($key [=> $coderef]) Works remotely similar to C, but is only called for JSON objects having a single key named C<$key>. This C<$coderef> is called before the one specified via C, if any. It gets passed the single value in the JSON object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even C but the empty list), the callback from C will be called next, as if no single-key callback were specified. If C<$coderef> is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. As this callback gets called less often then the C one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key JSON objects are as close to the type-tagged value concept as JSON gets (it's basically an ID/VALUE tuple). Of course, JSON does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. Typical names for the single object key are C<__class_whatever__>, or C<$__dollars_are_rarely_used__$> or C<}ugly_brace_placement>, or even things like C<__class_md5sum(classname)__>, to reduce the risk of clashing with real hashes. Example, decode JSON objects of the form C<< { "__widget__" => } >> into the corresponding C<< $WIDGET{} >> object: # return whatever is in $WIDGET{5}: JSON::PP ->new ->filter_json_single_key_object (__widget__ => sub { $WIDGET{ $_[0] } }) ->decode ('{"__widget__": 5') # this can be used with a TO_JSON method in some "widget" class # for serialisation to json: sub WidgetBase::TO_JSON { my ($self) = @_; unless ($self->{id}) { $self->{id} = ..get..some..id..; $WIDGET{$self->{id}} = $self; } { __widget__ => $self->{id} } } =head2 shrink $json = $json->shrink([$enable]) $enabled = $json->get_shrink If C<$enable> is true (or missing), the string returned by C will be shrunk (i.e. downgraded if possible). The actual definition of what shrink does might change in future versions, but it will always try to save space at the expense of time. If C<$enable> is false, then JSON::PP does nothing. =head2 max_depth $json = $json->max_depth([$maximum_nesting_depth]) $max_depth = $json->get_max_depth Sets the maximum nesting level (default C<512>) accepted while encoding or decoding. If a higher nesting level is detected in JSON text or a Perl data structure, then the encoder and decoder will stop and croak at that point. Nesting level is defined by number of hash- or arrayrefs that the encoder needs to traverse to reach a given point or the number of C<{> or C<[> characters without their matching closing parenthesis crossed to reach a given character in a string. Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. If no argument is given, the highest possible setting will be used, which is rarely useful. See L for more info on why this is useful. =head2 max_size $json = $json->max_size([$maximum_string_size]) $max_size = $json->get_max_size Set the maximum length a JSON text may have (in bytes) where decoding is being attempted. The default is C<0>, meaning no limit. When C is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on C (yet). If no argument is given, the limit check will be deactivated (same as when C<0> is specified). See L for more info on why this is useful. =head2 encode $json_text = $json->encode($perl_scalar) Converts the given Perl value or data structure to its JSON representation. Croaks on error. =head2 decode $perl_scalar = $json->decode($json_text) The opposite of C: expects a JSON text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. =head2 decode_prefix ($perl_scalar, $characters) = $json->decode_prefix($json_text) This works like the C method, but instead of raising an exception when there is trailing garbage after the first JSON object, it will silently stop parsing there and return the number of characters consumed so far. This is useful if your JSON texts are not delimited by an outer protocol and you need to know where the JSON text ends. JSON::PP->new->decode_prefix ("[1] the tail") => ([1], 3) =head1 FLAGS FOR JSON::PP ONLY The following flags and properties are for JSON::PP only. If you use any of these, you can't make your application run faster by replacing JSON::PP with JSON::XS. If you need these and also speed boost, you might want to try L, a fork of JSON::XS by Reini Urban, which supports some of these (with a different set of incompatibilities). Most of these historical flags are only kept for backward compatibility, and should not be used in a new application. =head2 allow_singlequote $json = $json->allow_singlequote([$enable]) $enabled = $json->get_allow_singlequote If C<$enable> is true (or missing), then C will accept invalid JSON texts that contain strings that begin and end with single quotation marks. C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. $json->allow_singlequote->decode(qq|{"foo":'bar'}|); $json->allow_singlequote->decode(qq|{'foo':"bar"}|); $json->allow_singlequote->decode(qq|{'foo':'bar'}|); =head2 allow_barekey $json = $json->allow_barekey([$enable]) $enabled = $json->get_allow_barekey If C<$enable> is true (or missing), then C will accept invalid JSON texts that contain JSON objects whose names don't begin and end with quotation marks. C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. $json->allow_barekey->decode(qq|{foo:"bar"}|); =head2 allow_bignum $json = $json->allow_bignum([$enable]) $enabled = $json->get_allow_bignum If C<$enable> is true (or missing), then C will convert big integers Perl cannot handle as integer into L objects and convert floating numbers into L objects. C will convert C and C objects into JSON numbers. $json->allow_nonref->allow_bignum; $bigfloat = $json->decode('2.000000000000000000000000001'); print $json->encode($bigfloat); # => 2.000000000000000000000000001 See also L. =head2 loose $json = $json->loose([$enable]) $enabled = $json->get_loose If C<$enable> is true (or missing), then C will accept invalid JSON texts that contain unescaped [\x00-\x1f\x22\x5c] characters. C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. $json->loose->decode(qq|["abc def"]|); =head2 escape_slash $json = $json->escape_slash([$enable]) $enabled = $json->get_escape_slash If C<$enable> is true (or missing), then C will explicitly escape I (solidus; C) characters to reduce the risk of XSS (cross site scripting) that may be caused by C<< >> in a JSON text, with the cost of bloating the size of JSON texts. This option may be useful when you embed JSON in HTML, but embedding arbitrary JSON in HTML (by some HTML template toolkit or by string interpolation) is risky in general. You must escape necessary characters in correct order, depending on the context. C will not be affected in any way. =head2 indent_length $json = $json->indent_length($number_of_spaces) $length = $json->get_indent_length This option is only useful when you also enable C or C. JSON::XS indents with three spaces when you C (if requested by C or C), and the number cannot be changed. JSON::PP allows you to change/get the number of indent spaces with these mutator/accessor. The default number of spaces is three (the same as JSON::XS), and the acceptable range is from C<0> (no indentation; it'd be better to disable indentation by C) to C<15>. =head2 sort_by $json = $json->sort_by($code_ref) $json = $json->sort_by($subroutine_name) If you just want to sort keys (names) in JSON objects when you C, enable C option (see above) that allows you to sort object keys alphabetically. If you do need to sort non-alphabetically for whatever reasons, you can give a code reference (or a subroutine name) to C, then the argument will be passed to Perl's C built-in function. As the sorting is done in the JSON::PP scope, you usually need to prepend C to the subroutine name, and the special variables C<$a> and C<$b> used in the subrontine used by C function. Example: my %ORDER = (id => 1, class => 2, name => 3); $json->sort_by(sub { ($ORDER{$JSON::PP::a} // 999) <=> ($ORDER{$JSON::PP::b} // 999) or $JSON::PP::a cmp $JSON::PP::b }); print $json->encode([ {name => 'CPAN', id => 1, href => 'http://cpan.org'} ]); # [{"id":1,"name":"CPAN","href":"http://cpan.org"}] Note that C affects all the plain hashes in the data structure. If you need finer control, C necessary hashes with a module that implements ordered hash (such as L and L). C and C don't affect the key order in Cd hashes. use Hash::Ordered; tie my %hash, 'Hash::Ordered', (name => 'CPAN', id => 1, href => 'http://cpan.org'); print $json->encode([\%hash]); # [{"name":"CPAN","id":1,"href":"http://cpan.org"}] # order is kept =head1 INCREMENTAL PARSING This section is also taken from JSON::XS. In some cases, there is the need for incremental parsing of JSON texts. While this module always has to keep both JSON text and resulting Perl data structure in memory at one time, it does allow you to parse a JSON stream incrementally. It does so by accumulating text until it has a full JSON object, which it then can decode. This process is similar to using C to see if a full JSON object is available, but is much more efficient (and can be implemented with a minimum of method calls). JSON::PP will only attempt to parse the JSON text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid JSON text has been seen. This means you need to set resource limits (e.g. C) to ensure the parser will stop parsing in the presence if syntax errors. The following methods implement this incremental parser. =head2 incr_parse $json->incr_parse( [$string] ) # void context $obj_or_undef = $json->incr_parse( [$string] ) # scalar context @obj_or_empty = $json->incr_parse( [$string] ) # list context This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). If C<$string> is given, then this string is appended to the already existing JSON fragment stored in the C<$json> object. After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. If the method is called in scalar context, then it will try to extract exactly I JSON object. If that is successful, it will return this object, otherwise it will return C. If there is a parse error, this method will croak just as C would do (one can then use C to skip the erroneous part). This is the most common way of using the method. And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the JSON objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed JSON texts will be lost. Example: Parse some JSON arrays/objects in a given string and return them. my @objs = JSON::PP->new->incr_parse ("[5][7][1,2]"); =head2 incr_text $lvalue_string = $json->incr_text This method returns the currently stored JSON fragment as an lvalue, that is, you can manipulate it. This I works when a preceding call to C in I successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it I fail under real world conditions). As a special exception, you can also call this method before having parsed anything. That means you can only use this function to look at or manipulate text before or after complete JSON objects, not while the parser is in the middle of parsing a JSON object. This function is useful in two cases: a) finding the trailing text after a JSON object or b) parsing multiple JSON objects separated by non-JSON text (such as commas). =head2 incr_skip $json->incr_skip This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after C died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. The difference to C is that only text until the parse error occurred is removed. =head2 incr_reset $json->incr_reset This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. This is useful if you want to repeatedly parse JSON objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. =head1 MAPPING Most of this section is also taken from JSON::XS. This section describes how JSON::PP maps Perl values to JSON values and vice versa. These mappings are designed to "do the right thing" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). For the more enlightened: note that in the following descriptions, lowercase I refers to the Perl interpreter, while uppercase I refers to the abstract Perl language itself. =head2 JSON -> PERL =over 4 =item object A JSON object becomes a reference to a hash in Perl. No ordering of object keys is preserved (JSON does not preserve object key ordering itself). =item array A JSON array becomes a reference to an array in Perl. =item string A JSON string becomes a string scalar in Perl - Unicode codepoints in JSON are represented by the same codepoints in the Perl string, so no manual decoding is necessary. =item number A JSON number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. If the number consists of digits only, JSON::PP will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the JSON number will be re-encoded to a JSON string). Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the JSON number will still be re-encoded as a JSON number). Note that precision is not accuracy - binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, JSON::PP only guarantees precision up to but not including the least significant bit. When C is enabled, big integer values and any numeric values will be converted into L and L objects respectively, without becoming string scalars or losing precision. =item true, false These JSON atoms become C and C, respectively. They are overloaded to act almost exactly like the numbers C<1> and C<0>. You can check whether a scalar is a JSON boolean by using the C function. =item null A JSON null atom becomes C in Perl. =item shell-style comments (C<< # I >>) As a nonstandard extension to the JSON syntax that is enabled by the C setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. =item tagged values (C<< (I)I >>). Another nonstandard extension to the JSON syntax, enabled with the C setting, are tagged values. In this implementation, the I must be a perl package/class name encoded as a JSON string, and the I must be a JSON array encoding optional constructor arguments. See L, below, for details. =back =head2 PERL -> JSON The mapping from Perl to JSON is slightly more difficult, as Perl is a truly typeless language, so we can only guess which JSON type is meant by a Perl value. =over 4 =item hash references Perl hash references become JSON objects. As there is no inherent ordering in hash keys (or JSON objects), they will usually be encoded in a pseudo-random order. JSON::PP can optionally sort the hash keys (determined by the I flag and/or I property), so the same data structure will serialise to the same JSON text (given same settings and version of JSON::PP), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some JSON text against another for equality. =item array references Perl array references become JSON arrays. =item other references Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers C<0> and C<1>, which get turned into C and C atoms in JSON. You can also use C and C to improve readability. to_json [\0, JSON::PP::true] # yields [false,true] =item JSON::PP::true, JSON::PP::false These special values become JSON true and JSON false values, respectively. You can also use C<\1> and C<\0> directly if you want. =item JSON::PP::null This special value becomes JSON null. =item blessed objects Blessed objects are not directly representable in JSON, but C allows various ways of handling objects. See L, below, for details. =item simple scalars Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: JSON::PP will encode undefined scalars as JSON C values, scalars that have last been used in a string context before encoding as JSON strings, and anything else as number value: # dump as number encode_json [2] # yields [2] encode_json [-3.0e17] # yields [-3e+17] my $value = 5; encode_json [$value] # yields [5] # used as string, so dump as string print $value; encode_json [$value] # yields ["5"] # undef becomes null encode_json [undef] # yields [null] You can force the type to be a JSON string by stringifying it: my $x = 3.1; # some variable containing a number "$x"; # stringified $x .= ""; # another, more awkward way to stringify print $x; # perl does it for you, too, quite often # (but for older perls) You can force the type to be a JSON number by numifying it: my $x = "3"; # some variable containing a string $x += 0; # numify it, ensuring it will be dumped as a number $x *= 1; # same thing, the choice is yours. You can not currently force the type in other, less obscure, ways. Since version 2.91_01, JSON::PP uses a different number detection logic that converts a scalar that is possible to turn into a number safely. The new logic is slightly faster, and tends to help people who use older perl or who want to encode complicated data structure. However, this may results in a different JSON text from the one JSON::XS encodes (and thus may break tests that compare entire JSON texts). If you do need the previous behavior for compatibility or for finer control, set PERL_JSON_PP_USE_B environmental variable to true before you C JSON::PP (or JSON.pm). Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's - these cannot be represented in JSON, and it is an error to pass those in. JSON::PP (and JSON::XS) trusts what you pass to C method (or C function) is a clean, validated data structure with values that can be represented as valid JSON values only, because it's not from an external data source (as opposed to JSON texts you pass to C or C, which JSON::PP considers tainted and doesn't trust). As JSON::PP doesn't know exactly what you and consumers of your JSON texts want the unexpected values to be (you may want to convert them into null, or to stringify them with or without normalisation (string representation of infinities/NaN may vary depending on platforms), or to croak without conversion), you're advised to do what you and your consumers need before you encode, and also not to numify values that may start with values that look like a number (including infinities/NaN), without validating. =back =head2 OBJECT SERIALISATION As JSON cannot directly represent Perl objects, you have to choose between a pure JSON representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the JSON syntax, tagged values. =head3 SERIALISATION What happens when C encounters a Perl object depends on the C, C, C and C settings, which are used in this order: =over 4 =item 1. C is enabled and the object has a C method. In this case, C creates a tagged JSON value, using a nonstandard extension to the JSON syntax. This works by invoking the C method on the object, with the first argument being the object to serialise, and the second argument being the constant string C to distinguish it from other serialisers. The C method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged JSON value in the following format: ("classname")[FREEZE return values...] e.g.: ("URI")["http://www.google.com/"] ("MyDate")[2013,10,29] ("ImageData::JPEG")["Z3...VlCg=="] For example, the hypothetical C C method might use the objects C and C members to encode the object: sub My::Object::FREEZE { my ($self, $serialiser) = @_; ($self->{type}, $self->{id}) } =item 2. C is enabled and the object has a C method. In this case, the C method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into JSON. This scalar replaces the object in the JSON text. For example, the following C method will convert all L objects to JSON strings when serialised. The fact that these values originally were L objects is lost. sub URI::TO_JSON { my ($uri) = @_; $uri->as_string } =item 3. C is enabled and the object is a C or C. The object will be serialised as a JSON number value. =item 4. C is enabled. The object will be serialised as a JSON null value. =item 5. none of the above If none of the settings are enabled or the respective methods are missing, C throws an exception. =back =head3 DESERIALISATION For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case C decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the C or C callbacks to get some real objects our of your JSON. This section only considers the tagged value case: a tagged JSON object is encountered during decoding and C is disabled, a parse error will result (as if tagged values were not part of the grammar). If C is enabled, C will look up the C method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. Otherwise, the C method is invoked with the classname as first argument, the constant string C as second argument, and all the values from the JSON array (the values originally returned by the C method) as remaining arguments. The method must then return the object. While technically you can return any Perl scalar, you might have to enable the C setting to make that work in all cases, so better return an actual blessed reference. As an example, let's implement a C function that regenerates the C from the C example earlier: sub My::Object::THAW { my ($class, $serialiser, $type, $id) = @_; $class->new (type => $type, id => $id) } =head1 ENCODING/CODESET FLAG NOTES This section is taken from JSON::XS. The interested reader might have seen a number of flags that signify encodings or codesets - C, C and C. There seems to be some confusion on what these do, so here is a short comparison: C controls whether the JSON text created by C (and expected by C) is UTF-8 encoded or not, while C and C only control whether C escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. Care has been taken to make all flags symmetrical with respect to C and C, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used - in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. Below comes a verbose discussion of these flags. Note that a "codeset" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and I them, in our case into octets. Unicode is (among other things) a codeset, UTF-8 is an encoding, and ISO-8859-1 (= latin 1) and ASCII are both codesets I encodings at the same time, which can be confusing. =over 4 =item C flag disabled When C is disabled (the default), then C/C generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except "(re-)interpreting" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). This is useful when you want to do the encoding yourself (e.g. when you want to have UTF-16 encoded JSON texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to UTF-8 you certainly do NOT want to UTF-8 encode your data first and have Perl encode it another time). =item C flag enabled If the C-flag is enabled, C/C will encode all characters using the corresponding UTF-8 multi-byte sequence, and will expect your input strings to be encoded as UTF-8, that is, no "character" of the input string must have any value > 255, as UTF-8 does not allow that. The C flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get an UTF-8 encoded octet/binary string in Perl. =item C or C flags enabled With C (or C) enabled, C will escape characters with ordinal values > 255 (> 127 with C) and encode the remaining characters as specified by the C flag. If C is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a ISO-8859-1 string, and a Unicode string with all character values < 128 is the same thing as an ASCII string in Perl). If C is enabled, you still get a correct UTF-8-encoded string, regardless of these flags, just some more characters will be escaped using C<\uXXXX> then before. Note that ISO-8859-1-I strings are not compatible with UTF-8 encoding, while ASCII-encoded strings are. That is because the ISO-8859-1 encoding is NOT a subset of UTF-8 (despite the ISO-8859-1 I being a subset of Unicode), while ASCII is. Surprisingly, C will ignore these flags and so treat all input values as governed by the C flag. If it is disabled, this allows you to decode ISO-8859-1- and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode UTF-8 encoded strings. So neither C nor C are incompatible with the C flag - they only govern when the JSON output engine escapes a character or not. The main use for C is to relatively efficiently store binary data as JSON, at the expense of breaking compatibility with most JSON decoders. The main use for C is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as UTF-8, ISO-8859-1, ASCII, KOI8-R or most about any character set and 8-bit-encoding, and still get the same data structure back. This is useful when your channel for JSON transfer is not 8-bit clean or the encoding might be mangled in between (e.g. in mail), and works because ASCII is a proper subset of most 8-bit and multibyte encodings in use in the world. =back =head1 BUGS Please report bugs on a specific behavior of this module to RT or GitHub issues (preferred): L L As for new features and requests to change common behaviors, please ask the author of JSON::XS (Marc Lehmann, Eschmorp[at]schmorp.deE) first, by email (important!), to keep compatibility among JSON.pm backends. Generally speaking, if you need something special for you, you are advised to create a new module, maybe based on L, which is smaller and written in a much cleaner way than this module. =head1 SEE ALSO The F command line utility for quick experiments. L, L, and L for faster alternatives. L and L for easy migration. L and L for older perl users. RFC4627 (L) RFC7159 (L) RFC8259 (L) =head1 AUTHOR Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE =head1 CURRENT MAINTAINER Kenichi Ishigaki, Eishigaki[at]cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2007-2016 by Makamaka Hannyaharamitu Most of the documentation is taken from JSON::XS by Marc Lehmann This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/JSON/PP/Boolean.pm000044400000001452152462503210010600 0ustar00package JSON::PP::Boolean; use strict; require overload; local $^W; overload::import('overload', "0+" => sub { ${$_[0]} }, "++" => sub { $_[0] = ${$_[0]} + 1 }, "--" => sub { $_[0] = ${$_[0]} - 1 }, fallback => 1, ); $JSON::PP::Boolean::VERSION = '4.06'; 1; __END__ =head1 NAME JSON::PP::Boolean - dummy module providing JSON::PP::Boolean =head1 SYNOPSIS # do not "use" yourself =head1 DESCRIPTION This module exists only to provide overload resolution for Storable and similar modules. See L for more info about this class. =head1 AUTHOR This idea is from L written by Marc Lehmann =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/JSON/backportPP/Compat5006.pm000044400000007365152462503210012516 0ustar00package # This is JSON::backportPP JSON::backportPP56; use 5.006; use strict; my @properties; $JSON::PP56::VERSION = '1.08'; BEGIN { sub utf8::is_utf8 { my $len = length $_[0]; # char length { use bytes; # byte length; return $len != length $_[0]; # if !=, UTF8-flagged on. } } sub utf8::upgrade { ; # noop; } sub utf8::downgrade ($;$) { return 1 unless ( utf8::is_utf8( $_[0] ) ); if ( _is_valid_utf8( $_[0] ) ) { my $downgrade; for my $c ( unpack( "U*", $_[0] ) ) { if ( $c < 256 ) { $downgrade .= pack("C", $c); } else { $downgrade .= pack("U", $c); } } $_[0] = $downgrade; return 1; } else { Carp::croak("Wide character in subroutine entry") unless ( $_[1] ); 0; } } sub utf8::encode ($) { # UTF8 flag off if ( utf8::is_utf8( $_[0] ) ) { $_[0] = pack( "C*", unpack( "C*", $_[0] ) ); } else { $_[0] = pack( "U*", unpack( "C*", $_[0] ) ); $_[0] = pack( "C*", unpack( "C*", $_[0] ) ); } } sub utf8::decode ($) { # UTF8 flag on if ( _is_valid_utf8( $_[0] ) ) { utf8::downgrade( $_[0] ); $_[0] = pack( "U*", unpack( "U*", $_[0] ) ); } } *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; *JSON::PP::JSON_PP_decode_surrogates = \&JSON::PP::_decode_surrogates; *JSON::PP::JSON_PP_decode_unicode = \&JSON::PP::_decode_unicode; unless ( defined &B::SVp_NOK ) { # missing in B module. eval q{ sub B::SVp_NOK () { 0x02000000; } }; } } sub _encode_ascii { join('', map { $_ <= 127 ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', JSON::PP::_encode_surrogates($_)); } _unpack_emu($_[0]) ); } sub _encode_latin1 { join('', map { $_ <= 255 ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', JSON::PP::_encode_surrogates($_)); } _unpack_emu($_[0]) ); } sub _unpack_emu { # for Perl 5.6 unpack warnings return !utf8::is_utf8($_[0]) ? unpack('C*', $_[0]) : _is_valid_utf8($_[0]) ? unpack('U*', $_[0]) : unpack('C*', $_[0]); } sub _is_valid_utf8 { my $str = $_[0]; my $is_utf8; while ($str =~ /(?: ( [\x00-\x7F] |[\xC2-\xDF][\x80-\xBF] |[\xE0][\xA0-\xBF][\x80-\xBF] |[\xE1-\xEC][\x80-\xBF][\x80-\xBF] |[\xED][\x80-\x9F][\x80-\xBF] |[\xEE-\xEF][\x80-\xBF][\x80-\xBF] |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF] |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF] |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF] ) | (.) )/xg) { if (defined $1) { $is_utf8 = 1 if (!defined $is_utf8); } else { $is_utf8 = 0 if (!defined $is_utf8); if ($is_utf8) { # eventually, not utf8 return; } } } return $is_utf8; } 1; __END__ =pod =head1 NAME JSON::PP56 - Helper module in using JSON::PP in Perl 5.6 =head1 DESCRIPTION JSON::PP calls internally. =head1 AUTHOR Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2007-2012 by Makamaka Hannyaharamitu This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/JSON/backportPP/Boolean.pm000044400000001521152462503210012323 0ustar00package # This is JSON::backportPP JSON::PP::Boolean; use strict; require overload; local $^W; overload::import('overload', "0+" => sub { ${$_[0]} }, "++" => sub { $_[0] = ${$_[0]} + 1 }, "--" => sub { $_[0] = ${$_[0]} - 1 }, fallback => 1, ); $JSON::backportPP::Boolean::VERSION = '4.06'; 1; __END__ =head1 NAME JSON::PP::Boolean - dummy module providing JSON::PP::Boolean =head1 SYNOPSIS # do not "use" yourself =head1 DESCRIPTION This module exists only to provide overload resolution for Storable and similar modules. See L for more info about this class. =head1 AUTHOR This idea is from L written by Marc Lehmann =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/JSON/backportPP/Compat5005.pm000044400000005365152462503210012513 0ustar00package # This is JSON::backportPP JSON::backportPP5005; use 5.005; use strict; my @properties; $JSON::PP5005::VERSION = '1.10'; BEGIN { sub utf8::is_utf8 { 0; # It is considered that UTF8 flag off for Perl 5.005. } sub utf8::upgrade { } sub utf8::downgrade { 1; # must always return true. } sub utf8::encode { } sub utf8::decode { } *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates; *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode; # missing in B module. sub B::SVp_IOK () { 0x01000000; } sub B::SVp_NOK () { 0x02000000; } sub B::SVp_POK () { 0x04000000; } $INC{'bytes.pm'} = 1; # dummy } sub _encode_ascii { join('', map { $_ <= 127 ? chr($_) : sprintf('\u%04x', $_) } unpack('C*', $_[0]) ); } sub _encode_latin1 { join('', map { chr($_) } unpack('C*', $_[0]) ); } sub _decode_surrogates { # from http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00); # from perlunicode my $bit = unpack('B32', pack('N', $uni)); if ( $bit =~ /^00000000000(...)(......)(......)(......)$/ ) { my ($w, $x, $y, $z) = ($1, $2, $3, $4); return pack('B*', sprintf('11110%s10%s10%s10%s', $w, $x, $y, $z)); } else { Carp::croak("Invalid surrogate pair"); } } sub _decode_unicode { my ($u) = @_; my ($utf8bit); if ( $u =~ /^00([89a-f][0-9a-f])$/i ) { # 0x80-0xff return pack( 'H2', $1 ); } my $bit = unpack("B*", pack("H*", $u)); if ( $bit =~ /^00000(.....)(......)$/ ) { $utf8bit = sprintf('110%s10%s', $1, $2); } elsif ( $bit =~ /^(....)(......)(......)$/ ) { $utf8bit = sprintf('1110%s10%s10%s', $1, $2, $3); } else { Carp::croak("Invalid escaped unicode"); } return pack('B*', $utf8bit); } sub JSON::PP::incr_text { $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new; if ( $_[0]->{_incr_parser}->{incr_parsing} ) { Carp::croak("incr_text can not be called when the incremental parser already started parsing"); } $_[0]->{_incr_parser}->{incr_text} = $_[1] if ( @_ > 1 ); $_[0]->{_incr_parser}->{incr_text}; } 1; __END__ =pod =head1 NAME JSON::PP5005 - Helper module in using JSON::PP in Perl 5.005 =head1 DESCRIPTION JSON::PP calls internally. =head1 AUTHOR Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2007-2012 by Makamaka Hannyaharamitu This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/Path/Class.pm000044400000012673152462503210010101 0ustar00use strict; package Path::Class; { $Path::Class::VERSION = '0.37'; } { ## no critic no strict 'vars'; @ISA = qw(Exporter); @EXPORT = qw(file dir); @EXPORT_OK = qw(file dir foreign_file foreign_dir tempdir); } use Exporter; use Path::Class::File; use Path::Class::Dir; use File::Temp (); sub file { Path::Class::File->new(@_) } sub dir { Path::Class::Dir ->new(@_) } sub foreign_file { Path::Class::File->new_foreign(@_) } sub foreign_dir { Path::Class::Dir ->new_foreign(@_) } sub tempdir { Path::Class::Dir->new(File::Temp::tempdir(@_)) } 1; __END__ =head1 NAME Path::Class - Cross-platform path specification manipulation =head1 VERSION version 0.37 =head1 SYNOPSIS use Path::Class; my $dir = dir('foo', 'bar'); # Path::Class::Dir object my $file = file('bob', 'file.txt'); # Path::Class::File object # Stringifies to 'foo/bar' on Unix, 'foo\bar' on Windows, etc. print "dir: $dir\n"; # Stringifies to 'bob/file.txt' on Unix, 'bob\file.txt' on Windows print "file: $file\n"; my $subdir = $dir->subdir('baz'); # foo/bar/baz my $parent = $subdir->parent; # foo/bar my $parent2 = $parent->parent; # foo my $dir2 = $file->dir; # bob # Work with foreign paths use Path::Class qw(foreign_file foreign_dir); my $file = foreign_file('Mac', ':foo:file.txt'); print $file->dir; # :foo: print $file->as_foreign('Win32'); # foo\file.txt # Interact with the underlying filesystem: # $dir_handle is an IO::Dir object my $dir_handle = $dir->open or die "Can't read $dir: $!"; # $file_handle is an IO::File object my $file_handle = $file->open($mode) or die "Can't read $file: $!"; =head1 DESCRIPTION C is a module for manipulation of file and directory specifications (strings describing their locations, like C<'/home/ken/foo.txt'> or C<'C:\Windows\Foo.txt'>) in a cross-platform manner. It supports pretty much every platform Perl runs on, including Unix, Windows, Mac, VMS, Epoc, Cygwin, OS/2, and NetWare. The well-known module L also provides this service, but it's sort of awkward to use well, so people sometimes avoid it, or use it in a way that won't actually work properly on platforms significantly different than the ones they've tested their code on. In fact, C uses C internally, wrapping all the unsightly details so you can concentrate on your application code. Whereas C provides functions for some common path manipulations, C provides an object-oriented model of the world of path specifications and their underlying semantics. C doesn't create any objects, and its classes represent the different ways in which paths must be manipulated on various platforms (not a very intuitive concept). C creates objects representing files and directories, and provides methods that relate them to each other. For instance, the following C code: my $absolute = File::Spec->file_name_is_absolute( File::Spec->catfile( @dirs, $file ) ); can be written using C as my $absolute = Path::Class::File->new( @dirs, $file )->is_absolute; or even as my $absolute = file( @dirs, $file )->is_absolute; Similar readability improvements should happen all over the place when using C. Using C can help solve real problems in your code too - for instance, how many people actually take the "volume" (like C on Windows) into account when writing C-using code? I thought not. But if you use C, your file and directory objects will know what volumes they refer to and do the right thing. The guts of the C code live in the L and L modules, so please see those modules' documentation for more details about how to use them. =head2 EXPORT The following functions are exported by default. =over 4 =item file A synonym for C<< Path::Class::File->new >>. =item dir A synonym for C<< Path::Class::Dir->new >>. =back If you would like to prevent their export, you may explicitly pass an empty list to perl's C, i.e. C. The following are exported only on demand. =over 4 =item foreign_file A synonym for C<< Path::Class::File->new_foreign >>. =item foreign_dir A synonym for C<< Path::Class::Dir->new_foreign >>. =item tempdir Create a new Path::Class::Dir instance pointed to temporary directory. my $temp = Path::Class::tempdir(CLEANUP => 1); A synonym for C<< Path::Class::Dir->new(File::Temp::tempdir(@_)) >>. =back =head1 Notes on Cross-Platform Compatibility Although it is much easier to write cross-platform-friendly code with this module than with C, there are still some issues to be aware of. =over 4 =item * On some platforms, notably VMS and some older versions of DOS (I think), all filenames must have an extension. Thus if you create a file called F and then ask for a list of files in the directory F, you may find a file called F instead of the F you were expecting. Thus it might be a good idea to use an extension in the first place. =back =head1 AUTHOR Ken Williams, KWILLIAMS@cpan.org =head1 COPYRIGHT Copyright (c) Ken Williams. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L, L =cut perl5/Path/Class/File.pm000044400000034553152462503210010761 0ustar00use strict; package Path::Class::File; { $Path::Class::File::VERSION = '0.37'; } use Path::Class::Dir; use parent qw(Path::Class::Entity); use Carp; use IO::File (); sub new { my $self = shift->SUPER::new; my $file = pop(); my @dirs = @_; my ($volume, $dirs, $base) = $self->_spec->splitpath($file); if (length $dirs) { push @dirs, $self->_spec->catpath($volume, $dirs, ''); } $self->{dir} = @dirs ? $self->dir_class->new(@dirs) : undef; $self->{file} = $base; return $self; } sub dir_class { "Path::Class::Dir" } sub as_foreign { my ($self, $type) = @_; local $Path::Class::Foreign = $self->_spec_class($type); my $foreign = ref($self)->SUPER::new; $foreign->{dir} = $self->{dir}->as_foreign($type) if defined $self->{dir}; $foreign->{file} = $self->{file}; return $foreign; } sub stringify { my $self = shift; return $self->{file} unless defined $self->{dir}; return $self->_spec->catfile($self->{dir}->stringify, $self->{file}); } sub dir { my $self = shift; return $self->{dir} if defined $self->{dir}; return $self->dir_class->new($self->_spec->curdir); } BEGIN { *parent = \&dir; } sub volume { my $self = shift; return '' unless defined $self->{dir}; return $self->{dir}->volume; } sub components { my $self = shift; croak "Arguments are not currently supported by File->components()" if @_; return ($self->dir->components, $self->basename); } sub basename { shift->{file} } sub open { IO::File->new(@_) } sub openr { $_[0]->open('r') or croak "Can't read $_[0]: $!" } sub openw { $_[0]->open('w') or croak "Can't write to $_[0]: $!" } sub opena { $_[0]->open('a') or croak "Can't append to $_[0]: $!" } sub touch { my $self = shift; if (-e $self) { utime undef, undef, $self; } else { $self->openw; } } sub slurp { my ($self, %args) = @_; my $iomode = $args{iomode} || 'r'; my $fh = $self->open($iomode) or croak "Can't read $self: $!"; if (wantarray) { my @data = <$fh>; chomp @data if $args{chomped} or $args{chomp}; if ( my $splitter = $args{split} ) { @data = map { [ split $splitter, $_ ] } @data; } return @data; } croak "'split' argument can only be used in list context" if $args{split}; if ($args{chomped} or $args{chomp}) { chomp( my @data = <$fh> ); return join '', @data; } local $/; return <$fh>; } sub spew { my $self = shift; my %args = splice( @_, 0, @_-1 ); my $iomode = $args{iomode} || 'w'; my $fh = $self->open( $iomode ) or croak "Can't write to $self: $!"; if (ref($_[0]) eq 'ARRAY') { # Use old-school for loop to avoid copying. for (my $i = 0; $i < @{ $_[0] }; $i++) { print $fh $_[0]->[$i] or croak "Can't write to $self: $!"; } } else { print $fh $_[0] or croak "Can't write to $self: $!"; } close $fh or croak "Can't write to $self: $!"; return; } sub spew_lines { my $self = shift; my %args = splice( @_, 0, @_-1 ); my $content = $_[0]; # If content is an array ref, appends $/ to each element of the array. # Otherwise, if it is a simple scalar, just appends $/ to that scalar. $content = ref( $content ) eq 'ARRAY' ? [ map { $_, $/ } @$content ] : "$content$/"; return $self->spew( %args, $content ); } sub remove { my $file = shift->stringify; return unlink $file unless -e $file; # Sets $! correctly 1 while unlink $file; return not -e $file; } sub copy_to { my ($self, $dest) = @_; if ( eval{ $dest->isa("Path::Class::File")} ) { $dest = $dest->stringify; croak "Can't copy to file $dest: it is a directory" if -d $dest; } elsif ( eval{ $dest->isa("Path::Class::Dir") } ) { $dest = $dest->stringify; croak "Can't copy to directory $dest: it is a file" if -f $dest; croak "Can't copy to directory $dest: no such directory" unless -d $dest; } elsif ( ref $dest ) { croak "Don't know how to copy files to objects of type '".ref($self)."'"; } require Perl::OSType; if ( !Perl::OSType::is_os_type('Unix') ) { require File::Copy; return unless File::Copy::cp($self->stringify, "${dest}"); } else { return unless (system('cp', $self->stringify, "${dest}") == 0); } return $self->new($dest); } sub move_to { my ($self, $dest) = @_; require File::Copy; if (File::Copy::move($self->stringify, "${dest}")) { my $new = $self->new($dest); $self->{$_} = $new->{$_} foreach (qw/ dir file /); return $self; } else { return; } } sub traverse { my $self = shift; my ($callback, @args) = @_; return $self->$callback(sub { () }, @args); } sub traverse_if { my $self = shift; my ($callback, $condition, @args) = @_; return $self->$callback(sub { () }, @args); } 1; __END__ =head1 NAME Path::Class::File - Objects representing files =head1 VERSION version 0.37 =head1 SYNOPSIS use Path::Class; # Exports file() by default my $file = file('foo', 'bar.txt'); # Path::Class::File object my $file = Path::Class::File->new('foo', 'bar.txt'); # Same thing # Stringifies to 'foo/bar.txt' on Unix, 'foo\bar.txt' on Windows, etc. print "file: $file\n"; if ($file->is_absolute) { ... } if ($file->is_relative) { ... } my $v = $file->volume; # Could be 'C:' on Windows, empty string # on Unix, 'Macintosh HD:' on Mac OS $file->cleanup; # Perform logical cleanup of pathname $file->resolve; # Perform physical cleanup of pathname my $dir = $file->dir; # A Path::Class::Dir object my $abs = $file->absolute; # Transform to absolute path my $rel = $file->relative; # Transform to relative path =head1 DESCRIPTION The C class contains functionality for manipulating file names in a cross-platform way. =head1 METHODS =over 4 =item $file = Path::Class::File->new( , , ..., ) =item $file = file( , , ..., ) Creates a new C object and returns it. The arguments specify the path to the file. Any volume may also be specified as the first argument, or as part of the first argument. You can use platform-neutral syntax: my $file = file( 'foo', 'bar', 'baz.txt' ); or platform-native syntax: my $file = file( 'foo/bar/baz.txt' ); or a mixture of the two: my $file = file( 'foo/bar', 'baz.txt' ); All three of the above examples create relative paths. To create an absolute path, either use the platform native syntax for doing so: my $file = file( '/var/tmp/foo.txt' ); or use an empty string as the first argument: my $file = file( '', 'var', 'tmp', 'foo.txt' ); If the second form seems awkward, that's somewhat intentional - paths like C or C<\Windows> aren't cross-platform concepts in the first place, so they probably shouldn't appear in your code if you're trying to be cross-platform. The first form is perfectly fine, because paths like this may come from config files, user input, or whatever. =item $file->stringify This method is called internally when a C object is used in a string context, so the following are equivalent: $string = $file->stringify; $string = "$file"; =item $file->volume Returns the volume (e.g. C on Windows, C on Mac OS, etc.) of the object, if any. Otherwise, returns the empty string. =item $file->basename Returns the name of the file as a string, without the directory portion (if any). =item $file->components Returns a list of the directory components of this file, followed by the basename. Note: unlike C<< $dir->components >>, this method currently does not accept any arguments to select which elements of the list will be returned. It may do so in the future. Currently it throws an exception if such arguments are present. =item $file->is_dir Returns a boolean value indicating whether this object represents a directory. Not surprisingly, C objects always return false, and L objects always return true. =item $file->is_absolute Returns true or false depending on whether the file refers to an absolute path specifier (like C or C<\Windows\Foo.txt>). =item $file->is_relative Returns true or false depending on whether the file refers to a relative path specifier (like C or C<.\Foo.txt>). =item $file->cleanup Performs a logical cleanup of the file path. For instance: my $file = file('/foo//baz/./foo.txt')->cleanup; # $file now represents '/foo/baz/foo.txt'; =item $dir->resolve Performs a physical cleanup of the file path. For instance: my $file = file('/foo/baz/../foo.txt')->resolve; # $file now represents '/foo/foo.txt', assuming no symlinks This actually consults the filesystem to verify the validity of the path. =item $dir = $file->dir Returns a C object representing the directory containing this file. =item $dir = $file->parent A synonym for the C method. =item $abs = $file->absolute Returns a C object representing C<$file> as an absolute path. An optional argument, given as either a string or a L object, specifies the directory to use as the base of relativity - otherwise the current working directory will be used. =item $rel = $file->relative Returns a C object representing C<$file> as a relative path. An optional argument, given as either a string or a C object, specifies the directory to use as the base of relativity - otherwise the current working directory will be used. =item $foreign = $file->as_foreign($type) Returns a C object representing C<$file> as it would be specified on a system of type C<$type>. Known types include C, C, C, C, and C, i.e. anything for which there is a subclass of C. Any generated objects (subdirectories, files, parents, etc.) will also retain this type. =item $foreign = Path::Class::File->new_foreign($type, @args) Returns a C object representing a file as it would be specified on a system of type C<$type>. Known types include C, C, C, C, and C, i.e. anything for which there is a subclass of C. The arguments in C<@args> are the same as they would be specified in C. =item $fh = $file->open($mode, $permissions) Passes the given arguments, including C<$file>, to C<< IO::File->new >> (which in turn calls C<< IO::File->open >> and returns the result as an L object. If the opening fails, C is returned and C<$!> is set. =item $fh = $file->openr() A shortcut for $fh = $file->open('r') or croak "Can't read $file: $!"; =item $fh = $file->openw() A shortcut for $fh = $file->open('w') or croak "Can't write to $file: $!"; =item $fh = $file->opena() A shortcut for $fh = $file->open('a') or croak "Can't append to $file: $!"; =item $file->touch Sets the modification and access time of the given file to right now, if the file exists. If it doesn't exist, C will I it exist, and - YES! - set its modification and access time to now. =item $file->slurp() In a scalar context, returns the contents of C<$file> in a string. In a list context, returns the lines of C<$file> (according to how C<$/> is set) as a list. If the file can't be read, this method will throw an exception. If you want C run on each line of the file, pass a true value for the C or C parameters: my @lines = $file->slurp(chomp => 1); You may also use the C parameter to pass in an IO mode to use when opening the file, usually IO layers (though anything accepted by the MODE argument of C is accepted here). Just make sure it's a I mode. my @lines = $file->slurp(iomode => ':crlf'); my $lines = $file->slurp(iomode => '<:encoding(UTF-8)'); The default C is C. Lines can also be automatically split, mimicking the perl command-line option C<-a> by using the C parameter. If this parameter is used, each line will be returned as an array ref. my @lines = $file->slurp( chomp => 1, split => qr/\s*,\s*/ ); The C parameter can only be used in a list context. =item $file->spew( $content ); The opposite of L, this takes a list of strings and prints them to the file in write mode. If the file can't be written to, this method will throw an exception. The content to be written can be either an array ref or a plain scalar. If the content is an array ref then each entry in the array will be written to the file. You may use the C parameter to pass in an IO mode to use when opening the file, just like L supports. $file->spew(iomode => '>:raw', $content); The default C is C. =item $file->spew_lines( $content ); Just like C, but, if $content is a plain scalar, appends $/ to it, or, if $content is an array ref, appends $/ to each element of the array. Can also take an C parameter like C. Again, the default C is C. =item $file->traverse(sub { ... }, @args) Calls the given callback on $file. This doesn't do much on its own, but see the associated documentation in L. =item $file->remove() This method will remove the file in a way that works well on all platforms, and returns a boolean value indicating whether or not the file was successfully removed. C is better than simply calling Perl's C function, because on some platforms (notably VMS) you actually may need to call C several times before all versions of the file are gone - the C method handles this process for you. =item $st = $file->stat() Invokes C<< File::stat::stat() >> on this file and returns a L object representing the result. =item $st = $file->lstat() Same as C, but if C<$file> is a symbolic link, C stats the link instead of the file the link points to. =item $class = $file->dir_class() Returns the class which should be used to create directory objects. Generally overridden whenever this class is subclassed. =item $copy = $file->copy_to( $dest ); Copies the C<$file> to C<$dest>. It returns a L object when successful, C otherwise. =item $moved = $file->move_to( $dest ); Moves the C<$file> to C<$dest>, and updates C<$file> accordingly. It returns C<$file> is successful, C otherwise. =back =head1 AUTHOR Ken Williams, kwilliams@cpan.org =head1 SEE ALSO L, L, L =cut perl5/Path/Class/Entity.pm000044400000004522152462503210011347 0ustar00use strict; package Path::Class::Entity; { $Path::Class::Entity::VERSION = '0.37'; } use File::Spec 3.26; use File::stat (); use Cwd; use Carp(); use overload ( q[""] => 'stringify', 'bool' => 'boolify', fallback => 1, ); sub new { my $from = shift; my ($class, $fs_class) = (ref($from) ? (ref $from, $from->{file_spec_class}) : ($from, $Path::Class::Foreign)); return bless {file_spec_class => $fs_class}, $class; } sub is_dir { 0 } sub _spec_class { my ($class, $type) = @_; die "Invalid system type '$type'" unless ($type) = $type =~ /^(\w+)$/; # Untaint my $spec = "File::Spec::$type"; ## no critic eval "require $spec; 1" or die $@; return $spec; } sub new_foreign { my ($class, $type) = (shift, shift); local $Path::Class::Foreign = $class->_spec_class($type); return $class->new(@_); } sub _spec { (ref($_[0]) && $_[0]->{file_spec_class}) || 'File::Spec' } sub boolify { 1 } sub is_absolute { # 5.6.0 has a bug with regexes and stringification that's ticked by # file_name_is_absolute(). Help it along with an explicit stringify(). $_[0]->_spec->file_name_is_absolute($_[0]->stringify) } sub is_relative { ! $_[0]->is_absolute } sub cleanup { my $self = shift; my $cleaned = $self->new( $self->_spec->canonpath("$self") ); %$self = %$cleaned; return $self; } sub resolve { my $self = shift; Carp::croak($! . " $self") unless -e $self; # No such file or directory my $cleaned = $self->new( scalar Cwd::realpath($self->stringify) ); # realpath() always returns absolute path, kind of annoying $cleaned = $cleaned->relative if $self->is_relative; %$self = %$cleaned; return $self; } sub absolute { my $self = shift; return $self if $self->is_absolute; return $self->new($self->_spec->rel2abs($self->stringify, @_)); } sub relative { my $self = shift; return $self->new($self->_spec->abs2rel($self->stringify, @_)); } sub stat { File::stat::stat("$_[0]") } sub lstat { File::stat::lstat("$_[0]") } sub PRUNE { return \&PRUNE; } 1; __END__ =head1 NAME Path::Class::Entity - Base class for files and directories =head1 VERSION version 0.37 =head1 DESCRIPTION This class is the base class for C and C, it is not used directly by callers. =head1 AUTHOR Ken Williams, kwilliams@cpan.org =head1 SEE ALSO Path::Class =cut perl5/Path/Class/Dir.pm000044400000060745152462503210010622 0ustar00use strict; package Path::Class::Dir; { $Path::Class::Dir::VERSION = '0.37'; } use Path::Class::File; use Carp(); use parent qw(Path::Class::Entity); use IO::Dir (); use File::Path (); use File::Temp (); use Scalar::Util (); # updir & curdir on the local machine, for screening them out in # children(). Note that they don't respect 'foreign' semantics. my $Updir = __PACKAGE__->_spec->updir; my $Curdir = __PACKAGE__->_spec->curdir; sub new { my $self = shift->SUPER::new(); # If the only arg is undef, it's probably a mistake. Without this # special case here, we'd return the root directory, which is a # lousy thing to do to someone when they made a mistake. Return # undef instead. return if @_==1 && !defined($_[0]); my $s = $self->_spec; my $first = (@_ == 0 ? $s->curdir : !ref($_[0]) && $_[0] eq '' ? (shift, $s->rootdir) : shift() ); $self->{dirs} = []; if ( Scalar::Util::blessed($first) && $first->isa("Path::Class::Dir") ) { $self->{volume} = $first->{volume}; push @{$self->{dirs}}, @{$first->{dirs}}; } else { ($self->{volume}, my $dirs) = $s->splitpath( $s->canonpath("$first") , 1); push @{$self->{dirs}}, $dirs eq $s->rootdir ? "" : $s->splitdir($dirs); } push @{$self->{dirs}}, map { Scalar::Util::blessed($_) && $_->isa("Path::Class::Dir") ? @{$_->{dirs}} : $s->splitdir( $s->canonpath($_) ) } @_; return $self; } sub file_class { "Path::Class::File" } sub is_dir { 1 } sub as_foreign { my ($self, $type) = @_; my $foreign = do { local $self->{file_spec_class} = $self->_spec_class($type); $self->SUPER::new; }; # Clone internal structure $foreign->{volume} = $self->{volume}; my ($u, $fu) = ($self->_spec->updir, $foreign->_spec->updir); $foreign->{dirs} = [ map {$_ eq $u ? $fu : $_} @{$self->{dirs}}]; return $foreign; } sub stringify { my $self = shift; my $s = $self->_spec; return $s->catpath($self->{volume}, $s->catdir(@{$self->{dirs}}), ''); } sub volume { shift()->{volume} } sub file { local $Path::Class::Foreign = $_[0]->{file_spec_class} if $_[0]->{file_spec_class}; return $_[0]->file_class->new(@_); } sub basename { shift()->{dirs}[-1] } sub dir_list { my $self = shift; my $d = $self->{dirs}; return @$d unless @_; my $offset = shift; if ($offset < 0) { $offset = $#$d + $offset + 1 } return wantarray ? @$d[$offset .. $#$d] : $d->[$offset] unless @_; my $length = shift; if ($length < 0) { $length = $#$d + $length + 1 - $offset } return @$d[$offset .. $length + $offset - 1]; } sub components { my $self = shift; return $self->dir_list(@_); } sub subdir { my $self = shift; return $self->new($self, @_); } sub parent { my $self = shift; my $dirs = $self->{dirs}; my ($curdir, $updir) = ($self->_spec->curdir, $self->_spec->updir); if ($self->is_absolute) { my $parent = $self->new($self); pop @{$parent->{dirs}} if @$dirs > 1; return $parent; } elsif ($self eq $curdir) { return $self->new($updir); } elsif (!grep {$_ ne $updir} @$dirs) { # All updirs return $self->new($self, $updir); # Add one more } elsif (@$dirs == 1) { return $self->new($curdir); } else { my $parent = $self->new($self); pop @{$parent->{dirs}}; return $parent; } } sub relative { # File::Spec->abs2rel before version 3.13 returned the empty string # when the two paths were equal - work around it here. my $self = shift; my $rel = $self->_spec->abs2rel($self->stringify, @_); return $self->new( length $rel ? $rel : $self->_spec->curdir ); } sub open { IO::Dir->new(@_) } sub mkpath { File::Path::mkpath(shift()->stringify, @_) } sub rmtree { File::Path::rmtree(shift()->stringify, @_) } sub remove { rmdir( shift() ); } sub traverse { my $self = shift; my ($callback, @args) = @_; my @children = $self->children; return $self->$callback( sub { my @inner_args = @_; return map { $_->traverse($callback, @inner_args) } @children; }, @args ); } sub traverse_if { my $self = shift; my ($callback, $condition, @args) = @_; my @children = grep { $condition->($_) } $self->children; return $self->$callback( sub { my @inner_args = @_; return map { $_->traverse_if($callback, $condition, @inner_args) } @children; }, @args ); } sub recurse { my $self = shift; my %opts = (preorder => 1, depthfirst => 0, @_); my $callback = $opts{callback} or Carp::croak( "Must provide a 'callback' parameter to recurse()" ); my @queue = ($self); my $visit_entry; my $visit_dir = $opts{depthfirst} && $opts{preorder} ? sub { my $dir = shift; my $ret = $callback->($dir); unless( ($ret||'') eq $self->PRUNE ) { unshift @queue, $dir->children; } } : $opts{preorder} ? sub { my $dir = shift; my $ret = $callback->($dir); unless( ($ret||'') eq $self->PRUNE ) { push @queue, $dir->children; } } : sub { my $dir = shift; $visit_entry->($_) foreach $dir->children; $callback->($dir); }; $visit_entry = sub { my $entry = shift; if ($entry->is_dir) { $visit_dir->($entry) } # Will call $callback else { $callback->($entry) } }; while (@queue) { $visit_entry->( shift @queue ); } } sub children { my ($self, %opts) = @_; my $dh = $self->open or Carp::croak( "Can't open directory $self: $!" ); my @out; while (defined(my $entry = $dh->read)) { next if !$opts{all} && $self->_is_local_dot_dir($entry); next if ($opts{no_hidden} && $entry =~ /^\./); push @out, $self->file($entry); $out[-1] = $self->subdir($entry) if -d $out[-1]; } return @out; } sub _is_local_dot_dir { my $self = shift; my $dir = shift; return ($dir eq $Updir or $dir eq $Curdir); } sub next { my $self = shift; unless ($self->{dh}) { $self->{dh} = $self->open or Carp::croak( "Can't open directory $self: $!" ); } my $next = $self->{dh}->read; unless (defined $next) { delete $self->{dh}; ## no critic return undef; } # Figure out whether it's a file or directory my $file = $self->file($next); $file = $self->subdir($next) if -d $file; return $file; } sub subsumes { Carp::croak "Too many arguments given to subsumes()" if $#_ > 2; my ($self, $other) = @_; Carp::croak( "No second entity given to subsumes()" ) unless defined $other; $other = $self->new($other) unless eval{$other->isa( "Path::Class::Entity")}; $other = $other->dir unless $other->is_dir; if ($self->is_absolute) { $other = $other->absolute; } elsif ($other->is_absolute) { $self = $self->absolute; } $self = $self->cleanup; $other = $other->cleanup; if ($self->volume || $other->volume) { return 0 unless $other->volume eq $self->volume; } # The root dir subsumes everything (but ignore the volume because # we've already checked that) return 1 if "@{$self->{dirs}}" eq "@{$self->new('')->{dirs}}"; # The current dir subsumes every relative path (unless starting with updir) if ($self eq $self->_spec->curdir) { return $other->{dirs}[0] ne $self->_spec->updir; } my $i = 0; while ($i <= $#{ $self->{dirs} }) { return 0 if $i > $#{ $other->{dirs} }; return 0 if $self->{dirs}[$i] ne $other->{dirs}[$i]; $i++; } return 1; } sub contains { Carp::croak "Too many arguments given to contains()" if $#_ > 2; my ($self, $other) = @_; Carp::croak "No second entity given to contains()" unless defined $other; return unless -d $self and (-e $other or -l $other); # We're going to resolve the path, and don't want side effects on the objects # so clone them. This also handles strings passed as $other. $self= $self->new($self)->resolve; $other= $self->new($other)->resolve; return $self->subsumes($other); } sub tempfile { my $self = shift; return File::Temp::tempfile(@_, DIR => $self->stringify); } 1; __END__ =head1 NAME Path::Class::Dir - Objects representing directories =head1 VERSION version 0.37 =head1 SYNOPSIS use Path::Class; # Exports dir() by default my $dir = dir('foo', 'bar'); # Path::Class::Dir object my $dir = Path::Class::Dir->new('foo', 'bar'); # Same thing # Stringifies to 'foo/bar' on Unix, 'foo\bar' on Windows, etc. print "dir: $dir\n"; if ($dir->is_absolute) { ... } if ($dir->is_relative) { ... } my $v = $dir->volume; # Could be 'C:' on Windows, empty string # on Unix, 'Macintosh HD:' on Mac OS $dir->cleanup; # Perform logical cleanup of pathname $dir->resolve; # Perform physical cleanup of pathname my $file = $dir->file('file.txt'); # A file in this directory my $subdir = $dir->subdir('george'); # A subdirectory my $parent = $dir->parent; # The parent directory, 'foo' my $abs = $dir->absolute; # Transform to absolute path my $rel = $abs->relative; # Transform to relative path my $rel = $abs->relative('/foo'); # Relative to /foo print $dir->as_foreign('Mac'); # :foo:bar: print $dir->as_foreign('Win32'); # foo\bar # Iterate with IO::Dir methods: my $handle = $dir->open; while (my $file = $handle->read) { $file = $dir->file($file); # Turn into Path::Class::File object ... } # Iterate with Path::Class methods: while (my $file = $dir->next) { # $file is a Path::Class::File or Path::Class::Dir object ... } =head1 DESCRIPTION The C class contains functionality for manipulating directory names in a cross-platform way. =head1 METHODS =over 4 =item $dir = Path::Class::Dir->new( , , ... ) =item $dir = dir( , , ... ) Creates a new C object and returns it. The arguments specify names of directories which will be joined to create a single directory object. A volume may also be specified as the first argument, or as part of the first argument. You can use platform-neutral syntax: my $dir = dir( 'foo', 'bar', 'baz' ); or platform-native syntax: my $dir = dir( 'foo/bar/baz' ); or a mixture of the two: my $dir = dir( 'foo/bar', 'baz' ); All three of the above examples create relative paths. To create an absolute path, either use the platform native syntax for doing so: my $dir = dir( '/var/tmp' ); or use an empty string as the first argument: my $dir = dir( '', 'var', 'tmp' ); If the second form seems awkward, that's somewhat intentional - paths like C or C<\Windows> aren't cross-platform concepts in the first place (many non-Unix platforms don't have a notion of a "root directory"), so they probably shouldn't appear in your code if you're trying to be cross-platform. The first form is perfectly natural, because paths like this may come from config files, user input, or whatever. As a special case, since it doesn't otherwise mean anything useful and it's convenient to define this way, C<< Path::Class::Dir->new() >> (or C) refers to the current directory (C<< File::Spec->curdir >>). To get the current directory as an absolute path, do C<< dir()->absolute >>. Finally, as another special case C will return undef, since that's usually an accident on the part of the caller, and returning the root directory would be a nasty surprise just asking for trouble a few lines later. =item $dir->stringify This method is called internally when a C object is used in a string context, so the following are equivalent: $string = $dir->stringify; $string = "$dir"; =item $dir->volume Returns the volume (e.g. C on Windows, C on Mac OS, etc.) of the directory object, if any. Otherwise, returns the empty string. =item $dir->basename Returns the last directory name of the path as a string. =item $dir->is_dir Returns a boolean value indicating whether this object represents a directory. Not surprisingly, L objects always return false, and C objects always return true. =item $dir->is_absolute Returns true or false depending on whether the directory refers to an absolute path specifier (like C or C<\Windows>). =item $dir->is_relative Returns true or false depending on whether the directory refers to a relative path specifier (like C or C<./dir>). =item $dir->cleanup Performs a logical cleanup of the file path. For instance: my $dir = dir('/foo//baz/./foo')->cleanup; # $dir now represents '/foo/baz/foo'; =item $dir->resolve Performs a physical cleanup of the file path. For instance: my $dir = dir('/foo//baz/../foo')->resolve; # $dir now represents '/foo/foo', assuming no symlinks This actually consults the filesystem to verify the validity of the path. =item $file = $dir->file( , , ..., ) Returns a L object representing an entry in C<$dir> or one of its subdirectories. Internally, this just calls C<< Path::Class::File->new( @_ ) >>. =item $subdir = $dir->subdir( , , ... ) Returns a new C object representing a subdirectory of C<$dir>. =item $parent = $dir->parent Returns the parent directory of C<$dir>. Note that this is the I parent, not necessarily the physical parent. It really means we just chop off entries from the end of the directory list until we cain't chop no more. If the directory is relative, we start using the relative forms of parent directories. The following code demonstrates the behavior on absolute and relative directories: $dir = dir('/foo/bar'); for (1..6) { print "Absolute: $dir\n"; $dir = $dir->parent; } $dir = dir('foo/bar'); for (1..6) { print "Relative: $dir\n"; $dir = $dir->parent; } ########### Output on Unix ################ Absolute: /foo/bar Absolute: /foo Absolute: / Absolute: / Absolute: / Absolute: / Relative: foo/bar Relative: foo Relative: . Relative: .. Relative: ../.. Relative: ../../.. =item @list = $dir->children Returns a list of L and/or C objects listed in this directory, or in scalar context the number of such objects. Obviously, it is necessary for C<$dir> to exist and be readable in order to find its children. Note that the children are returned as subdirectories of C<$dir>, i.e. the children of F will be F and F, not F and F. Ordinarily C will not include the I and I entries C<.> and C<..> (or their equivalents on non-Unix systems), because that's like I'm-my-own-grandpa business. If you do want all directory entries including these special ones, pass a true value for the C parameter: @c = $dir->children(); # Just the children @c = $dir->children(all => 1); # All entries In addition, there's a C parameter that will exclude all normally "hidden" entries - on Unix this means excluding all entries that begin with a dot (C<.>): @c = $dir->children(no_hidden => 1); # Just normally-visible entries =item $abs = $dir->absolute Returns a C object representing C<$dir> as an absolute path. An optional argument, given as either a string or a C object, specifies the directory to use as the base of relativity - otherwise the current working directory will be used. =item $rel = $dir->relative Returns a C object representing C<$dir> as a relative path. An optional argument, given as either a string or a C object, specifies the directory to use as the base of relativity - otherwise the current working directory will be used. =item $boolean = $dir->subsumes($other) Returns true if this directory spec subsumes the other spec, and false otherwise. Think of "subsumes" as "contains", but we only look at the I, not whether C<$dir> actually contains C<$other> on the filesystem. The C<$other> argument may be a C object, a L object, or a string. In the latter case, we assume it's a directory. # Examples: dir('foo/bar' )->subsumes(dir('foo/bar/baz')) # True dir('/foo/bar')->subsumes(dir('/foo/bar/baz')) # True dir('foo/..')->subsumes(dir('foo/../bar)) # True dir('foo/bar' )->subsumes(dir('bar/baz')) # False dir('/foo/bar')->subsumes(dir('foo/bar')) # False dir('foo/..')->subsumes(dir('bar')) # False! Use C to resolve ".." =item $boolean = $dir->contains($other) Returns true if this directory actually contains C<$other> on the filesystem. C<$other> doesn't have to be a direct child of C<$dir>, it just has to be subsumed after both paths have been resolved. =item $foreign = $dir->as_foreign($type) Returns a C object representing C<$dir> as it would be specified on a system of type C<$type>. Known types include C, C, C, C, and C, i.e. anything for which there is a subclass of C. Any generated objects (subdirectories, files, parents, etc.) will also retain this type. =item $foreign = Path::Class::Dir->new_foreign($type, @args) Returns a C object representing C<$dir> as it would be specified on a system of type C<$type>. Known types include C, C, C, C, and C, i.e. anything for which there is a subclass of C. The arguments in C<@args> are the same as they would be specified in C. =item @list = $dir->dir_list([OFFSET, [LENGTH]]) Returns the list of strings internally representing this directory structure. Each successive member of the list is understood to be an entry in its predecessor's directory list. By contract, C<< Path::Class->new( $dir->dir_list ) >> should be equivalent to C<$dir>. The semantics of this method are similar to Perl's C or C functions; they return C elements starting at C. If C is omitted, returns all the elements starting at C up to the end of the list. If C is negative, returns the elements from C onward except for C<-LENGTH> elements at the end. If C is negative, it counts backward C elements from the end of the list. If C and C are both omitted, the entire list is returned. In a scalar context, C with no arguments returns the number of entries in the directory list; C returns the single element at that offset; C returns the final element that would have been returned in a list context. =item $dir->components Identical to C. It exists because there's an analogous method C in the C class that also returns the basename string, so this method lets someone call C without caring whether the object is a file or a directory. =item $fh = $dir->open() Passes C<$dir> to C<< IO::Dir->open >> and returns the result as an L object. If the opening fails, C is returned and C<$!> is set. =item $dir->mkpath($verbose, $mode) Passes all arguments, including C<$dir>, to C<< File::Path::mkpath() >> and returns the result (a list of all directories created). =item $dir->rmtree($verbose, $cautious) Passes all arguments, including C<$dir>, to C<< File::Path::rmtree() >> and returns the result (the number of files successfully deleted). =item $dir->remove() Removes the directory, which must be empty. Returns a boolean value indicating whether or not the directory was successfully removed. This method is mainly provided for consistency with C's C method. =item $dir->tempfile(...) An interface to L's C function. Just like that function, if you call this in a scalar context, the return value is the filehandle and the file is Ced as soon as possible (which is immediately on Unix-like platforms). If called in a list context, the return values are the filehandle and the filename. The given directory is passed as the C parameter. Here's an example of pretty good usage which doesn't allow race conditions, won't leave yucky tempfiles around on your filesystem, etc.: my $fh = $dir->tempfile; print $fh "Here's some data...\n"; seek($fh, 0, 0); while (<$fh>) { do something... } Or in combination with a C: my $fh = $dir->tempfile; print $fh "Here's some more data...\n"; seek($fh, 0, 0); if ($pid=fork()) { wait; } else { something($_) while <$fh>; } =item $dir_or_file = $dir->next() A convenient way to iterate through directory contents. The first time C is called, it will C the directory and read the first item from it, returning the result as a C or L object (depending, of course, on its actual type). Each subsequent call to C will simply iterate over the directory's contents, until there are no more items in the directory, and then the undefined value is returned. For example, to iterate over all the regular files in a directory: while (my $file = $dir->next) { next unless -f $file; my $fh = $file->open('r') or die "Can't read $file: $!"; ... } If an error occurs when opening the directory (for instance, it doesn't exist or isn't readable), C will throw an exception with the value of C<$!>. =item $dir->traverse( sub { ... }, @args ) Calls the given callback for the root, passing it a continuation function which, when called, will call this recursively on each of its children. The callback function should be of the form: sub { my ($child, $cont, @args) = @_; # ... } For instance, to calculate the number of files in a directory, you can do this: my $nfiles = $dir->traverse(sub { my ($child, $cont) = @_; return sum($cont->(), ($child->is_dir ? 0 : 1)); }); or to calculate the maximum depth of a directory: my $depth = $dir->traverse(sub { my ($child, $cont, $depth) = @_; return max($cont->($depth + 1), $depth); }, 0); You can also choose not to call the callback in certain situations: $dir->traverse(sub { my ($child, $cont) = @_; return if -l $child; # don't follow symlinks # do something with $child return $cont->(); }); =item $dir->traverse_if( sub { ... }, sub { ... }, @args ) traverse with additional "should I visit this child" callback. Particularly useful in case examined tree contains inaccessible directories. Canonical example: $dir->traverse_if( sub { my ($child, $cont) = @_; # do something with $child return $cont->(); }, sub { my ($child) = @_; # Process only readable items return -r $child; }); Second callback gets single parameter: child. Only children for which it returns true will be processed by the first callback. Remaining parameters are interpreted as in traverse, in particular C is equivalent to C. =item $dir->recurse( callback => sub {...} ) Iterates through this directory and all of its children, and all of its children's children, etc., calling the C subroutine for each entry. This is a lot like what the L module does, and of course C will work fine on L objects, but the advantage of the C method is that it will also feed your callback routine C objects rather than just pathname strings. The C method requires a C parameter specifying the subroutine to invoke for each entry. It will be passed the C object as its first argument. C also accepts two boolean parameters, C and C that control the order of recursion. The default is a preorder, breadth-first search, i.e. C<< depthfirst => 0, preorder => 1 >>. At the time of this writing, all combinations of these two parameters are supported I C<< depthfirst => 0, preorder => 0 >>. C is normally not required to return any value. If it returns special constant C (more easily available as C<< $item->PRUNE >>), no children of analyzed item will be analyzed (mostly as if you set C<$File::Find::prune=1>). Of course pruning is available only in C, in postorder return value has no effect. =item $st = $file->stat() Invokes C<< File::stat::stat() >> on this directory and returns a C object representing the result. =item $st = $file->lstat() Same as C, but if C<$file> is a symbolic link, C stats the link instead of the directory the link points to. =item $class = $file->file_class() Returns the class which should be used to create file objects. Generally overridden whenever this class is subclassed. =back =head1 AUTHOR Ken Williams, kwilliams@cpan.org =head1 SEE ALSO L, L, L =cut perl5/HTTP/Tiny.pm000044400000234172152462503210007642 0ustar00# vim: ts=4 sts=4 sw=4 et: package HTTP::Tiny; use strict; use warnings; # ABSTRACT: A small, simple, correct HTTP/1.1 client our $VERSION = '0.078'; sub _croak { require Carp; Carp::croak(@_) } #pod =method new #pod #pod $http = HTTP::Tiny->new( %attributes ); #pod #pod This constructor returns a new HTTP::Tiny object. Valid attributes include: #pod #pod =for :list #pod * C — A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If #pod C — ends in a space character, the default user-agent string is #pod appended. #pod * C — An instance of L — or equivalent class #pod that supports the C and C methods #pod * C — A hashref of default headers to apply to requests #pod * C — The local IP address to bind to #pod * C — Whether to reuse the last connection (if for the same #pod scheme, host and port) (defaults to 1) #pod * C — Maximum number of redirects allowed (defaults to 5) #pod * C — Maximum response size in bytes (only when not using a data #pod callback). If defined, requests with responses larger than this will return #pod a 599 status code. #pod * C — URL of a proxy server to use for HTTP connections #pod (default is C<$ENV{http_proxy}> — if set) #pod * C — URL of a proxy server to use for HTTPS connections #pod (default is C<$ENV{https_proxy}> — if set) #pod * C — URL of a generic proxy server for both HTTP and HTTPS #pod connections (default is C<$ENV{all_proxy}> — if set) #pod * C — List of domain suffixes that should not be proxied. Must #pod be a comma-separated string or an array reference. (default is #pod C<$ENV{no_proxy}> —) #pod * C — Request timeout in seconds (default is 60) If a socket open, #pod read or write takes longer than the timeout, the request response status code #pod will be 599. #pod * C — A boolean that indicates whether to validate the SSL #pod certificate of an C — connection (default is false) #pod * C — A hashref of C — options to pass through to #pod L #pod #pod An accessor/mutator method exists for each attribute. #pod #pod Passing an explicit C for C, C or C will #pod prevent getting the corresponding proxies from the environment. #pod #pod Errors during request execution will result in a pseudo-HTTP status code of 599 #pod and a reason of "Internal Exception". The content field in the response will #pod contain the text of the error. #pod #pod The C parameter enables a persistent connection, but only to a #pod single destination scheme, host and port. If any connection-relevant #pod attributes are modified via accessor, or if the process ID or thread ID change, #pod the persistent connection will be dropped. If you want persistent connections #pod across multiple destinations, use multiple HTTP::Tiny objects. #pod #pod See L for more on the C and C attributes. #pod #pod =cut my @attributes; BEGIN { @attributes = qw( cookie_jar default_headers http_proxy https_proxy keep_alive local_address max_redirect max_size proxy no_proxy SSL_options verify_SSL ); my %persist_ok = map {; $_ => 1 } qw( cookie_jar default_headers max_redirect max_size ); no strict 'refs'; no warnings 'uninitialized'; for my $accessor ( @attributes ) { *{$accessor} = sub { @_ > 1 ? do { delete $_[0]->{handle} if !$persist_ok{$accessor} && $_[1] ne $_[0]->{$accessor}; $_[0]->{$accessor} = $_[1] } : $_[0]->{$accessor}; }; } } sub agent { my($self, $agent) = @_; if( @_ > 1 ){ $self->{agent} = (defined $agent && $agent =~ / $/) ? $agent . $self->_agent : $agent; } return $self->{agent}; } sub timeout { my ($self, $timeout) = @_; if ( @_ > 1 ) { $self->{timeout} = $timeout; if ($self->{handle}) { $self->{handle}->timeout($timeout); } } return $self->{timeout}; } sub new { my($class, %args) = @_; my $self = { max_redirect => 5, timeout => defined $args{timeout} ? $args{timeout} : 60, keep_alive => 1, verify_SSL => $args{verify_SSL} || $args{verify_ssl} || 0, # no verification by default no_proxy => $ENV{no_proxy}, }; bless $self, $class; $class->_validate_cookie_jar( $args{cookie_jar} ) if $args{cookie_jar}; for my $key ( @attributes ) { $self->{$key} = $args{$key} if exists $args{$key} } $self->agent( exists $args{agent} ? $args{agent} : $class->_agent ); $self->_set_proxies; return $self; } sub _set_proxies { my ($self) = @_; # get proxies from %ENV only if not provided; explicit undef will disable # getting proxies from the environment # generic proxy if (! exists $self->{proxy} ) { $self->{proxy} = $ENV{all_proxy} || $ENV{ALL_PROXY}; } if ( defined $self->{proxy} ) { $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # validate } else { delete $self->{proxy}; } # http proxy if (! exists $self->{http_proxy} ) { # under CGI, bypass HTTP_PROXY as request sets it from Proxy header local $ENV{HTTP_PROXY} = $ENV{CGI_HTTP_PROXY} if $ENV{REQUEST_METHOD}; $self->{http_proxy} = $ENV{http_proxy} || $ENV{HTTP_PROXY} || $self->{proxy}; } if ( defined $self->{http_proxy} ) { $self->_split_proxy( http_proxy => $self->{http_proxy} ); # validate $self->{_has_proxy}{http} = 1; } else { delete $self->{http_proxy}; } # https proxy if (! exists $self->{https_proxy} ) { $self->{https_proxy} = $ENV{https_proxy} || $ENV{HTTPS_PROXY} || $self->{proxy}; } if ( $self->{https_proxy} ) { $self->_split_proxy( https_proxy => $self->{https_proxy} ); # validate $self->{_has_proxy}{https} = 1; } else { delete $self->{https_proxy}; } # Split no_proxy to array reference if not provided as such unless ( ref $self->{no_proxy} eq 'ARRAY' ) { $self->{no_proxy} = (defined $self->{no_proxy}) ? [ split /\s*,\s*/, $self->{no_proxy} ] : []; } return; } #pod =method get|head|put|post|patch|delete #pod #pod $response = $http->get($url); #pod $response = $http->get($url, \%options); #pod $response = $http->head($url); #pod #pod These methods are shorthand for calling C for the given method. The #pod URL must have unsafe characters escaped and international domain names encoded. #pod See C for valid options and a description of the response. #pod #pod The C field of the response will be true if the status code is 2XX. #pod #pod =cut for my $sub_name ( qw/get head put post patch delete/ ) { my $req_method = uc $sub_name; no strict 'refs'; eval <<"HERE"; ## no critic sub $sub_name { my (\$self, \$url, \$args) = \@_; \@_ == 2 || (\@_ == 3 && ref \$args eq 'HASH') or _croak(q/Usage: \$http->$sub_name(URL, [HASHREF])/ . "\n"); return \$self->request('$req_method', \$url, \$args || {}); } HERE } #pod =method post_form #pod #pod $response = $http->post_form($url, $form_data); #pod $response = $http->post_form($url, $form_data, \%options); #pod #pod This method executes a C request and sends the key/value pairs from a #pod form data hash or array reference to the given URL with a C of #pod C. If data is provided as an array #pod reference, the order is preserved; if provided as a hash reference, the terms #pod are sorted on key and value for consistency. See documentation for the #pod C method for details on the encoding. #pod #pod The URL must have unsafe characters escaped and international domain names #pod encoded. See C for valid options and a description of the response. #pod Any C header or content in the options hashref will be ignored. #pod #pod The C field of the response will be true if the status code is 2XX. #pod #pod =cut sub post_form { my ($self, $url, $data, $args) = @_; (@_ == 3 || @_ == 4 && ref $args eq 'HASH') or _croak(q/Usage: $http->post_form(URL, DATAREF, [HASHREF])/ . "\n"); my $headers = {}; while ( my ($key, $value) = each %{$args->{headers} || {}} ) { $headers->{lc $key} = $value; } delete $args->{headers}; return $self->request('POST', $url, { %$args, content => $self->www_form_urlencode($data), headers => { %$headers, 'content-type' => 'application/x-www-form-urlencoded' }, } ); } #pod =method mirror #pod #pod $response = $http->mirror($url, $file, \%options) #pod if ( $response->{success} ) { #pod print "$file is up to date\n"; #pod } #pod #pod Executes a C request for the URL and saves the response body to the file #pod name provided. The URL must have unsafe characters escaped and international #pod domain names encoded. If the file already exists, the request will include an #pod C header with the modification timestamp of the file. You #pod may specify a different C header yourself in the C<< #pod $options->{headers} >> hash. #pod #pod The C field of the response will be true if the status code is 2XX #pod or if the status code is 304 (unmodified). #pod #pod If the file was modified and the server response includes a properly #pod formatted C header, the file modification time will #pod be updated accordingly. #pod #pod =cut sub mirror { my ($self, $url, $file, $args) = @_; @_ == 3 || (@_ == 4 && ref $args eq 'HASH') or _croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ . "\n"); if ( exists $args->{headers} ) { my $headers = {}; while ( my ($key, $value) = each %{$args->{headers} || {}} ) { $headers->{lc $key} = $value; } $args->{headers} = $headers; } if ( -e $file and my $mtime = (stat($file))[9] ) { $args->{headers}{'if-modified-since'} ||= $self->_http_date($mtime); } my $tempfile = $file . int(rand(2**31)); require Fcntl; sysopen my $fh, $tempfile, Fcntl::O_CREAT()|Fcntl::O_EXCL()|Fcntl::O_WRONLY() or _croak(qq/Error: Could not create temporary file $tempfile for downloading: $!\n/); binmode $fh; $args->{data_callback} = sub { print {$fh} $_[0] }; my $response = $self->request('GET', $url, $args); close $fh or _croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/); if ( $response->{success} ) { rename $tempfile, $file or _croak(qq/Error replacing $file with $tempfile: $!\n/); my $lm = $response->{headers}{'last-modified'}; if ( $lm and my $mtime = $self->_parse_http_date($lm) ) { utime $mtime, $mtime, $file; } } $response->{success} ||= $response->{status} eq '304'; unlink $tempfile; return $response; } #pod =method request #pod #pod $response = $http->request($method, $url); #pod $response = $http->request($method, $url, \%options); #pod #pod Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST', #pod 'PUT', etc.) on the given URL. The URL must have unsafe characters escaped and #pod international domain names encoded. #pod #pod B: Method names are B per the HTTP/1.1 specification. #pod Don't use C when you really want C. See L for #pod how this applies to redirection. #pod #pod If the URL includes a "user:password" stanza, they will be used for Basic-style #pod authorization headers. (Authorization headers will not be included in a #pod redirected request.) For example: #pod #pod $http->request('GET', 'http://Aladdin:open sesame@example.com/'); #pod #pod If the "user:password" stanza contains reserved characters, they must #pod be percent-escaped: #pod #pod $http->request('GET', 'http://john%40example.com:password@example.com/'); #pod #pod A hashref of options may be appended to modify the request. #pod #pod Valid options are: #pod #pod =for :list #pod * C — #pod A hashref containing headers to include with the request. If the value for #pod a header is an array reference, the header will be output multiple times with #pod each value in the array. These headers over-write any default headers. #pod * C — #pod A scalar to include as the body of the request OR a code reference #pod that will be called iteratively to produce the body of the request #pod * C — #pod A code reference that will be called if it exists to provide a hashref #pod of trailing headers (only used with chunked transfer-encoding) #pod * C — #pod A code reference that will be called for each chunks of the response #pod body received. #pod * C — #pod Override host resolution and force all connections to go only to a #pod specific peer address, regardless of the URL of the request. This will #pod include any redirections! This options should be used with extreme #pod caution (e.g. debugging or very special circumstances). It can be given as #pod either a scalar or a code reference that will receive the hostname and #pod whose response will be taken as the address. #pod #pod The C header is generated from the URL in accordance with RFC 2616. It #pod is a fatal error to specify C in the C option. Other headers #pod may be ignored or overwritten if necessary for transport compliance. #pod #pod If the C option is a code reference, it will be called iteratively #pod to provide the content body of the request. It should return the empty #pod string or undef when the iterator is exhausted. #pod #pod If the C option is the empty string, no C or #pod C headers will be generated. #pod #pod If the C option is provided, it will be called iteratively until #pod the entire response body is received. The first argument will be a string #pod containing a chunk of the response body, the second argument will be the #pod in-progress response hash reference, as described below. (This allows #pod customizing the action of the callback based on the C or C #pod received prior to the content body.) #pod #pod The C method returns a hashref containing the response. The hashref #pod will have the following keys: #pod #pod =for :list #pod * C — #pod Boolean indicating whether the operation returned a 2XX status code #pod * C — #pod URL that provided the response. This is the URL of the request unless #pod there were redirections, in which case it is the last URL queried #pod in a redirection chain #pod * C — #pod The HTTP status code of the response #pod * C — #pod The response phrase returned by the server #pod * C — #pod The body of the response. If the response does not have any content #pod or if a data callback is provided to consume the response body, #pod this will be the empty string #pod * C — #pod A hashref of header fields. All header field names will be normalized #pod to be lower case. If a header is repeated, the value will be an arrayref; #pod it will otherwise be a scalar string containing the value #pod * C - #pod If this field exists, it is the protocol of the response #pod such as HTTP/1.0 or HTTP/1.1 #pod * C #pod If this field exists, it is an arrayref of response hash references from #pod redirects in the same order that redirections occurred. If it does #pod not exist, then no redirections occurred. #pod #pod On an error during the execution of the request, the C field will #pod contain 599, and the C field will contain the text of the error. #pod #pod =cut my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/; sub request { my ($self, $method, $url, $args) = @_; @_ == 3 || (@_ == 4 && ref $args eq 'HASH') or _croak(q/Usage: $http->request(METHOD, URL, [HASHREF])/ . "\n"); $args ||= {}; # we keep some state in this during _request # RFC 2616 Section 8.1.4 mandates a single retry on broken socket my $response; for ( 0 .. 1 ) { $response = eval { $self->_request($method, $url, $args) }; last unless $@ && $idempotent{$method} && $@ =~ m{^(?:Socket closed|Unexpected end|SSL read error)}; } if (my $e = $@) { # maybe we got a response hash thrown from somewhere deep if ( ref $e eq 'HASH' && exists $e->{status} ) { $e->{redirects} = delete $args->{_redirects} if @{ $args->{_redirects} || []}; return $e; } # otherwise, stringify it $e = "$e"; $response = { url => $url, success => q{}, status => 599, reason => 'Internal Exception', content => $e, headers => { 'content-type' => 'text/plain', 'content-length' => length $e, }, ( @{$args->{_redirects} || []} ? (redirects => delete $args->{_redirects}) : () ), }; } return $response; } #pod =method www_form_urlencode #pod #pod $params = $http->www_form_urlencode( $data ); #pod $response = $http->get("http://example.com/query?$params"); #pod #pod This method converts the key/value pairs from a data hash or array reference #pod into a C string. The keys and values from the data #pod reference will be UTF-8 encoded and escaped per RFC 3986. If a value is an #pod array reference, the key will be repeated with each of the values of the array #pod reference. If data is provided as a hash reference, the key/value pairs in the #pod resulting string will be sorted by key and value for consistent ordering. #pod #pod =cut sub www_form_urlencode { my ($self, $data) = @_; (@_ == 2 && ref $data) or _croak(q/Usage: $http->www_form_urlencode(DATAREF)/ . "\n"); (ref $data eq 'HASH' || ref $data eq 'ARRAY') or _croak("form data must be a hash or array reference\n"); my @params = ref $data eq 'HASH' ? %$data : @$data; @params % 2 == 0 or _croak("form data reference must have an even number of terms\n"); my @terms; while( @params ) { my ($key, $value) = splice(@params, 0, 2); _croak("form data keys must not be undef") if !defined($key); if ( ref $value eq 'ARRAY' ) { unshift @params, map { $key => $_ } @$value; } else { push @terms, join("=", map { $self->_uri_escape($_) } $key, $value); } } return join("&", (ref $data eq 'ARRAY') ? (@terms) : (sort @terms) ); } #pod =method can_ssl #pod #pod $ok = HTTP::Tiny->can_ssl; #pod ($ok, $why) = HTTP::Tiny->can_ssl; #pod ($ok, $why) = $http->can_ssl; #pod #pod Indicates if SSL support is available. When called as a class object, it #pod checks for the correct version of L and L. #pod When called as an object methods, if C is true or if C #pod is set in C, it checks that a CA file is available. #pod #pod In scalar context, returns a boolean indicating if SSL is available. #pod In list context, returns the boolean and a (possibly multi-line) string of #pod errors indicating why SSL isn't available. #pod #pod =cut sub can_ssl { my ($self) = @_; my($ok, $reason) = (1, ''); # Need IO::Socket::SSL 1.42 for SSL_create_ctx_callback local @INC = @INC; pop @INC if $INC[-1] eq '.'; unless (eval {require IO::Socket::SSL; IO::Socket::SSL->VERSION(1.42)}) { $ok = 0; $reason .= qq/IO::Socket::SSL 1.42 must be installed for https support\n/; } # Need Net::SSLeay 1.49 for MODE_AUTO_RETRY unless (eval {require Net::SSLeay; Net::SSLeay->VERSION(1.49)}) { $ok = 0; $reason .= qq/Net::SSLeay 1.49 must be installed for https support\n/; } # If an object, check that SSL config lets us get a CA if necessary if ( ref($self) && ( $self->{verify_SSL} || $self->{SSL_options}{SSL_verify_mode} ) ) { my $handle = HTTP::Tiny::Handle->new( SSL_options => $self->{SSL_options}, verify_SSL => $self->{verify_SSL}, ); unless ( eval { $handle->_find_CA_file; 1 } ) { $ok = 0; $reason .= "$@"; } } wantarray ? ($ok, $reason) : $ok; } #pod =method connected #pod #pod $host = $http->connected; #pod ($host, $port) = $http->connected; #pod #pod Indicates if a connection to a peer is being kept alive, per the C #pod option. #pod #pod In scalar context, returns the peer host and port, joined with a colon, or #pod C (if no peer is connected). #pod In list context, returns the peer host and port or an empty list (if no peer #pod is connected). #pod #pod B: This method cannot reliably be used to discover whether the remote #pod host has closed its end of the socket. #pod #pod =cut sub connected { my ($self) = @_; if ( $self->{handle} ) { return $self->{handle}->connected; } return; } #--------------------------------------------------------------------------# # private methods #--------------------------------------------------------------------------# my %DefaultPort = ( http => 80, https => 443, ); sub _agent { my $class = ref($_[0]) || $_[0]; (my $default_agent = $class) =~ s{::}{-}g; my $version = $class->VERSION; $default_agent .= "/$version" if defined $version; return $default_agent; } sub _request { my ($self, $method, $url, $args) = @_; my ($scheme, $host, $port, $path_query, $auth) = $self->_split_url($url); if ($scheme ne 'http' && $scheme ne 'https') { die(qq/Unsupported URL scheme '$scheme'\n/); } my $request = { method => $method, scheme => $scheme, host => $host, port => $port, host_port => ($port == $DefaultPort{$scheme} ? $host : "$host:$port"), uri => $path_query, headers => {}, }; my $peer = $args->{peer} || $host; # Allow 'peer' to be a coderef. if ('CODE' eq ref $peer) { $peer = $peer->($host); } # We remove the cached handle so it is not reused in the case of redirect. # If all is well, it will be recached at the end of _request. We only # reuse for the same scheme, host and port my $handle = delete $self->{handle}; if ( $handle ) { unless ( $handle->can_reuse( $scheme, $host, $port, $peer ) ) { $handle->close; undef $handle; } } $handle ||= $self->_open_handle( $request, $scheme, $host, $port, $peer ); $self->_prepare_headers_and_cb($request, $args, $url, $auth); $handle->write_request($request); my $response; do { $response = $handle->read_response_header } until (substr($response->{status},0,1) ne '1'); $self->_update_cookie_jar( $url, $response ) if $self->{cookie_jar}; my @redir_args = $self->_maybe_redirect($request, $response, $args); my $known_message_length; if ($method eq 'HEAD' || $response->{status} =~ /^[23]04/) { # response has no message body $known_message_length = 1; } else { # Ignore any data callbacks during redirection. my $cb_args = @redir_args ? +{} : $args; my $data_cb = $self->_prepare_data_cb($response, $cb_args); $known_message_length = $handle->read_body($data_cb, $response); } if ( $self->{keep_alive} && $handle->connected && $known_message_length && $response->{protocol} eq 'HTTP/1.1' && ($response->{headers}{connection} || '') ne 'close' ) { $self->{handle} = $handle; } else { $handle->close; } $response->{success} = substr( $response->{status}, 0, 1 ) eq '2'; $response->{url} = $url; # Push the current response onto the stack of redirects if redirecting. if (@redir_args) { push @{$args->{_redirects}}, $response; return $self->_request(@redir_args, $args); } # Copy the stack of redirects into the response before returning. $response->{redirects} = delete $args->{_redirects} if @{$args->{_redirects}}; return $response; } sub _open_handle { my ($self, $request, $scheme, $host, $port, $peer) = @_; my $handle = HTTP::Tiny::Handle->new( timeout => $self->{timeout}, SSL_options => $self->{SSL_options}, verify_SSL => $self->{verify_SSL}, local_address => $self->{local_address}, keep_alive => $self->{keep_alive} ); if ($self->{_has_proxy}{$scheme} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) { return $self->_proxy_connect( $request, $handle ); } else { return $handle->connect($scheme, $host, $port, $peer); } } sub _proxy_connect { my ($self, $request, $handle) = @_; my @proxy_vars; if ( $request->{scheme} eq 'https' ) { _croak(qq{No https_proxy defined}) unless $self->{https_proxy}; @proxy_vars = $self->_split_proxy( https_proxy => $self->{https_proxy} ); if ( $proxy_vars[0] eq 'https' ) { _croak(qq{Can't proxy https over https: $request->{uri} via $self->{https_proxy}}); } } else { _croak(qq{No http_proxy defined}) unless $self->{http_proxy}; @proxy_vars = $self->_split_proxy( http_proxy => $self->{http_proxy} ); } my ($p_scheme, $p_host, $p_port, $p_auth) = @proxy_vars; if ( length $p_auth && ! defined $request->{headers}{'proxy-authorization'} ) { $self->_add_basic_auth_header( $request, 'proxy-authorization' => $p_auth ); } $handle->connect($p_scheme, $p_host, $p_port, $p_host); if ($request->{scheme} eq 'https') { $self->_create_proxy_tunnel( $request, $handle ); } else { # non-tunneled proxy requires absolute URI $request->{uri} = "$request->{scheme}://$request->{host_port}$request->{uri}"; } return $handle; } sub _split_proxy { my ($self, $type, $proxy) = @_; my ($scheme, $host, $port, $path_query, $auth) = eval { $self->_split_url($proxy) }; unless( defined($scheme) && length($scheme) && length($host) && length($port) && $path_query eq '/' ) { _croak(qq{$type URL must be in format http[s]://[auth@]:/\n}); } return ($scheme, $host, $port, $auth); } sub _create_proxy_tunnel { my ($self, $request, $handle) = @_; $handle->_assert_ssl; my $agent = exists($request->{headers}{'user-agent'}) ? $request->{headers}{'user-agent'} : $self->{agent}; my $connect_request = { method => 'CONNECT', uri => "$request->{host}:$request->{port}", headers => { host => "$request->{host}:$request->{port}", 'user-agent' => $agent, } }; if ( $request->{headers}{'proxy-authorization'} ) { $connect_request->{headers}{'proxy-authorization'} = delete $request->{headers}{'proxy-authorization'}; } $handle->write_request($connect_request); my $response; do { $response = $handle->read_response_header } until (substr($response->{status},0,1) ne '1'); # if CONNECT failed, throw the response so it will be # returned from the original request() method; unless (substr($response->{status},0,1) eq '2') { die $response; } # tunnel established, so start SSL handshake $handle->start_ssl( $request->{host} ); return; } sub _prepare_headers_and_cb { my ($self, $request, $args, $url, $auth) = @_; for ($self->{default_headers}, $args->{headers}) { next unless defined; while (my ($k, $v) = each %$_) { $request->{headers}{lc $k} = $v; $request->{header_case}{lc $k} = $k; } } if (exists $request->{headers}{'host'}) { die(qq/The 'Host' header must not be provided as header option\n/); } $request->{headers}{'host'} = $request->{host_port}; $request->{headers}{'user-agent'} ||= $self->{agent}; $request->{headers}{'connection'} = "close" unless $self->{keep_alive}; # Some servers error on an empty-body PUT/POST without a content-length if ( $request->{method} eq 'PUT' || $request->{method} eq 'POST' ) { if (!defined($args->{content}) || !length($args->{content}) ) { $request->{headers}{'content-length'} = 0; } } if ( defined $args->{content} ) { if ( ref $args->{content} eq 'CODE' ) { if ( exists $request->{'content-length'} && $request->{'content-length'} == 0 ) { $request->{cb} = sub { "" }; } else { $request->{headers}{'content-type'} ||= "application/octet-stream"; $request->{headers}{'transfer-encoding'} = 'chunked' unless exists $request->{headers}{'content-length'} || $request->{headers}{'transfer-encoding'}; $request->{cb} = $args->{content}; } } elsif ( length $args->{content} ) { my $content = $args->{content}; if ( $] ge '5.008' ) { utf8::downgrade($content, 1) or die(qq/Wide character in request message body\n/); } $request->{headers}{'content-type'} ||= "application/octet-stream"; $request->{headers}{'content-length'} = length $content unless $request->{headers}{'content-length'} || $request->{headers}{'transfer-encoding'}; $request->{cb} = sub { substr $content, 0, length $content, '' }; } $request->{trailer_cb} = $args->{trailer_callback} if ref $args->{trailer_callback} eq 'CODE'; } ### If we have a cookie jar, then maybe add relevant cookies if ( $self->{cookie_jar} ) { my $cookies = $self->cookie_jar->cookie_header( $url ); $request->{headers}{cookie} = $cookies if length $cookies; } # if we have Basic auth parameters, add them if ( length $auth && ! defined $request->{headers}{authorization} ) { $self->_add_basic_auth_header( $request, 'authorization' => $auth ); } return; } sub _add_basic_auth_header { my ($self, $request, $header, $auth) = @_; require MIME::Base64; $request->{headers}{$header} = "Basic " . MIME::Base64::encode_base64($auth, ""); return; } sub _prepare_data_cb { my ($self, $response, $args) = @_; my $data_cb = $args->{data_callback}; $response->{content} = ''; if (!$data_cb || $response->{status} !~ /^2/) { if (defined $self->{max_size}) { $data_cb = sub { $_[1]->{content} .= $_[0]; die(qq/Size of response body exceeds the maximum allowed of $self->{max_size}\n/) if length $_[1]->{content} > $self->{max_size}; }; } else { $data_cb = sub { $_[1]->{content} .= $_[0] }; } } return $data_cb; } sub _update_cookie_jar { my ($self, $url, $response) = @_; my $cookies = $response->{headers}->{'set-cookie'}; return unless defined $cookies; my @cookies = ref $cookies ? @$cookies : $cookies; $self->cookie_jar->add( $url, $_ ) for @cookies; return; } sub _validate_cookie_jar { my ($class, $jar) = @_; # duck typing for my $method ( qw/add cookie_header/ ) { _croak(qq/Cookie jar must provide the '$method' method\n/) unless ref($jar) && ref($jar)->can($method); } return; } sub _maybe_redirect { my ($self, $request, $response, $args) = @_; my $headers = $response->{headers}; my ($status, $method) = ($response->{status}, $request->{method}); $args->{_redirects} ||= []; if (($status eq '303' or ($status =~ /^30[1278]/ && $method =~ /^GET|HEAD$/)) and $headers->{location} and @{$args->{_redirects}} < $self->{max_redirect} ) { my $location = ($headers->{location} =~ /^\//) ? "$request->{scheme}://$request->{host_port}$headers->{location}" : $headers->{location} ; return (($status eq '303' ? 'GET' : $method), $location); } return; } sub _split_url { my $url = pop; # URI regex adapted from the URI module my ($scheme, $host, $path_query) = $url =~ m<\A([^:/?#]+)://([^/?#]*)([^#]*)> or die(qq/Cannot parse URL: '$url'\n/); $scheme = lc $scheme; $path_query = "/$path_query" unless $path_query =~ m<\A/>; my $auth = ''; if ( (my $i = index $host, '@') != -1 ) { # user:pass@host $auth = substr $host, 0, $i, ''; # take up to the @ for auth substr $host, 0, 1, ''; # knock the @ off the host # userinfo might be percent escaped, so recover real auth info $auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; } my $port = $host =~ s/:(\d*)\z// && length $1 ? $1 : $scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef; return ($scheme, (length $host ? lc $host : "localhost") , $port, $path_query, $auth); } # Date conversions adapted from HTTP::Date my $DoW = "Sun|Mon|Tue|Wed|Thu|Fri|Sat"; my $MoY = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"; sub _http_date { my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($_[1]); return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT", substr($DoW,$wday*4,3), $mday, substr($MoY,$mon*4,3), $year+1900, $hour, $min, $sec ); } sub _parse_http_date { my ($self, $str) = @_; require Time::Local; my @tl_parts; if ($str =~ /^[SMTWF][a-z]+, +(\d{1,2}) ($MoY) +(\d\d\d\d) +(\d\d):(\d\d):(\d\d) +GMT$/) { @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3); } elsif ($str =~ /^[SMTWF][a-z]+, +(\d\d)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT$/ ) { @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3); } elsif ($str =~ /^[SMTWF][a-z]+ +($MoY) +(\d{1,2}) +(\d\d):(\d\d):(\d\d) +(?:[^0-9]+ +)?(\d\d\d\d)$/ ) { @tl_parts = ($5, $4, $3, $2, (index($MoY,$1)/4), $6); } return eval { my $t = @tl_parts ? Time::Local::timegm(@tl_parts) : -1; $t < 0 ? undef : $t; }; } # URI escaping adapted from URI::Escape # c.f. http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 # perl 5.6 ready UTF-8 encoding adapted from JSON::PP my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; $escapes{' '}="+"; my $unsafe_char = qr/[^A-Za-z0-9\-\._~]/; sub _uri_escape { my ($self, $str) = @_; return "" if !defined $str; if ( $] ge '5.008' ) { utf8::encode($str); } else { $str = pack("U*", unpack("C*", $str)) # UTF-8 encode a byte string if ( length $str == do { use bytes; length $str } ); $str = pack("C*", unpack("C*", $str)); # clear UTF-8 flag } $str =~ s/($unsafe_char)/$escapes{$1}/g; return $str; } package HTTP::Tiny::Handle; # hide from PAUSE/indexers use strict; use warnings; use Errno qw[EINTR EPIPE]; use IO::Socket qw[SOCK_STREAM]; use Socket qw[SOL_SOCKET SO_KEEPALIVE]; # PERL_HTTP_TINY_IPV4_ONLY is a private environment variable to force old # behavior if someone is unable to boostrap CPAN from a new perl install; it is # not intended for general, per-client use and may be removed in the future my $SOCKET_CLASS = $ENV{PERL_HTTP_TINY_IPV4_ONLY} ? 'IO::Socket::INET' : eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.32) } ? 'IO::Socket::IP' : 'IO::Socket::INET'; sub BUFSIZE () { 32768 } ## no critic my $Printable = sub { local $_ = shift; s/\r/\\r/g; s/\n/\\n/g; s/\t/\\t/g; s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge; $_; }; my $Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/; my $Field_Content = qr/[[:print:]]+ (?: [\x20\x09]+ [[:print:]]+ )*/x; sub new { my ($class, %args) = @_; return bless { rbuf => '', timeout => 60, max_line_size => 16384, max_header_lines => 64, verify_SSL => 0, SSL_options => {}, %args }, $class; } sub timeout { my ($self, $timeout) = @_; if ( @_ > 1 ) { $self->{timeout} = $timeout; if ( $self->{fh} && $self->{fh}->can('timeout') ) { $self->{fh}->timeout($timeout); } } return $self->{timeout}; } sub connect { @_ == 5 || die(q/Usage: $handle->connect(scheme, host, port, peer)/ . "\n"); my ($self, $scheme, $host, $port, $peer) = @_; if ( $scheme eq 'https' ) { $self->_assert_ssl; } $self->{fh} = $SOCKET_CLASS->new( PeerHost => $peer, PeerPort => $port, $self->{local_address} ? ( LocalAddr => $self->{local_address} ) : (), Proto => 'tcp', Type => SOCK_STREAM, Timeout => $self->{timeout}, ) or die(qq/Could not connect to '$host:$port': $@\n/); binmode($self->{fh}) or die(qq/Could not binmode() socket: '$!'\n/); if ( $self->{keep_alive} ) { unless ( defined( $self->{fh}->setsockopt( SOL_SOCKET, SO_KEEPALIVE, 1 ) ) ) { CORE::close($self->{fh}); die(qq/Could not set SO_KEEPALIVE on socket: '$!'\n/); } } $self->start_ssl($host) if $scheme eq 'https'; $self->{scheme} = $scheme; $self->{host} = $host; $self->{peer} = $peer; $self->{port} = $port; $self->{pid} = $$; $self->{tid} = _get_tid(); return $self; } sub connected { my ($self) = @_; if ( $self->{fh} && $self->{fh}->connected ) { return wantarray ? ( $self->{fh}->peerhost, $self->{fh}->peerport ) : join( ':', $self->{fh}->peerhost, $self->{fh}->peerport ); } return; } sub start_ssl { my ($self, $host) = @_; # As this might be used via CONNECT after an SSL session # to a proxy, we shut down any existing SSL before attempting # the handshake if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) { unless ( $self->{fh}->stop_SSL ) { my $ssl_err = IO::Socket::SSL->errstr; die(qq/Error halting prior SSL connection: $ssl_err/); } } my $ssl_args = $self->_ssl_args($host); IO::Socket::SSL->start_SSL( $self->{fh}, %$ssl_args, SSL_create_ctx_callback => sub { my $ctx = shift; Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY()); }, ); unless ( ref($self->{fh}) eq 'IO::Socket::SSL' ) { my $ssl_err = IO::Socket::SSL->errstr; die(qq/SSL connection failed for $host: $ssl_err\n/); } } sub close { @_ == 1 || die(q/Usage: $handle->close()/ . "\n"); my ($self) = @_; CORE::close($self->{fh}) or die(qq/Could not close socket: '$!'\n/); } sub write { @_ == 2 || die(q/Usage: $handle->write(buf)/ . "\n"); my ($self, $buf) = @_; if ( $] ge '5.008' ) { utf8::downgrade($buf, 1) or die(qq/Wide character in write()\n/); } my $len = length $buf; my $off = 0; local $SIG{PIPE} = 'IGNORE'; while () { $self->can_write or die(qq/Timed out while waiting for socket to become ready for writing\n/); my $r = syswrite($self->{fh}, $buf, $len, $off); if (defined $r) { $len -= $r; $off += $r; last unless $len > 0; } elsif ($! == EPIPE) { die(qq/Socket closed by remote server: $!\n/); } elsif ($! != EINTR) { if ($self->{fh}->can('errstr')){ my $err = $self->{fh}->errstr(); die (qq/Could not write to SSL socket: '$err'\n /); } else { die(qq/Could not write to socket: '$!'\n/); } } } return $off; } sub read { @_ == 2 || @_ == 3 || die(q/Usage: $handle->read(len [, allow_partial])/ . "\n"); my ($self, $len, $allow_partial) = @_; my $buf = ''; my $got = length $self->{rbuf}; if ($got) { my $take = ($got < $len) ? $got : $len; $buf = substr($self->{rbuf}, 0, $take, ''); $len -= $take; } # Ignore SIGPIPE because SSL reads can result in writes that might error. # See "Expecting exactly the same behavior as plain sockets" in # https://metacpan.org/dist/IO-Socket-SSL/view/lib/IO/Socket/SSL.pod#Common-Usage-Errors local $SIG{PIPE} = 'IGNORE'; while ($len > 0) { $self->can_read or die(q/Timed out while waiting for socket to become ready for reading/ . "\n"); my $r = sysread($self->{fh}, $buf, $len, length $buf); if (defined $r) { last unless $r; $len -= $r; } elsif ($! != EINTR) { if ($self->{fh}->can('errstr')){ my $err = $self->{fh}->errstr(); die (qq/Could not read from SSL socket: '$err'\n /); } else { die(qq/Could not read from socket: '$!'\n/); } } } if ($len && !$allow_partial) { die(qq/Unexpected end of stream\n/); } return $buf; } sub readline { @_ == 1 || die(q/Usage: $handle->readline()/ . "\n"); my ($self) = @_; while () { if ($self->{rbuf} =~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x) { return $1; } if (length $self->{rbuf} >= $self->{max_line_size}) { die(qq/Line size exceeds the maximum allowed size of $self->{max_line_size}\n/); } $self->can_read or die(qq/Timed out while waiting for socket to become ready for reading\n/); my $r = sysread($self->{fh}, $self->{rbuf}, BUFSIZE, length $self->{rbuf}); if (defined $r) { last unless $r; } elsif ($! != EINTR) { if ($self->{fh}->can('errstr')){ my $err = $self->{fh}->errstr(); die (qq/Could not read from SSL socket: '$err'\n /); } else { die(qq/Could not read from socket: '$!'\n/); } } } die(qq/Unexpected end of stream while looking for line\n/); } sub read_header_lines { @_ == 1 || @_ == 2 || die(q/Usage: $handle->read_header_lines([headers])/ . "\n"); my ($self, $headers) = @_; $headers ||= {}; my $lines = 0; my $val; while () { my $line = $self->readline; if (++$lines >= $self->{max_header_lines}) { die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/); } elsif ($line =~ /\A ([^\x00-\x1F\x7F:]+) : [\x09\x20]* ([^\x0D\x0A]*)/x) { my ($field_name) = lc $1; if (exists $headers->{$field_name}) { for ($headers->{$field_name}) { $_ = [$_] unless ref $_ eq "ARRAY"; push @$_, $2; $val = \$_->[-1]; } } else { $val = \($headers->{$field_name} = $2); } } elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x) { $val or die(qq/Unexpected header continuation line\n/); next unless length $1; $$val .= ' ' if length $$val; $$val .= $1; } elsif ($line =~ /\A \x0D?\x0A \z/x) { last; } else { die(q/Malformed header line: / . $Printable->($line) . "\n"); } } return $headers; } sub write_request { @_ == 2 || die(q/Usage: $handle->write_request(request)/ . "\n"); my($self, $request) = @_; $self->write_request_header(@{$request}{qw/method uri headers header_case/}); $self->write_body($request) if $request->{cb}; return; } # Standard request header names/case from HTTP/1.1 RFCs my @rfc_request_headers = qw( Accept Accept-Charset Accept-Encoding Accept-Language Authorization Cache-Control Connection Content-Length Expect From Host If-Match If-Modified-Since If-None-Match If-Range If-Unmodified-Since Max-Forwards Pragma Proxy-Authorization Range Referer TE Trailer Transfer-Encoding Upgrade User-Agent Via ); my @other_request_headers = qw( Content-Encoding Content-MD5 Content-Type Cookie DNT Date Origin X-XSS-Protection ); my %HeaderCase = map { lc($_) => $_ } @rfc_request_headers, @other_request_headers; # to avoid multiple small writes and hence nagle, you can pass the method line or anything else to # combine writes. sub write_header_lines { (@_ >= 2 && @_ <= 4 && ref $_[1] eq 'HASH') || die(q/Usage: $handle->write_header_lines(headers, [header_case, prefix])/ . "\n"); my($self, $headers, $header_case, $prefix_data) = @_; $header_case ||= {}; my $buf = (defined $prefix_data ? $prefix_data : ''); # Per RFC, control fields should be listed first my %seen; for my $k ( qw/host cache-control expect max-forwards pragma range te/ ) { next unless exists $headers->{$k}; $seen{$k}++; my $field_name = $HeaderCase{$k}; my $v = $headers->{$k}; for (ref $v eq 'ARRAY' ? @$v : $v) { $_ = '' unless defined $_; $buf .= "$field_name: $_\x0D\x0A"; } } # Other headers sent in arbitrary order while (my ($k, $v) = each %$headers) { my $field_name = lc $k; next if $seen{$field_name}; if (exists $HeaderCase{$field_name}) { $field_name = $HeaderCase{$field_name}; } else { if (exists $header_case->{$field_name}) { $field_name = $header_case->{$field_name}; } else { $field_name =~ s/\b(\w)/\u$1/g; } $field_name =~ /\A $Token+ \z/xo or die(q/Invalid HTTP header field name: / . $Printable->($field_name) . "\n"); $HeaderCase{lc $field_name} = $field_name; } for (ref $v eq 'ARRAY' ? @$v : $v) { # unwrap a field value if pre-wrapped by user s/\x0D?\x0A\s+/ /g; die(qq/Invalid HTTP header field value ($field_name): / . $Printable->($_). "\n") unless $_ eq '' || /\A $Field_Content \z/xo; $_ = '' unless defined $_; $buf .= "$field_name: $_\x0D\x0A"; } } $buf .= "\x0D\x0A"; return $self->write($buf); } # return value indicates whether message length was defined; this is generally # true unless there was no content-length header and we just read until EOF. # Other message length errors are thrown as exceptions sub read_body { @_ == 3 || die(q/Usage: $handle->read_body(callback, response)/ . "\n"); my ($self, $cb, $response) = @_; my $te = $response->{headers}{'transfer-encoding'} || ''; my $chunked = grep { /chunked/i } ( ref $te eq 'ARRAY' ? @$te : $te ) ; return $chunked ? $self->read_chunked_body($cb, $response) : $self->read_content_body($cb, $response); } sub write_body { @_ == 2 || die(q/Usage: $handle->write_body(request)/ . "\n"); my ($self, $request) = @_; if (exists $request->{headers}{'content-length'}) { return unless $request->{headers}{'content-length'}; return $self->write_content_body($request); } else { return $self->write_chunked_body($request); } } sub read_content_body { @_ == 3 || @_ == 4 || die(q/Usage: $handle->read_content_body(callback, response, [read_length])/ . "\n"); my ($self, $cb, $response, $content_length) = @_; $content_length ||= $response->{headers}{'content-length'}; if ( defined $content_length ) { my $len = $content_length; while ($len > 0) { my $read = ($len > BUFSIZE) ? BUFSIZE : $len; $cb->($self->read($read, 0), $response); $len -= $read; } return length($self->{rbuf}) == 0; } my $chunk; $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) ); return; } sub write_content_body { @_ == 2 || die(q/Usage: $handle->write_content_body(request)/ . "\n"); my ($self, $request) = @_; my ($len, $content_length) = (0, $request->{headers}{'content-length'}); while () { my $data = $request->{cb}->(); defined $data && length $data or last; if ( $] ge '5.008' ) { utf8::downgrade($data, 1) or die(qq/Wide character in write_content()\n/); } $len += $self->write($data); } $len == $content_length or die(qq/Content-Length mismatch (got: $len expected: $content_length)\n/); return $len; } sub read_chunked_body { @_ == 3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ . "\n"); my ($self, $cb, $response) = @_; while () { my $head = $self->readline; $head =~ /\A ([A-Fa-f0-9]+)/x or die(q/Malformed chunk head: / . $Printable->($head) . "\n"); my $len = hex($1) or last; $self->read_content_body($cb, $response, $len); $self->read(2) eq "\x0D\x0A" or die(qq/Malformed chunk: missing CRLF after chunk data\n/); } $self->read_header_lines($response->{headers}); return 1; } sub write_chunked_body { @_ == 2 || die(q/Usage: $handle->write_chunked_body(request)/ . "\n"); my ($self, $request) = @_; my $len = 0; while () { my $data = $request->{cb}->(); defined $data && length $data or last; if ( $] ge '5.008' ) { utf8::downgrade($data, 1) or die(qq/Wide character in write_chunked_body()\n/); } $len += length $data; my $chunk = sprintf '%X', length $data; $chunk .= "\x0D\x0A"; $chunk .= $data; $chunk .= "\x0D\x0A"; $self->write($chunk); } $self->write("0\x0D\x0A"); if ( ref $request->{trailer_cb} eq 'CODE' ) { $self->write_header_lines($request->{trailer_cb}->()) } else { $self->write("\x0D\x0A"); } return $len; } sub read_response_header { @_ == 1 || die(q/Usage: $handle->read_response_header()/ . "\n"); my ($self) = @_; my $line = $self->readline; $line =~ /\A (HTTP\/(0*\d+\.0*\d+)) [\x09\x20]+ ([0-9]{3}) (?: [\x09\x20]+ ([^\x0D\x0A]*) )? \x0D?\x0A/x or die(q/Malformed Status-Line: / . $Printable->($line). "\n"); my ($protocol, $version, $status, $reason) = ($1, $2, $3, $4); $reason = "" unless defined $reason; die (qq/Unsupported HTTP protocol: $protocol\n/) unless $version =~ /0*1\.0*[01]/; return { status => $status, reason => $reason, headers => $self->read_header_lines, protocol => $protocol, }; } sub write_request_header { @_ == 5 || die(q/Usage: $handle->write_request_header(method, request_uri, headers, header_case)/ . "\n"); my ($self, $method, $request_uri, $headers, $header_case) = @_; return $self->write_header_lines($headers, $header_case, "$method $request_uri HTTP/1.1\x0D\x0A"); } sub _do_timeout { my ($self, $type, $timeout) = @_; $timeout = $self->{timeout} unless defined $timeout && $timeout >= 0; my $fd = fileno $self->{fh}; defined $fd && $fd >= 0 or die(qq/select(2): 'Bad file descriptor'\n/); my $initial = time; my $pending = $timeout; my $nfound; vec(my $fdset = '', $fd, 1) = 1; while () { $nfound = ($type eq 'read') ? select($fdset, undef, undef, $pending) : select(undef, $fdset, undef, $pending) ; if ($nfound == -1) { $! == EINTR or die(qq/select(2): '$!'\n/); redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0; $nfound = 0; } last; } $! = 0; return $nfound; } sub can_read { @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_read([timeout])/ . "\n"); my $self = shift; if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) { return 1 if $self->{fh}->pending; } return $self->_do_timeout('read', @_) } sub can_write { @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_write([timeout])/ . "\n"); my $self = shift; return $self->_do_timeout('write', @_) } sub _assert_ssl { my($ok, $reason) = HTTP::Tiny->can_ssl(); die $reason unless $ok; } sub can_reuse { my ($self,$scheme,$host,$port,$peer) = @_; return 0 if $self->{pid} != $$ || $self->{tid} != _get_tid() || length($self->{rbuf}) || $scheme ne $self->{scheme} || $host ne $self->{host} || $port ne $self->{port} || $peer ne $self->{peer} || eval { $self->can_read(0) } || $@ ; return 1; } # Try to find a CA bundle to validate the SSL cert, # prefer Mozilla::CA or fallback to a system file sub _find_CA_file { my $self = shift(); my $ca_file = defined( $self->{SSL_options}->{SSL_ca_file} ) ? $self->{SSL_options}->{SSL_ca_file} : $ENV{SSL_CERT_FILE}; if ( defined $ca_file ) { unless ( -r $ca_file ) { die qq/SSL_ca_file '$ca_file' not found or not readable\n/; } return $ca_file; } local @INC = @INC; pop @INC if $INC[-1] eq '.'; return Mozilla::CA::SSL_ca_file() if eval { require Mozilla::CA; 1 }; # cert list copied from golang src/crypto/x509/root_unix.go foreach my $ca_bundle ( "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc. "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL "/etc/ssl/ca-bundle.pem", # OpenSUSE "/etc/openssl/certs/ca-certificates.crt", # NetBSD "/etc/ssl/cert.pem", # OpenBSD "/usr/local/share/certs/ca-root-nss.crt", # FreeBSD/DragonFly "/etc/pki/tls/cacert.pem", # OpenELEC "/etc/certs/ca-certificates.crt", # Solaris 11.2+ ) { return $ca_bundle if -e $ca_bundle; } die qq/Couldn't find a CA bundle with which to verify the SSL certificate.\n/ . qq/Try installing Mozilla::CA from CPAN\n/; } # for thread safety, we need to know thread id if threads are loaded sub _get_tid { no warnings 'reserved'; # for 'threads' return threads->can("tid") ? threads->tid : 0; } sub _ssl_args { my ($self, $host) = @_; my %ssl_args; # This test reimplements IO::Socket::SSL::can_client_sni(), which wasn't # added until IO::Socket::SSL 1.84 if ( Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x01000000 ) { $ssl_args{SSL_hostname} = $host, # Sane SNI support } if ($self->{verify_SSL}) { $ssl_args{SSL_verifycn_scheme} = 'http'; # enable CN validation $ssl_args{SSL_verifycn_name} = $host; # set validation hostname $ssl_args{SSL_verify_mode} = 0x01; # enable cert validation $ssl_args{SSL_ca_file} = $self->_find_CA_file; } else { $ssl_args{SSL_verifycn_scheme} = 'none'; # disable CN validation $ssl_args{SSL_verify_mode} = 0x00; # disable cert validation } # user options override settings from verify_SSL for my $k ( keys %{$self->{SSL_options}} ) { $ssl_args{$k} = $self->{SSL_options}{$k} if $k =~ m/^SSL_/; } return \%ssl_args; } 1; __END__ =pod =encoding UTF-8 =head1 NAME HTTP::Tiny - A small, simple, correct HTTP/1.1 client =head1 VERSION version 0.078 =head1 SYNOPSIS use HTTP::Tiny; my $response = HTTP::Tiny->new->get('http://example.com/'); die "Failed!\n" unless $response->{success}; print "$response->{status} $response->{reason}\n"; while (my ($k, $v) = each %{$response->{headers}}) { for (ref $v eq 'ARRAY' ? @$v : $v) { print "$k: $_\n"; } } print $response->{content} if length $response->{content}; =head1 DESCRIPTION This is a very simple HTTP/1.1 client, designed for doing simple requests without the overhead of a large framework like L. It is more correct and more complete than L. It supports proxies and redirection. It also correctly resumes after EINTR. If L 0.25 or later is installed, HTTP::Tiny will use it instead of L for transparent support for both IPv4 and IPv6. Cookie support requires L or an equivalent class. =head1 METHODS =head2 new $http = HTTP::Tiny->new( %attributes ); This constructor returns a new HTTP::Tiny object. Valid attributes include: =over 4 =item * C — A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C — ends in a space character, the default user-agent string is appended. =item * C — An instance of L — or equivalent class that supports the C and C methods =item * C — A hashref of default headers to apply to requests =item * C — The local IP address to bind to =item * C — Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1) =item * C — Maximum number of redirects allowed (defaults to 5) =item * C — Maximum response size in bytes (only when not using a data callback). If defined, requests with responses larger than this will return a 599 status code. =item * C — URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> — if set) =item * C — URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> — if set) =item * C — URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> — if set) =item * C — List of domain suffixes that should not be proxied. Must be a comma-separated string or an array reference. (default is C<$ENV{no_proxy}> —) =item * C — Request timeout in seconds (default is 60) If a socket open, read or write takes longer than the timeout, the request response status code will be 599. =item * C — A boolean that indicates whether to validate the SSL certificate of an C — connection (default is false) =item * C — A hashref of C — options to pass through to L =back An accessor/mutator method exists for each attribute. Passing an explicit C for C, C or C will prevent getting the corresponding proxies from the environment. Errors during request execution will result in a pseudo-HTTP status code of 599 and a reason of "Internal Exception". The content field in the response will contain the text of the error. The C parameter enables a persistent connection, but only to a single destination scheme, host and port. If any connection-relevant attributes are modified via accessor, or if the process ID or thread ID change, the persistent connection will be dropped. If you want persistent connections across multiple destinations, use multiple HTTP::Tiny objects. See L for more on the C and C attributes. =head2 get|head|put|post|patch|delete $response = $http->get($url); $response = $http->get($url, \%options); $response = $http->head($url); These methods are shorthand for calling C for the given method. The URL must have unsafe characters escaped and international domain names encoded. See C for valid options and a description of the response. The C field of the response will be true if the status code is 2XX. =head2 post_form $response = $http->post_form($url, $form_data); $response = $http->post_form($url, $form_data, \%options); This method executes a C request and sends the key/value pairs from a form data hash or array reference to the given URL with a C of C. If data is provided as an array reference, the order is preserved; if provided as a hash reference, the terms are sorted on key and value for consistency. See documentation for the C method for details on the encoding. The URL must have unsafe characters escaped and international domain names encoded. See C for valid options and a description of the response. Any C header or content in the options hashref will be ignored. The C field of the response will be true if the status code is 2XX. =head2 mirror $response = $http->mirror($url, $file, \%options) if ( $response->{success} ) { print "$file is up to date\n"; } Executes a C request for the URL and saves the response body to the file name provided. The URL must have unsafe characters escaped and international domain names encoded. If the file already exists, the request will include an C header with the modification timestamp of the file. You may specify a different C header yourself in the C<< $options->{headers} >> hash. The C field of the response will be true if the status code is 2XX or if the status code is 304 (unmodified). If the file was modified and the server response includes a properly formatted C header, the file modification time will be updated accordingly. =head2 request $response = $http->request($method, $url); $response = $http->request($method, $url, \%options); Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST', 'PUT', etc.) on the given URL. The URL must have unsafe characters escaped and international domain names encoded. B: Method names are B per the HTTP/1.1 specification. Don't use C when you really want C. See L for how this applies to redirection. If the URL includes a "user:password" stanza, they will be used for Basic-style authorization headers. (Authorization headers will not be included in a redirected request.) For example: $http->request('GET', 'http://Aladdin:open sesame@example.com/'); If the "user:password" stanza contains reserved characters, they must be percent-escaped: $http->request('GET', 'http://john%40example.com:password@example.com/'); A hashref of options may be appended to modify the request. Valid options are: =over 4 =item * C — A hashref containing headers to include with the request. If the value for a header is an array reference, the header will be output multiple times with each value in the array. These headers over-write any default headers. =item * C — A scalar to include as the body of the request OR a code reference that will be called iteratively to produce the body of the request =item * C — A code reference that will be called if it exists to provide a hashref of trailing headers (only used with chunked transfer-encoding) =item * C — A code reference that will be called for each chunks of the response body received. =item * C — Override host resolution and force all connections to go only to a specific peer address, regardless of the URL of the request. This will include any redirections! This options should be used with extreme caution (e.g. debugging or very special circumstances). It can be given as either a scalar or a code reference that will receive the hostname and whose response will be taken as the address. =back The C header is generated from the URL in accordance with RFC 2616. It is a fatal error to specify C in the C option. Other headers may be ignored or overwritten if necessary for transport compliance. If the C option is a code reference, it will be called iteratively to provide the content body of the request. It should return the empty string or undef when the iterator is exhausted. If the C option is the empty string, no C or C headers will be generated. If the C option is provided, it will be called iteratively until the entire response body is received. The first argument will be a string containing a chunk of the response body, the second argument will be the in-progress response hash reference, as described below. (This allows customizing the action of the callback based on the C or C received prior to the content body.) The C method returns a hashref containing the response. The hashref will have the following keys: =over 4 =item * C — Boolean indicating whether the operation returned a 2XX status code =item * C — URL that provided the response. This is the URL of the request unless there were redirections, in which case it is the last URL queried in a redirection chain =item * C — The HTTP status code of the response =item * C — The response phrase returned by the server =item * C — The body of the response. If the response does not have any content or if a data callback is provided to consume the response body, this will be the empty string =item * C — A hashref of header fields. All header field names will be normalized to be lower case. If a header is repeated, the value will be an arrayref; it will otherwise be a scalar string containing the value =item * C - If this field exists, it is the protocol of the response such as HTTP/1.0 or HTTP/1.1 =item * C If this field exists, it is an arrayref of response hash references from redirects in the same order that redirections occurred. If it does not exist, then no redirections occurred. =back On an error during the execution of the request, the C field will contain 599, and the C field will contain the text of the error. =head2 www_form_urlencode $params = $http->www_form_urlencode( $data ); $response = $http->get("http://example.com/query?$params"); This method converts the key/value pairs from a data hash or array reference into a C string. The keys and values from the data reference will be UTF-8 encoded and escaped per RFC 3986. If a value is an array reference, the key will be repeated with each of the values of the array reference. If data is provided as a hash reference, the key/value pairs in the resulting string will be sorted by key and value for consistent ordering. =head2 can_ssl $ok = HTTP::Tiny->can_ssl; ($ok, $why) = HTTP::Tiny->can_ssl; ($ok, $why) = $http->can_ssl; Indicates if SSL support is available. When called as a class object, it checks for the correct version of L and L. When called as an object methods, if C is true or if C is set in C, it checks that a CA file is available. In scalar context, returns a boolean indicating if SSL is available. In list context, returns the boolean and a (possibly multi-line) string of errors indicating why SSL isn't available. =head2 connected $host = $http->connected; ($host, $port) = $http->connected; Indicates if a connection to a peer is being kept alive, per the C option. In scalar context, returns the peer host and port, joined with a colon, or C (if no peer is connected). In list context, returns the peer host and port or an empty list (if no peer is connected). B: This method cannot reliably be used to discover whether the remote host has closed its end of the socket. =for Pod::Coverage SSL_options agent cookie_jar default_headers http_proxy https_proxy keep_alive local_address max_redirect max_size no_proxy proxy timeout verify_SSL =head1 SSL SUPPORT Direct C connections are supported only if L 1.56 or greater and L 1.49 or greater are installed. An error will occur if new enough versions of these modules are not installed or if the SSL encryption fails. You can also use C utility function that returns boolean to see if the required modules are installed. An C connection may be made via an C proxy that supports the CONNECT command (i.e. RFC 2817). You may not proxy C via a proxy that itself requires C to communicate. SSL provides two distinct capabilities: =over 4 =item * Encrypted communication channel =item * Verification of server identity =back B. Server identity verification is controversial and potentially tricky because it depends on a (usually paid) third-party Certificate Authority (CA) trust model to validate a certificate as legitimate. This discriminates against servers with self-signed certificates or certificates signed by free, community-driven CA's such as L. By default, HTTP::Tiny does not make any assumptions about your trust model, threat level or risk tolerance. It just aims to give you an encrypted channel when you need one. Setting the C attribute to a true value will make HTTP::Tiny verify that an SSL connection has a valid SSL certificate corresponding to the host name of the connection and that the SSL certificate has been verified by a CA. Assuming you trust the CA, this will protect against a L. If you are concerned about security, you should enable this option. Certificate verification requires a file containing trusted CA certificates. If the environment variable C is present, HTTP::Tiny will try to find a CA certificate file in that location. If the L module is installed, HTTP::Tiny will use the CA file included with it as a source of trusted CA's. (This means you trust Mozilla, the author of Mozilla::CA, the CPAN mirror where you got Mozilla::CA, the toolchain used to install it, and your operating system security, right?) If that module is not available, then HTTP::Tiny will search several system-specific default locations for a CA certificate file: =over 4 =item * /etc/ssl/certs/ca-certificates.crt =item * /etc/pki/tls/certs/ca-bundle.crt =item * /etc/ssl/ca-bundle.pem =back An error will be occur if C is true and no CA certificate file is available. If you desire complete control over SSL connections, the C attribute lets you provide a hash reference that will be passed through to C, overriding any options set by HTTP::Tiny. For example, to provide your own trusted CA file: SSL_options => { SSL_ca_file => $file_path, } The C attribute could also be used for such things as providing a client certificate for authentication to a server or controlling the choice of cipher used for the SSL connection. See L documentation for details. =head1 PROXY SUPPORT HTTP::Tiny can proxy both C and C requests. Only Basic proxy authorization is supported and it must be provided as part of the proxy URL: C. HTTP::Tiny supports the following proxy environment variables: =over 4 =item * http_proxy or HTTP_PROXY =item * https_proxy or HTTPS_PROXY =item * all_proxy or ALL_PROXY =back If the C environment variable is set, then this might be a CGI process and C would be set from the C header, which is a security risk. If C is set, C (the upper case variant only) is ignored, but C is considered instead. Tunnelling C over an C proxy using the CONNECT method is supported. If your proxy uses C itself, you can not tunnel C over it. Be warned that proxying an C connection opens you to the risk of a man-in-the-middle attack by the proxy server. The C environment variable is supported in the format of a comma-separated list of domain extensions proxy should not be used for. Proxy arguments passed to C will override their corresponding environment variables. =head1 LIMITATIONS HTTP::Tiny is I with the L: =over 4 =item * "Message Syntax and Routing" [RFC7230] =item * "Semantics and Content" [RFC7231] =item * "Conditional Requests" [RFC7232] =item * "Range Requests" [RFC7233] =item * "Caching" [RFC7234] =item * "Authentication" [RFC7235] =back It attempts to meet all "MUST" requirements of the specification, but does not implement all "SHOULD" requirements. (Note: it was developed against the earlier RFC 2616 specification and may not yet meet the revised RFC 7230-7235 spec.) Additionally, HTTP::Tiny supports the C method of RFC 5789. Some particular limitations of note include: =over =item * HTTP::Tiny focuses on correct transport. Users are responsible for ensuring that user-defined headers and content are compliant with the HTTP/1.1 specification. =item * Users must ensure that URLs are properly escaped for unsafe characters and that international domain names are properly encoded to ASCII. See L, L and L. =item * Redirection is very strict against the specification. Redirection is only automatic for response codes 301, 302, 307 and 308 if the request method is 'GET' or 'HEAD'. Response code 303 is always converted into a 'GET' redirection, as mandated by the specification. There is no automatic support for status 305 ("Use proxy") redirections. =item * There is no provision for delaying a request body using an C header. Unexpected C<1XX> responses are silently ignored as per the specification. =item * Only 'chunked' C is supported. =item * There is no support for a Request-URI of '*' for the 'OPTIONS' request. =item * Headers mentioned in the RFCs and some other, well-known headers are generated with their canonical case. Other headers are sent in the case provided by the user. Except for control headers (which are sent first), headers are sent in arbitrary order. =back Despite the limitations listed above, HTTP::Tiny is considered feature-complete. New feature requests should be directed to L. =head1 SEE ALSO =over 4 =item * L - Higher level UA features for HTTP::Tiny =item * L - HTTP::Tiny wrapper with L/L compatibility =item * L - Wrap L instance in HTTP::Tiny compatible interface =item * L - Required for IPv6 support =item * L - Required for SSL support =item * L - If HTTP::Tiny isn't enough for you, this is the "standard" way to do things =item * L - Required if you want to validate SSL certificates =item * L - Required for SSL support =back =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at L. You will be notified automatically of any progress on your issue. =head2 Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. L git clone https://github.com/chansen/p5-http-tiny.git =head1 AUTHORS =over 4 =item * Christian Hansen =item * David Golden =back =head1 CONTRIBUTORS =for stopwords Alan Gardner Alessandro Ghedini A. Sinan Unur Brad Gilbert brian m. carlson Chris Nehren Weyl Claes Jakobsson Clinton Gormley Craig Berry David Golden Mitchell Dean Pearce Edward Zborowski Felipe Gasper Greg Kennedy James E Keenan Raspass Jeremy Mates Jess Robinson Karen Etheridge Lukas Eklund Martin J. Evans Martin-Louis Bright Matthew Horsfall Michael R. Davis Mike Doherty Nicolas Rochelemagne Olaf Alders Olivier Mengué Petr Písař sanjay-cpu Serguei Trouchelle Shoichi Kaji SkyMarshal Sören Kornetzki Steve Grazzini Syohei YOSHIDA Tatsuhiko Miyagawa Tom Hukins Tony Cook Xavier Guimard =over 4 =item * Alan Gardner =item * Alessandro Ghedini =item * A. Sinan Unur =item * Brad Gilbert =item * brian m. carlson =item * Chris Nehren =item * Chris Weyl =item * Claes Jakobsson =item * Clinton Gormley =item * Craig A. Berry =item * Craig Berry =item * David Golden =item * David Mitchell =item * Dean Pearce =item * Edward Zborowski =item * Felipe Gasper =item * Greg Kennedy =item * James E Keenan =item * James Raspass =item * Jeremy Mates =item * Jess Robinson =item * Karen Etheridge =item * Lukas Eklund =item * Martin J. Evans =item * Martin-Louis Bright =item * Matthew Horsfall =item * Michael R. Davis =item * Mike Doherty =item * Nicolas Rochelemagne =item * Olaf Alders =item * Olivier Mengué =item * Petr Písař =item * sanjay-cpu =item * Serguei Trouchelle =item * Shoichi Kaji =item * SkyMarshal =item * Sören Kornetzki =item * Steve Grazzini =item * Syohei YOSHIDA =item * Tatsuhiko Miyagawa =item * Tom Hukins =item * Tony Cook =item * Xavier Guimard =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2021 by Christian Hansen. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut perl5/x86_64-linux-thread-multi/.meta/JSON-PP-4.06/MYMETA.json000044400000002257152462503210016635 0ustar00{ "abstract" : "JSON::XS compatible pure-Perl module.", "author" : [ "Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "JSON-PP", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Scalar::Util" : "1.08", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/makamaka/JSON-PP/issues" }, "repository" : { "url" : "https://github.com/makamaka/JSON-PP" } }, "version" : "4.06", "x_serialization_backend" : "JSON::PP version 4.06" } perl5/x86_64-linux-thread-multi/.meta/JSON-PP-4.06/install.json000044400000000501152462503210017275 0ustar00{"pathname":"I/IS/ISHIGAKI/JSON-PP-4.06.tar.gz","name":"JSON::PP","dist":"JSON-PP-4.06","target":"JSON::PP","provides":{"JSON::PP":{"file":"lib/JSON/PP.pm","version":4.06},"JSON::PP::IncrParser":{"version":4.06,"file":"lib/JSON/PP.pm"},"JSON::PP::Boolean":{"file":"lib/JSON/PP/Boolean.pm","version":4.06}},"version":4.06}perl5/x86_64-linux-thread-multi/.meta/DBI-1.643/MYMETA.json000044400000003323152462503210016224 0ustar00{ "abstract" : "Database independent interface for Perl", "author" : [ "Tim Bunce (dbi-users@perl.org)" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "DBI", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "6.48", "Test::Simple" : "0.90" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "conflicts" : { "DBD::Amazon" : "0.10", "DBD::AnyData" : "0.110", "DBD::CSV" : "0.36", "DBD::Google" : "0.51", "DBD::PO" : "2.10", "DBD::RAM" : "0.072", "SQL::Statement" : "1.33" }, "requires" : { "perl" : "5.008001" } } }, "release_status" : "stable", "resources" : { "homepage" : "http://dbi.perl.org/", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "https://github.com/perl5-dbi/dbi" }, "x_IRC" : "irc://irc.perl.org/#dbi", "x_MailingList" : "mailto:dbi-dev@perl.org" }, "version" : "1.643", "x_serialization_backend" : "JSON::PP version 4.06", "x_suggests" : { "Clone" : 0.34, "DB_File" : 0, "MLDBM" : 0, "Net::Daemon" : 0, "RPC::PlServer" : 0.2001, "SQL::Statement" : 1.402 } } perl5/x86_64-linux-thread-multi/.meta/DBI-1.643/install.json000044400000015537152462503210016710 0ustar00{"pathname":"T/TI/TIMB/DBI-1.643.tar.gz","name":"DBI","dist":"DBI-1.643","target":"DBI","provides":{"DBD::File::DataSource::File":{"version":0.44,"file":"lib/DBD/File.pm"},"DBI::DBD::SqlEngine::db":{"file":"lib/DBI/DBD/SqlEngine.pm","version":0.06},"DBI::ProfileSubs":{"file":"lib/DBI/ProfileSubs.pm","version":0.009396},"DBD::DBM::st":{"version":0.08,"file":"lib/DBD/DBM.pm"},"DBI::Gofer::Transport::Base":{"file":"lib/DBI/Gofer/Transport/Base.pm","version":0.012537},"DBD::Proxy::st":{"version":0.2004,"file":"lib/DBD/Proxy.pm"},"DBI::Const::GetInfo::ODBC":{"file":"lib/DBI/Const/GetInfo/ODBC.pm","version":2.011374},"DBI::Util::CacheMemory":{"version":0.010315,"file":"lib/DBI/Util/CacheMemory.pm"},"DBI::ProfileDumper":{"version":2.015325,"file":"lib/DBI/ProfileDumper.pm"},"DBI::ProxyServer::dr":{"version":0.3005,"file":"lib/DBI/ProxyServer.pm"},"DBD::Sponge::st":{"file":"lib/DBD/Sponge.pm","version":12.010003},"DBI::ProfileData":{"version":2.010008,"file":"lib/DBI/ProfileData.pm"},"DBD::DBM":{"version":0.08,"file":"lib/DBD/DBM.pm"},"DBD::Mem":{"version":0.001,"file":"lib/DBD/Mem.pm"},"DBI::DBD::Metadata":{"version":2.014214,"file":"lib/DBI/DBD/Metadata.pm"},"DBI::SQL::Nano":{"version":1.015544,"file":"lib/DBI/SQL/Nano.pm"},"DBI::SQL::Nano::Table_":{"file":"lib/DBI/SQL/Nano.pm","version":1.015544},"DBD::Sponge::db":{"version":12.010003,"file":"lib/DBD/Sponge.pm"},"DBD::Gofer::Policy::pedantic":{"file":"lib/DBD/Gofer/Policy/pedantic.pm","version":0.010088},"DBD::File::TableSource::FileSystem":{"version":0.44,"file":"lib/DBD/File.pm"},"DBD::File::DataSource::Stream":{"version":0.44,"file":"lib/DBD/File.pm"},"DBI::ProxyServer::db":{"version":0.3005,"file":"lib/DBI/ProxyServer.pm"},"DBI::Const::GetInfo::ANSI":{"version":2.008697,"file":"lib/DBI/Const/GetInfo/ANSI.pm"},"DBD::File::dr":{"version":0.44,"file":"lib/DBD/File.pm"},"DBI::Profile":{"version":2.015065,"file":"lib/DBI/Profile.pm"},"DBI::DBD":{"version":12.015129,"file":"lib/DBI/DBD.pm"},"DBI::Gofer::Transport::pipeone":{"version":0.012537,"file":"lib/DBI/Gofer/Transport/pipeone.pm"},"DBD::Gofer::Transport::null":{"version":0.010088,"file":"lib/DBD/Gofer/Transport/null.pm"},"DBD::Gofer":{"file":"lib/DBD/Gofer.pm","version":0.015327},"DBD::Gofer::Policy::classic":{"version":0.010088,"file":"lib/DBD/Gofer/Policy/classic.pm"},"DBI::ProxyServer::st":{"file":"lib/DBI/ProxyServer.pm","version":0.3005},"DBD::File::Statement":{"version":0.44,"file":"lib/DBD/File.pm"},"DBD::DBM::Statement":{"version":0.08,"file":"lib/DBD/DBM.pm"},"DBI":{"file":"DBI.pm","version":1.643},"DBD::DBM::Table":{"file":"lib/DBD/DBM.pm","version":0.08},"DBD::Proxy::RPC::PlClient":{"file":"lib/DBD/Proxy.pm","version":0.2004},"DBI::Gofer::Serializer::Storable":{"version":0.015586,"file":"lib/DBI/Gofer/Serializer/Storable.pm"},"DBI::DBD::SqlEngine::TieMeta":{"file":"lib/DBI/DBD/SqlEngine.pm","version":0.06},"DBI::Gofer::Request":{"file":"lib/DBI/Gofer/Request.pm","version":0.012537},"DBI::Gofer::Transport::stream":{"version":0.012537,"file":"lib/DBI/Gofer/Transport/stream.pm"},"DBI::ProfileDumper::Apache":{"version":2.014121,"file":"lib/DBI/ProfileDumper/Apache.pm"},"DBD::File::db":{"version":0.44,"file":"lib/DBD/File.pm"},"DBI::DBD::SqlEngine":{"version":0.06,"file":"lib/DBI/DBD/SqlEngine.pm"},"DBI::Const::GetInfoType":{"file":"lib/DBI/Const/GetInfoType.pm","version":2.008697},"DBI::DBD::SqlEngine::dr":{"file":"lib/DBI/DBD/SqlEngine.pm","version":0.06},"DBD::Mem::st":{"version":0.001,"file":"lib/DBD/Mem.pm"},"DBD::Mem::Statement":{"version":0.001,"file":"lib/DBD/Mem.pm"},"DBI::DBD::SqlEngine::Statement":{"version":0.06,"file":"lib/DBI/DBD/SqlEngine.pm"},"DBD::Proxy::dr":{"version":0.2004,"file":"lib/DBD/Proxy.pm"},"DBD::Gofer::dr":{"version":0.015327,"file":"lib/DBD/Gofer.pm"},"DBI::Util::_accessor":{"file":"lib/DBI/Util/_accessor.pm","version":0.009479},"DBD::Gofer::Transport::stream":{"file":"lib/DBD/Gofer/Transport/stream.pm","version":0.014599},"DBD::Gofer::Policy::rush":{"version":0.010088,"file":"lib/DBD/Gofer/Policy/rush.pm"},"DBD::DBM::dr":{"file":"lib/DBD/DBM.pm","version":0.08},"DBI::Gofer::Serializer::Base":{"version":"0.009950","file":"lib/DBI/Gofer/Serializer/Base.pm"},"DBI::DBD::SqlEngine::st":{"file":"lib/DBI/DBD/SqlEngine.pm","version":0.06},"DBD::ExampleP::db":{"file":"lib/DBD/ExampleP.pm","version":12.014311},"DBD::Gofer::Policy::Base":{"file":"lib/DBD/Gofer/Policy/Base.pm","version":0.010088},"DBD::Sponge::dr":{"file":"lib/DBD/Sponge.pm","version":12.010003},"DBI::Gofer::Response":{"version":0.011566,"file":"lib/DBI/Gofer/Response.pm"},"DBD::Gofer::st":{"file":"lib/DBD/Gofer.pm","version":0.015327},"DBD::File":{"file":"lib/DBD/File.pm","version":0.44},"DBD::Proxy":{"version":0.2004,"file":"lib/DBD/Proxy.pm"},"DBDI":{"version":12.015129,"file":"lib/DBI/DBD.pm"},"DBD::ExampleP::dr":{"file":"lib/DBD/ExampleP.pm","version":12.014311},"DBI::ProxyServer":{"version":0.3005,"file":"lib/DBI/ProxyServer.pm"},"DBD::File::st":{"file":"lib/DBD/File.pm","version":0.44},"DBI::Gofer::Execute":{"file":"lib/DBI/Gofer/Execute.pm","version":0.014283},"DBD::ExampleP::st":{"version":12.014311,"file":"lib/DBD/ExampleP.pm"},"DBD::NullP::dr":{"file":"lib/DBD/NullP.pm","version":12.014715},"DBI::Const::GetInfoReturn":{"version":2.008697,"file":"lib/DBI/Const/GetInfoReturn.pm"},"DBD::Mem::dr":{"file":"lib/DBD/Mem.pm","version":0.001},"DBD::NullP::db":{"version":12.014715,"file":"lib/DBD/NullP.pm"},"DBD::Mem::DataSource":{"version":0.001,"file":"lib/DBD/Mem.pm"},"DBI::DBD::SqlEngine::TieTables":{"version":0.06,"file":"lib/DBI/DBD/SqlEngine.pm"},"DBI::Gofer::Serializer::DataDumper":{"file":"lib/DBI/Gofer/Serializer/DataDumper.pm","version":"0.009950"},"DBD::Sponge":{"file":"lib/DBD/Sponge.pm","version":12.010003},"DBI::common":{"version":1.643,"file":"DBI.pm"},"DBD::NullP":{"version":12.014715,"file":"lib/DBD/NullP.pm"},"DBI::DBD::SqlEngine::TableSource":{"file":"lib/DBI/DBD/SqlEngine.pm","version":0.06},"DBI::SQL::Nano::Statement_":{"version":1.015544,"file":"lib/DBI/SQL/Nano.pm"},"DBI::DBD::SqlEngine::DataSource":{"version":0.06,"file":"lib/DBI/DBD/SqlEngine.pm"},"DBD::ExampleP":{"file":"lib/DBD/ExampleP.pm","version":12.014311},"DBD::File::Table":{"version":0.44,"file":"lib/DBD/File.pm"},"DBI::DBD::SqlEngine::Table":{"file":"lib/DBI/DBD/SqlEngine.pm","version":0.06},"DBD::Mem::Table":{"version":0.001,"file":"lib/DBD/Mem.pm"},"DBD::Mem::db":{"version":0.001,"file":"lib/DBD/Mem.pm"},"Bundle::DBI":{"version":12.008696,"file":"lib/Bundle/DBI.pm"},"DBD::Proxy::db":{"version":0.2004,"file":"lib/DBD/Proxy.pm"},"DBD::Gofer::db":{"version":0.015327,"file":"lib/DBD/Gofer.pm"},"DBD::Gofer::Transport::pipeone":{"version":0.010088,"file":"lib/DBD/Gofer/Transport/pipeone.pm"},"DBD::Gofer::Transport::corostream":{"file":"lib/DBD/Gofer/Transport/corostream.pm"},"DBD::DBM::db":{"version":0.08,"file":"lib/DBD/DBM.pm"},"DBD::Gofer::Transport::Base":{"file":"lib/DBD/Gofer/Transport/Base.pm","version":0.014121},"DBD::NullP::st":{"version":12.014715,"file":"lib/DBD/NullP.pm"}},"version":1.643}perl5/x86_64-linux-thread-multi/.meta/JSON-XS-4.03/MYMETA.json000044400000001757152462503210016651 0ustar00{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150001, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "JSON-XS", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "Canary::Stability" : "0", "ExtUtils::MakeMaker" : "6.52" } }, "runtime" : { "requires" : { "Types::Serialiser" : "0", "common::sense" : "0" } } }, "release_status" : "stable", "version" : "4.03", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/JSON-XS-4.03/install.json000044400000000263152462503210017312 0ustar00{"name":"JSON::XS","target":"JSON::XS","provides":{"JSON::XS":{"version":4.03,"file":"XS.pm"}},"pathname":"M/ML/MLEHMANN/JSON-XS-4.03.tar.gz","dist":"JSON-XS-4.03","version":4.03}perl5/x86_64-linux-thread-multi/.meta/Types-Serialiser-1.01/MYMETA.json000044400000001647152462503210020745 0ustar00{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150001, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Types-Serialiser", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "common::sense" : "0" } } }, "release_status" : "stable", "version" : "1.01", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/Types-Serialiser-1.01/install.json000044400000000660152462503210021411 0ustar00{"target":"Types::Serialiser","name":"Types::Serialiser","provides":{"Types::Serialiser::Error":{"version":1.01,"file":"Serialiser.pm"},"Types::Serialiser":{"version":1.01,"file":"Serialiser.pm"},"Types::Serialiser::BooleanBase":{"file":"Serialiser.pm","version":1.01},"JSON::PP::Boolean":{"version":1.01,"file":"Serialiser.pm"}},"version":1.01,"pathname":"M/ML/MLEHMANN/Types-Serialiser-1.01.tar.gz","dist":"Types-Serialiser-1.01"}perl5/x86_64-linux-thread-multi/.meta/Log-LogLite-0.82/MYMETA.json000044400000001570152462503210017622 0ustar00{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Log-LogLite", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "IO::LockedFile" : "0.2" } } }, "release_status" : "stable", "version" : 0.82, "x_serialization_backend" : "JSON::PP version 4.06" } perl5/x86_64-linux-thread-multi/.meta/Log-LogLite-0.82/install.json000044400000000404152462503210020267 0ustar00{"dist":"Log-LogLite-0.82","pathname":"R/RA/RANI/Log-LogLite-0.82.tar.gz","name":"Log::LogLite","version":0.82,"provides":{"Log::NullLogLite":{"file":"NullLogLite.pm","version":0.82},"Log::LogLite":{"file":"LogLite.pm","version":0.82}},"target":"Log::LogLite"}perl5/x86_64-linux-thread-multi/.meta/Net-HTTP-6.21/MYMETA.json000044400000070626152462503210017056 0ustar00{ "abstract" : "Low-level HTTP connection (client)", "author" : [ "Gisle Aas " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Net-HTTP", "no_index" : { "directory" : [ "examples", "t", "xt" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" }, "suggests" : { "JSON::PP" : "2.27300" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::EOL" : "0", "Test::Mojibake" : "0", "Test::More" : "0.88", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Version" : "1" } }, "runtime" : { "requires" : { "Carp" : "0", "Compress::Raw::Zlib" : "0", "IO::Socket::INET" : "0", "IO::Uncompress::Gunzip" : "0", "URI" : "0", "base" : "0", "perl" : "5.006002", "strict" : "0", "warnings" : "0" }, "suggests" : { "IO::Socket" : "0", "IO::Socket::INET6" : "0", "IO::Socket::IP" : "0", "IO::Socket::SSL" : "2.012", "Symbol" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "Data::Dumper" : "0", "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "IO::Select" : "0", "Socket" : "0", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/libwww-perl/Net-HTTP/issues" }, "homepage" : "https://github.com/libwww-perl/Net-HTTP", "repository" : { "type" : "git", "url" : "https://github.com/libwww-perl/Net-HTTP.git", "web" : "https://github.com/libwww-perl/Net-HTTP" }, "x_IRC" : "irc://irc.perl.org/#lwp", "x_MailingList" : "mailto:libwww@perl.org" }, "version" : "6.21", "x_Dist_Zilla" : { "perl" : { "version" : "5.030002" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "MetaResources", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "runtime", "type" : "requires" } }, "name" : "Prereqs", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 0, "check_all_prereqs" : 0, "modules" : [ "Dist::Zilla::PluginBundle::Author::OALDERS" ], "phase" : "build", "run_under_travis" : 0, "skip" : [] } }, "name" : "@Author::OALDERS/stale modules, build", "version" : "0.057" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 1, "check_all_prereqs" : 1, "modules" : [], "phase" : "release", "run_under_travis" : 0, "skip" : [] } }, "name" : "@Author::OALDERS/stale modules, release", "version" : "0.057" }, { "class" : "Dist::Zilla::Plugin::OALDERS::TidyAll", "name" : "@Author::OALDERS/OALDERS::TidyAll", "version" : "0.000029" }, { "class" : "Dist::Zilla::Plugin::MakeMaker", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "4" } }, "name" : "@Author::OALDERS/MakeMaker", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::CPANFile", "name" : "@Author::OALDERS/CPANFile", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::ContributorsFile", "name" : "@Author::OALDERS/ContributorsFile", "version" : "0.3.0" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "@Author::OALDERS/MetaJSON", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "@Author::OALDERS/MetaYAML", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "@Author::OALDERS/Manifest", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaNoIndex", "name" : "@Author::OALDERS/MetaNoIndex", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "@Author::OALDERS/MetaConfig", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "@Author::OALDERS/MetaResources", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "@Author::OALDERS/License", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::InstallGuide", "config" : { "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "@Author::OALDERS/InstallGuide", "version" : "1.200013" }, { "class" : "Dist::Zilla::Plugin::ExecDir", "name" : "@Author::OALDERS/ExecDir", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "@Author::OALDERS/MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "@Author::OALDERS/PodSyntaxTests", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":InstallModules", ":TestFiles" ], "trailing_whitespace" : 1 } }, "name" : "@Author::OALDERS/Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "config" : { "Dist::Zilla::Plugin::Test::Portability" : { "options" : "" } }, "name" : "@Author::OALDERS/Test::Portability", "version" : "2.001000" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "@Author::OALDERS/TestRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "@Author::OALDERS/Test::ReportPrereqs", "version" : "0.028" }, { "class" : "Dist::Zilla::Plugin::Test::Version", "name" : "@Author::OALDERS/Test::Version", "version" : "1.09" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "4" } }, "name" : "@Author::OALDERS/RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::PodWeaver", "config" : { "Dist::Zilla::Plugin::PodWeaver" : { "finder" : [ ":InstallModules", ":ExecFiles" ], "plugins" : [ { "class" : "Pod::Weaver::Plugin::EnsurePod5", "name" : "@CorePrep/EnsurePod5", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::H1Nester", "name" : "@CorePrep/H1Nester", "version" : "4.015" }, { "class" : "Pod::Weaver::Plugin::SingleEncoding", "name" : "@Default/SingleEncoding", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Name", "name" : "@Default/Name", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Version", "name" : "@Default/Version", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Default/prelude", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "SYNOPSIS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "DESCRIPTION", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "OVERVIEW", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "ATTRIBUTES", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "METHODS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "FUNCTIONS", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Leftovers", "name" : "@Default/Leftovers", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Default/postlude", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Authors", "name" : "@Default/Authors", "version" : "4.015" }, { "class" : "Pod::Weaver::Section::Legal", "name" : "@Default/Legal", "version" : "4.015" } ] } }, "name" : "@Author::OALDERS/PodWeaver", "version" : "4.008" }, { "class" : "Dist::Zilla::Plugin::PruneCruft", "name" : "@Author::OALDERS/PruneCruft", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", "name" : "@Author::OALDERS/CopyFilesFromBuild", "version" : "0.170880" }, { "class" : "Dist::Zilla::Plugin::GithubMeta", "name" : "@Author::OALDERS/GithubMeta", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "Install", "LICENSE", "META.json", "Makefile.PL", "README.md", "cpanfile" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "@Author::OALDERS/Git::GatherDir", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Install" ], "match" : [] } }, "name" : "@Author::OALDERS/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "Install", "LICENSE", "META.json", "Makefile.PL", "README.md", "cpanfile", "dist.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.30.1", "repo_root" : "." } }, "name" : "@Author::OALDERS/Git::Check", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.30.1", "include_authors" : 0, "include_releaser" : 1, "order_by" : "name", "paths" : [] } }, "name" : "@Author::OALDERS/Git::Contributors", "version" : "0.036" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "@Author::OALDERS/ReadmeMdInBuild", "version" : "0.163250" }, { "class" : "Dist::Zilla::Plugin::ShareDir", "name" : "@Author::OALDERS/ShareDir", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::CheckIssues", "name" : "@Author::OALDERS/CheckIssues", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "@Author::OALDERS/ConfirmRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "@Author::OALDERS/UploadToCPAN", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::RewriteVersion::Transitional", "config" : { "Dist::Zilla::Plugin::RewriteVersion" : { "add_tarball_name" : 0, "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "skip_version_provider" : 0 }, "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {} }, "name" : "@Author::OALDERS/@Git::VersionManager/RewriteVersion::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Update", "name" : "@Author::OALDERS/@Git::VersionManager/MetaProvides::Update", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Changes" ], "match" : [] } }, "name" : "@Author::OALDERS/@Git::VersionManager/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "v%V%n%n%c", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "Install", "LICENSE", "META.json", "Makefile.PL", "README.md", "cpanfile", "dist.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.30.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::OALDERS/@Git::VersionManager/release snapshot", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v6.21", "tag_format" : "v%V", "tag_message" : "v%V" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.30.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::OALDERS/@Git::VersionManager/Git::Tag", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 }, "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {} }, "name" : "@Author::OALDERS/@Git::VersionManager/BumpVersionAfterRelease::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@Author::OALDERS/@Git::VersionManager/NextRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "increment $VERSION after %v release", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Build.PL", "Changes", "Makefile.PL" ], "allow_dirty_match" : [ "(?^:^lib/.*\\.pm$)" ], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.30.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::OALDERS/@Git::VersionManager/post-release commit", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.30.1", "repo_root" : "." } }, "name" : "@Author::OALDERS/Git::Push", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", "name" : "Test::Pod::Coverage::Configurable", "version" : "0.07" }, { "class" : "Dist::Zilla::Plugin::AutoPrereqs", "name" : "AutoPrereqs", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "runtime", "type" : "suggests" } }, "name" : "RuntimeSuggests", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Prereqs::Soften", "config" : { "Dist::Zilla::Plugin::Prereqs::Soften" : { "copy_to" : [], "modules" : [ "IO::Socket", "IO::Socket::INET6", "IO::Socket::IP", "IO::Socket::SSL", "Symbol" ], "modules_from_features" : null, "to_relationship" : "suggests" } }, "name" : "Prereqs::Soften", "version" : "0.006003" }, { "class" : "Dist::Zilla::Plugin::StaticInstall", "config" : { "Dist::Zilla::Plugin::StaticInstall" : { "dry_run" : 0, "mode" : "on" } }, "name" : "StaticInstall", "version" : "0.012" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.017" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.017" } }, "x_contributors" : [ "Adam Kennedy ", "Adam Sjogren ", "Alexey Tourbin ", "Alex Kapranoff ", "amire80 ", "Andreas J. Koenig ", "Andy Grundman ", "Bill Mann ", "Bron Gondwana ", "Chase Whitener ", "Dagfinn Ilmari Mannsåker ", "Daniel Hedlund ", "Dave Rolsky ", "David E. Wheeler ", "DAVIDRW ", "David Steinbrunner ", "Eric Wong ", "Father Chrysostomos ", "FWILES ", "Gavin Peters ", "Gisle Aas ", "Gisle Aas ", "Gisle Aas ", "Gisle Aas ", "Graeme Thompson ", "Hans-H. Froehlich ", "Ian Kilgore ", "Jacob J ", "James Raspass ", "Jason A Fesler ", "Jay Hannah ", "Jean-Louis Martineau ", "jefflee ", "Jesse Luehrs ", "john9art ", "Karen Etheridge ", "Kent Fredric ", "Lasse Makholm ", "Marinos Yannikos ", "Mark Overmeer ", "Mark Stosberg ", "Mark Stosberg ", "Mark Stosberg ", "Mike Schilli ", "Mohammad S Anwar ", "mschilli ", "murphy ", "Olaf Alders ", "Ondrej Hanak ", "Peter Rabbitson ", "phrstbrn ", "Robert Stone ", "Rolf Grossmann ", "ruff ", "sasao ", "Sean M. Burke ", "Shoichi Kaji ", "Slaven Rezic ", "Slaven Rezic ", "Spiros Denaxas ", "Steffen Ullrich ", "Steve Hay ", "Todd Lipcon ", "Tom Hukins ", "Tom Wyant ", "Tony Finch ", "Toru Yamaguchi ", "uid39246 ", "Ville Skyttä ", "Yuri Karaban ", "Zefram " ], "x_generated_by_perl" : "v5.30.2", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later", "x_static_install" : 1 } perl5/x86_64-linux-thread-multi/.meta/Net-HTTP-6.21/install.json000044400000000575152462503210017524 0ustar00{"version":6.21,"provides":{"Net::HTTP":{"file":"lib/Net/HTTP.pm","version":6.21},"Net::HTTP::NB":{"version":6.21,"file":"lib/Net/HTTP/NB.pm"},"Net::HTTP::Methods":{"version":6.21,"file":"lib/Net/HTTP/Methods.pm"},"Net::HTTPS":{"version":6.21,"file":"lib/Net/HTTPS.pm"}},"target":"Net::HTTP","dist":"Net-HTTP-6.21","name":"Net::HTTP","pathname":"O/OA/OALDERS/Net-HTTP-6.21.tar.gz"}perl5/x86_64-linux-thread-multi/.meta/YAML-Syck-1.34/MYMETA.json000044400000002345152462503210017214 0ustar00{ "abstract" : "Fast, lightweight YAML loader and dumper", "author" : [ "Todd Rinaldo " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "YAML-Syck", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Test::More" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "perl" : "5.006" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/toddr/YAML-Syck/issues" }, "homepage" : "http://github.com/toddr/YAML-Syck", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "http://github.com/toddr/YAML-Syck" } }, "version" : "1.34", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/YAML-Syck-1.34/install.json000044400000000555152462503210017667 0ustar00{"dist":"YAML-Syck-1.34","name":"YAML::Syck","target":"YAML::Syck","pathname":"T/TO/TODDR/YAML-Syck-1.34.tar.gz","provides":{"JSON::Syck":{"file":"lib/JSON/Syck.pm","version":1.34},"YAML::Loader::Syck":{"file":"lib/YAML/Loader/Syck.pm"},"YAML::Syck":{"file":"lib/YAML/Syck.pm","version":1.34},"YAML::Dumper::Syck":{"file":"lib/YAML/Dumper/Syck.pm"}},"version":1.34}perl5/x86_64-linux-thread-multi/.meta/Devel-CheckLib-1.14/MYMETA.json000044400000002506152462503210020241 0ustar00{ "abstract" : "check that a library is available", "author" : [ "David Cantrell", "David Golden", "Yasuhiro Matsumoto" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Devel-CheckLib", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Exporter" : "0", "File::Spec" : "0", "File::Temp" : "0.16", "perl" : "5.00405" } }, "test" : { "requires" : { "Capture::Tiny" : "0", "Mock::Config" : "0.02", "Test::More" : "0.88" } } }, "release_status" : "stable", "resources" : { "repository" : { "url" : "http://github.com/mattn/p5-Devel-CheckLib" } }, "version" : "1.14", "x_serialization_backend" : "JSON::PP version 4.06" } perl5/x86_64-linux-thread-multi/.meta/Devel-CheckLib-1.14/install.json000044400000000343152462503210020710 0ustar00{"provides":{"Devel::CheckLib":{"file":"lib/Devel/CheckLib.pm","version":1.14}},"version":1.14,"pathname":"M/MA/MATTN/Devel-CheckLib-1.14.tar.gz","dist":"Devel-CheckLib-1.14","target":"Devel::CheckLib","name":"Devel::CheckLib"}perl5/x86_64-linux-thread-multi/.meta/common-sense-3.75/MYMETA.json000044400000001477152462503210020162 0ustar00{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150001, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "common-sense", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } } }, "release_status" : "stable", "version" : 3.75, "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/common-sense-3.75/install.json000044400000000322152462503210020620 0ustar00{"version":3.75,"dist":"common-sense-3.75","pathname":"M/ML/MLEHMANN/common-sense-3.75.tar.gz","provides":{"common::sense":{"file":"sense.pm.PL","version":3.75}},"name":"common::sense","target":"common::sense"}perl5/x86_64-linux-thread-multi/.meta/Crypt-SSLeay-0.72/MYMETA.json000044400000003176152462503210020006 0ustar00{ "abstract" : "OpenSSL support for LWP", "author" : [ "A. Sinan Unur ", "David Landgren", "Joshua Chamas", "Gisle Aas" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 6.96, CPAN::Meta::Converter version 2.140640, CPAN::Meta::Converter version 2.150010", "keywords" : [ "lwp", "lwp-useragent", "openssl", "https" ], "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Crypt-SSLeay", "no_index" : { "directory" : [ "t", "inc", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::CBuilder" : "0.280205", "Getopt::Long" : "0", "Path::Class" : "0.26", "Try::Tiny" : "0.19" } }, "runtime" : { "requires" : { "LWP::Protocol::https" : "6.02", "MIME::Base64" : "0", "perl" : "5.006" } }, "test" : { "requires" : { "Test::More" : "0.19", "Try::Tiny" : "0.19" } } }, "release_status" : "stable", "resources" : { "repository" : { "url" : "https://github.com/nanis/Crypt-SSLeay" } }, "version" : "0.72", "x_build" : { "recommends" : { "Devel::CheckLib" : "0.99" } }, "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/Crypt-SSLeay-0.72/install.json000044400000001155152462503210020453 0ustar00{"name":"Crypt::SSLeay","pathname":"N/NA/NANIS/Crypt-SSLeay-0.72.tar.gz","dist":"Crypt-SSLeay-0.72","provides":{"Crypt::SSLeay::Version":{"file":"lib/Crypt/SSLeay/Version.pm"},"Crypt::SSLeay::CTX":{"file":"lib/Crypt/SSLeay/CTX.pm"},"Crypt::SSLeay::MainContext":{"file":"lib/Crypt/SSLeay/MainContext.pm"},"Crypt::SSLeay::X509":{"file":"lib/Crypt/SSLeay/X509.pm"},"Net::SSL":{"version":2.86,"file":"lib/Net/SSL.pm"},"Crypt::SSLeay::Conn":{"file":"lib/Crypt/SSLeay/Conn.pm"},"Crypt::SSLeay::Err":{"file":"lib/Crypt/SSLeay/Err.pm"},"Crypt::SSLeay":{"file":"SSLeay.pm","version":0.72}},"target":"Crypt::SSLeay","version":0.72}perl5/x86_64-linux-thread-multi/.meta/libwww-perl-6.58/MYMETA.json000044400000103202152462503210020023 0ustar00{ "abstract" : "The World-Wide Web library for Perl", "author" : [ "Gisle Aas " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "libwww-perl", "no_index" : { "directory" : [ "t", "xt" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "CPAN::Meta::Requirements" : "2.120620", "ExtUtils::MakeMaker" : "0", "File::Copy" : "0", "Getopt::Long" : "0", "Module::Metadata" : "0" } }, "develop" : { "recommends" : { "Dist::Zilla::PluginBundle::Git::VersionManager" : "0.007" }, "requires" : { "Authen::NTLM" : "1.02", "File::Spec" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Pod::Coverage::TrustPod" : "0", "Test::EOL" : "2.00", "Test::LeakTrace" : "0.16", "Test::MinimumVersion" : "0", "Test::Mojibake" : "0", "Test::More" : "0.94", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12", "Test::Version" : "1" } }, "runtime" : { "requires" : { "Digest::MD5" : "0", "Encode" : "2.12", "Encode::Locale" : "0", "File::Listing" : "6", "HTML::Entities" : "0", "HTML::HeadParser" : "0", "HTTP::Cookies" : "6", "HTTP::Date" : "6", "HTTP::Negotiate" : "6", "HTTP::Request" : "6", "HTTP::Request::Common" : "6", "HTTP::Response" : "6", "HTTP::Status" : "6.18", "IO::Select" : "0", "IO::Socket" : "0", "LWP::MediaTypes" : "6", "MIME::Base64" : "2.1", "Net::FTP" : "2.58", "Net::HTTP" : "6.18", "Scalar::Util" : "0", "Try::Tiny" : "0", "URI" : "1.10", "URI::Escape" : "0", "WWW::RobotRules" : "6", "parent" : "0.217", "perl" : "5.008001", "strict" : "0", "warnings" : "0" }, "suggests" : { "Authen::NTLM" : "1.02", "Data::Dump" : "1.13", "IO::Socket::INET" : "0", "LWP::Protocol::https" : "6.02" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900", "Test::LeakTrace" : "0" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "FindBin" : "0", "HTTP::Daemon" : "6.12", "Test::Fatal" : "0", "Test::More" : "0.96", "Test::Needs" : "0", "Test::RequiresInternet" : "0" } } }, "provides" : { "LWP" : { "file" : "lib/LWP.pm", "version" : "6.58" }, "LWP::Authen::Basic" : { "file" : "lib/LWP/Authen/Basic.pm", "version" : "6.58" }, "LWP::Authen::Digest" : { "file" : "lib/LWP/Authen/Digest.pm", "version" : "6.58" }, "LWP::Authen::Ntlm" : { "file" : "lib/LWP/Authen/Ntlm.pm", "version" : "6.58" }, "LWP::ConnCache" : { "file" : "lib/LWP/ConnCache.pm", "version" : "6.58" }, "LWP::Debug" : { "file" : "lib/LWP/Debug.pm", "version" : "6.58", "x_deprecated" : 1 }, "LWP::Debug::TraceHTTP" : { "file" : "lib/LWP/Debug/TraceHTTP.pm", "version" : "6.58" }, "LWP::DebugFile" : { "file" : "lib/LWP/DebugFile.pm", "version" : "6.58" }, "LWP::MemberMixin" : { "file" : "lib/LWP/MemberMixin.pm", "version" : "6.58" }, "LWP::Protocol" : { "file" : "lib/LWP/Protocol.pm", "version" : "6.58" }, "LWP::Protocol::cpan" : { "file" : "lib/LWP/Protocol/cpan.pm", "version" : "6.58" }, "LWP::Protocol::data" : { "file" : "lib/LWP/Protocol/data.pm", "version" : "6.58" }, "LWP::Protocol::file" : { "file" : "lib/LWP/Protocol/file.pm", "version" : "6.58" }, "LWP::Protocol::ftp" : { "file" : "lib/LWP/Protocol/ftp.pm", "version" : "6.58" }, "LWP::Protocol::gopher" : { "file" : "lib/LWP/Protocol/gopher.pm", "version" : "6.58" }, "LWP::Protocol::http" : { "file" : "lib/LWP/Protocol/http.pm", "version" : "6.58" }, "LWP::Protocol::loopback" : { "file" : "lib/LWP/Protocol/loopback.pm", "version" : "6.58" }, "LWP::Protocol::mailto" : { "file" : "lib/LWP/Protocol/mailto.pm", "version" : "6.58" }, "LWP::Protocol::nntp" : { "file" : "lib/LWP/Protocol/nntp.pm", "version" : "6.58" }, "LWP::Protocol::nogo" : { "file" : "lib/LWP/Protocol/nogo.pm", "version" : "6.58" }, "LWP::RobotUA" : { "file" : "lib/LWP/RobotUA.pm", "version" : "6.58" }, "LWP::Simple" : { "file" : "lib/LWP/Simple.pm", "version" : "6.58" }, "LWP::UserAgent" : { "file" : "lib/LWP/UserAgent.pm", "version" : "6.58" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/libwww-perl/libwww-perl/issues" }, "homepage" : "https://github.com/libwww-perl/libwww-perl", "repository" : { "type" : "git", "url" : "https://github.com/libwww-perl/libwww-perl.git", "web" : "https://github.com/libwww-perl/libwww-perl" }, "x_IRC" : "irc://irc.perl.org/#lwp", "x_MailingList" : "mailto:libwww@perl.org" }, "version" : "6.58", "x_Dist_Zilla" : { "perl" : { "version" : "5.026001" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "LICENSE", "META.json", "README.md" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "Git::GatherDir", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "MetaConfig", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Package", "config" : { "Dist::Zilla::Plugin::MetaProvides::Package" : { "finder_objects" : [ { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.024" } ], "include_underscores" : 0 }, "Dist::Zilla::Role::MetaProvider::Provider" : { "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004", "inherit_missing" : 1, "inherit_version" : 1, "meta_noindex" : 1 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.004" } }, "name" : "MetaProvides::Package", "version" : "2.004003" }, { "class" : "Dist::Zilla::Plugin::MetaNoIndex", "name" : "MetaNoIndex", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "MetaYAML", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "MetaJSON", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "MetaResources", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Deprecated", "config" : { "Dist::Zilla::Plugin::Deprecated" : { "all" : 0, "modules" : [ "LWP::Debug" ] } }, "name" : "Deprecated", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.33.1", "include_authors" : 0, "include_releaser" : 1, "order_by" : "name", "paths" : [] } }, "name" : "Git::Contributors", "version" : "0.036" }, { "class" : "Dist::Zilla::Plugin::GithubMeta", "name" : "GithubMeta", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "Manifest", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "License", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::InstallGuide", "config" : { "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.004" } }, "name" : "InstallGuide", "version" : "1.200014" }, { "class" : "Dist::Zilla::Plugin::ExecDir", "name" : "ExecDir", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Prereqs::FromCPANfile", "name" : "Prereqs::FromCPANfile", "version" : "0.08" }, { "class" : "Dist::Zilla::Plugin::DynamicPrereqs", "config" : { "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.004" } }, "name" : "DynamicPrereqs", "version" : "0.039" }, { "class" : "Dist::Zilla::Plugin::MakeMaker::Awesome", "config" : { "Dist::Zilla::Plugin::MakeMaker" : { "make_path" : "make", "version" : "6.024" }, "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "1", "version" : "6.024" } }, "name" : "MakeMaker::Awesome", "version" : "0.49" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::Test::Version", "name" : "Test::Version", "version" : "1.09" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "Test::ReportPrereqs", "version" : "0.028" }, { "class" : "Dist::Zilla::Plugin::Test::Compile", "config" : { "Dist::Zilla::Plugin::Test::Compile" : { "bail_out_on_fail" : "1", "fail_on_warning" : "author", "fake_home" : 0, "filename" : "xt/author/00-compile.t", "module_finder" : [ ":InstallModules" ], "needs_display" : 0, "phase" : "develop", "script_finder" : [ ":PerlExecFiles" ], "skips" : [], "switch" : [] } }, "name" : "Test::Compile", "version" : "2.058" }, { "class" : "Dist::Zilla::Plugin::Substitute", "name" : "00-compile.t", "version" : "0.006" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "config" : { "Dist::Zilla::Plugin::Test::Portability" : { "options" : "" } }, "name" : "Test::Portability", "version" : "2.001000" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":InstallModules", ":TestFiles" ], "trailing_whitespace" : 1 } }, "name" : "Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::Test::ChangesHasContent", "name" : "Test::ChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::Substitute", "name" : "changes_has_content.t", "version" : "0.006" }, { "class" : "Dist::Zilla::Plugin::Test::MinimumVersion", "config" : { "Dist::Zilla::Plugin::Test::MinimumVersion" : { "max_target_perl" : null } }, "name" : "Test::MinimumVersion", "version" : "2.000010" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "PodSyntaxTests", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", "name" : "Test::Pod::Coverage::Configurable", "version" : "0.07" }, { "class" : "Dist::Zilla::Plugin::Test::PodSpelling", "config" : { "Dist::Zilla::Plugin::Test::PodSpelling" : { "directories" : [ "bin", "lib" ], "spell_cmd" : "aspell list", "stopwords" : [ "Accomazzi", "Alexandre", "Andreas", "Asplund", "Betts", "Bochner", "BooK", "Buenzli", "CGI", "CPAN", "Chamas", "Coppit", "Dalgleish", "Dubois", "Dunkin", "Duret", "Dvornik", "Eldridge", "Gertjan", "Graaff", "Greab", "Guenther", "Gurusamy", "Gustafsson", "Hakanson", "Harald", "Hedlund", "Hoblitt", "Hwa", "INOUE", "Joao", "Joerg", "KONISHI", "Kaminsky", "Kartik", "Katsuhiro", "Kebsch", "Keiichiro", "Kilzer", "Klar", "Koster", "Kronengold", "Krüger", "Kubb", "König", "Laker", "Langfeldt", "Langheinrich", "Liam", "Lindley", "Lotterer", "Lutz", "MacEachern", "Macdonald", "Mailto", "Marko", "Markus", "Martijn", "McCauley", "Melchner", "Moshe", "Murrell", "NNTP", "NTLM", "Nagano", "Newby", "Nicolai", "Nierstrasz", "Olly", "Oosten", "Panchenko", "Pimlott", "Pon", "Quaranta", "Radoslaw", "Radu", "Rai", "Rezic", "RobotUA", "Sarathy", "Schilli", "Schinder", "Shirazi", "Skyttä", "Slaven", "Spafford", "Stosberg", "Subbarao", "TCP", "Takanori", "Thoennes", "Thurn", "Tilly", "UA", "Ugai", "Unger", "UserAgent", "VanHeyningen", "Vandewege", "Ville", "WireShark", "Yee", "Yitzchak", "Yoshinari", "Zajac", "Zakharevich", "Zielinski", "Zoest", "afPuUsSedvhx", "de", "erik", "getprint", "getstore", "peterm", "shildreth" ], "wordlist" : "Pod::Wordlist" } }, "name" : "Test::PodSpelling", "version" : "2.007005" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.33.1", "repo_root" : "." } }, "name" : "Git::Check", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::CheckStrictVersion", "name" : "CheckStrictVersion", "version" : "0.001" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "1" } }, "name" : "RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::CheckChangeLog", "name" : "CheckChangeLog", "version" : "0.05" }, { "class" : "Dist::Zilla::Plugin::CheckChangesHasContent", "name" : "CheckChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "TestRelease", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "UploadToCPAN", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "Markdown_Readme", "version" : "0.163250" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "LICENSE", "META.json" ], "match" : [] } }, "name" : "CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "recommends" } }, "name" : "@Git::VersionManager/pluginbundle version", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::RewriteVersion::Transitional", "config" : { "Dist::Zilla::Plugin::RewriteVersion" : { "add_tarball_name" : 0, "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "skip_version_provider" : 0 }, "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {} }, "name" : "@Git::VersionManager/RewriteVersion::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Update", "name" : "@Git::VersionManager/MetaProvides::Update", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Changes" ], "match" : [] } }, "name" : "@Git::VersionManager/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "v%V%n%n%c", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "LICENSE", "META.json", "README.md" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.33.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/release snapshot", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v6.58", "tag_format" : "v%V", "tag_message" : "v%V" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.33.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/Git::Tag", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 }, "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {} }, "name" : "@Git::VersionManager/BumpVersionAfterRelease::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@Git::VersionManager/NextRelease", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "increment $VERSION after %v release", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Build.PL", "Changes", "Makefile.PL" ], "allow_dirty_match" : [ "(?^:^lib/.*\\.pm$)" ], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.33.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/post-release commit", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.33.1", "repo_root" : "." } }, "name" : "Git::Push", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "ConfirmRelease", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.024" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.024" } }, "x_contributors" : [ "Adam Kennedy ", "Adam Sjogren ", "Alexey Tourbin ", "Alex Kapranoff ", "amire80 ", "Andreas J. Koenig ", "Andrew Grangaard ", "Anirvan Chatterjee ", "Arne Johannessen ", "BGMNT ", "Bill Mann ", "Bron Gondwana ", "Bryan Cardillo ", "Chase Whitener ", "Christopher J. Madsen ", "Colin Newell ", "Daina Pettit ", "Daniel Hedlund ", "David E. Wheeler ", "DAVIDRW ", "David Standish ", "David Steinbrunner ", "Desmond Daignault ", "Doug Bell ", "Fabian Zeindler ", "Father Chrysostomos ", "Frank Maas ", "FWILES ", "Galen Huntington ", "Gavin Peters ", "Gerhard Poul ", "Gianni Ceccarelli ", "Gisle Aas ", "Graeme Thompson ", "Graham Knop ", "Gregory Oschwald ", "Hans-H. Froehlich ", "Ian Kilgore ", "Jacob J ", "Jakub Wilk ", "James Raspass ", "Jason A Fesler ", "jefflee ", "Jeremy Mates ", "Joe Atzberger ", "john9art ", "John Wittkoski ", "Jonathan Dahan ", "Karen Etheridge ", "Katarina Durechova ", "leedo ", "Mark Fowler ", "Mark Stosberg ", "Martin H. Sluka ", "Matthew Horsfall ", "Max Maischein ", "michael gong ", "Michael G. Schwern ", "Michiel Beijen ", "Mike Schilli ", "Moritz Onken ", "murphy ", "Naveed Massjouni ", "Nigel Gregoire ", "Nik LaBelle ", "Niko Tyni ", "Olaf Alders ", "Ondrej Hanak ", "Patrik Lundin ", "Peter Rabbitson ", "phrstbrn ", "Piotr Roszatycki ", "Robert Stone ", "Rolf Grossmann ", "Roman Galeev ", "ruff ", "sasao ", "Sean M. Burke ", "Sebastian Paaske Tørholm ", "Sergey Romanov ", "Shoichi Kaji ", "simbabque ", "Slaven Rezic ", "Slaven Rezic ", "Spiros Denaxas ", "Steffen Ullrich ", "Steve Hay ", "Takumi Akiyama ", "Theodore Robert Campbell Jr ", "Theo van Hoesel ", "Tim Couzins ", "Todd Lipcon ", "Tomasz Konojacki ", "Tom Hukins ", "Tony Finch ", "Toru Yamaguchi ", "turugina ", "uid39246 ", "Ville Skyttä ", "Vyacheslav Matyukhin ", "Yuri Karaban ", "Yury Zavarin ", "Yves Orton ", "Zefram " ], "x_generated_by_perl" : "v5.26.1", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } perl5/x86_64-linux-thread-multi/.meta/libwww-perl-6.58/install.json000044400000003377152462503210020511 0ustar00{"provides":{"LWP::Protocol::loopback":{"file":"lib/LWP/Protocol/loopback.pm","version":"6.58"},"LWP::Protocol::gopher":{"file":"lib/LWP/Protocol/gopher.pm","version":"6.58"},"LWP::Protocol::mailto":{"file":"lib/LWP/Protocol/mailto.pm","version":"6.58"},"LWP::Protocol::ftp":{"file":"lib/LWP/Protocol/ftp.pm","version":"6.58"},"LWP::Protocol::nogo":{"version":"6.58","file":"lib/LWP/Protocol/nogo.pm"},"LWP::Authen::Digest":{"version":"6.58","file":"lib/LWP/Authen/Digest.pm"},"LWP::Protocol::file":{"file":"lib/LWP/Protocol/file.pm","version":"6.58"},"LWP::Simple":{"version":"6.58","file":"lib/LWP/Simple.pm"},"LWP::MemberMixin":{"file":"lib/LWP/MemberMixin.pm","version":"6.58"},"LWP::Protocol::cpan":{"file":"lib/LWP/Protocol/cpan.pm","version":"6.58"},"LWP::Debug":{"file":"lib/LWP/Debug.pm","version":"6.58","x_deprecated":1},"LWP::ConnCache":{"version":"6.58","file":"lib/LWP/ConnCache.pm"},"LWP::Authen::Ntlm":{"file":"lib/LWP/Authen/Ntlm.pm","version":"6.58"},"LWP::DebugFile":{"version":"6.58","file":"lib/LWP/DebugFile.pm"},"LWP::Protocol::nntp":{"file":"lib/LWP/Protocol/nntp.pm","version":"6.58"},"LWP::Protocol::http":{"version":"6.58","file":"lib/LWP/Protocol/http.pm"},"LWP::Protocol":{"version":"6.58","file":"lib/LWP/Protocol.pm"},"LWP::UserAgent":{"version":"6.58","file":"lib/LWP/UserAgent.pm"},"LWP::RobotUA":{"file":"lib/LWP/RobotUA.pm","version":"6.58"},"LWP::Protocol::data":{"version":"6.58","file":"lib/LWP/Protocol/data.pm"},"LWP::Authen::Basic":{"version":"6.58","file":"lib/LWP/Authen/Basic.pm"},"LWP":{"file":"lib/LWP.pm","version":"6.58"},"LWP::Debug::TraceHTTP":{"file":"lib/LWP/Debug/TraceHTTP.pm","version":"6.58"}},"target":"LWP::UserAgent","version":"6.58","pathname":"O/OA/OALDERS/libwww-perl-6.58.tar.gz","name":"libwww::perl","dist":"libwww-perl-6.58"}perl5/x86_64-linux-thread-multi/.meta/Expect-1.35/MYMETA.json000044400000003066152462503210016775 0ustar00{ "abstract" : "automate interactions with command line programs that expose a text terminal interface.", "author" : [ "Austin Schutz ", "Roland Giersig ", "Dave Jacoby " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Expect", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : {} }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.64" } }, "runtime" : { "requires" : { "Carp" : "0", "Errno" : "0", "Exporter" : "0", "Fcntl" : "0", "IO::Handle" : "0", "IO::Pty" : "1.11", "IO::Tty" : "1.11", "POSIX" : "0", "perl" : "5.006000" } }, "test" : { "requires" : { "File::Temp" : "0", "Test::More" : "1.00" } } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "http://github.com/jacoby/expect.pm.git", "web" : "http://github.com/jacoby/expect.pm" } }, "version" : "1.35", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/Expect-1.35/install.json000044400000000261152462503210017441 0ustar00{"target":"Expect","pathname":"J/JA/JACOBY/Expect-1.35.tar.gz","provides":{"Expect":{"file":"lib/Expect.pm","version":1.35}},"version":1.35,"dist":"Expect-1.35","name":"Expect"}perl5/x86_64-linux-thread-multi/.meta/IO-Tty-1.16/MYMETA.json000044400000002101152462503210016616 0ustar00{ "abstract" : "Pseudo ttys and constants", "author" : [ "Roland Giersig " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "IO-Tty", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Test::More" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/toddr/IO-Tty/issues" }, "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "https://github.com/toddr/IO-Tty" } }, "version" : "1.16", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/IO-Tty-1.16/install.json000044400000000425152462503210017277 0ustar00{"dist":"IO-Tty-1.16","name":"IO::Tty","target":"IO::Pty","pathname":"T/TO/TODDR/IO-Tty-1.16.tar.gz","provides":{"IO::Pty":{"file":"Pty.pm","version":1.16},"IO::Tty":{"version":1.16,"file":"Tty.pm"},"IO::Tty::Constant":{"version":1.16,"file":"Tty/Constant.pm"}},"version":1.16}perl5/x86_64-linux-thread-multi/.meta/JSON-4.03/MYMETA.json000044400000002317152462503210016312 0ustar00{ "abstract" : "JSON (JavaScript Object Notation) encoder/decoder", "author" : [ "Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "JSON", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "recommends" : { "JSON::XS" : "2.34" }, "requires" : { "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/makamaka/JSON/issues" }, "repository" : { "url" : "https://github.com/makamaka/JSON" } }, "version" : "4.03", "x_serialization_backend" : "JSON version 4.03" } perl5/x86_64-linux-thread-multi/.meta/JSON-4.03/install.json000044400000000341152462503210016757 0ustar00{"provides":{"JSON::Backend::PP":{"version":4.03,"file":"lib/JSON.pm"},"JSON":{"file":"lib/JSON.pm","version":4.03}},"target":"JSON","version":4.03,"pathname":"I/IS/ISHIGAKI/JSON-4.03.tar.gz","name":"JSON","dist":"JSON-4.03"}perl5/x86_64-linux-thread-multi/.meta/CPAN-2.28/MYMETA.json000044400000004707152462503210016274 0ustar00{ "abstract" : "query, download and build perl modules from CPAN sites", "author" : [ "Andreas Koenig " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "keywords" : [ "CPAN", "module", "module installation" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "CPAN", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Archive::Tar" : "0", "Archive::Zip" : "0", "CPAN::Meta" : "0", "CPAN::Meta::Requirements" : "2.121", "CPAN::Meta::YAML" : "0", "Compress::Bzip2" : "0", "Compress::Zlib" : "0", "Data::Dumper" : "0", "Digest::MD5" : "0", "Digest::SHA" : "0", "Exporter" : "0", "Exporter::Heavy" : "0", "ExtUtils::CBuilder" : "0", "File::Copy" : "0", "File::HomeDir" : "0", "File::Spec" : "0", "File::Temp" : "0", "File::Which" : "0", "HTTP::Tiny" : "0", "IO::Compress::Base" : "0", "IO::Zlib" : "0", "JSON::PP" : "0", "LWP::UserAgent" : "0", "MIME::Base64" : "0", "Module::Build" : "0", "Net::FTP" : "0", "Net::Ping" : "0", "Parse::CPAN::Meta" : "0", "Pod::Perldoc" : "0", "Pod::Perldoc::ToMan" : "0", "Scalar::Util" : "0", "Socket" : "0", "Term::ReadKey" : "0", "Test::Harness" : "2.62", "Test::More" : "0", "Text::Glob" : "0", "Text::ParseWords" : "0", "Text::Wrap" : "0", "perl" : "5.006002" } } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "https://github.com/andk/cpanpm" } }, "version" : "2.28", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/CPAN-2.28/install.json000044400000006750152462503210016746 0ustar00{"target":"CPAN","pathname":"A/AN/ANDK/CPAN-2.28.tar.gz","provides":{"CPAN::Distribution":{"file":"lib/CPAN/Distribution.pm","version":2.27},"CPAN::URL":{"version":5.5,"file":"lib/CPAN/URL.pm"},"CPAN::Version":{"version":5.5003,"file":"lib/CPAN/Version.pm"},"CPAN::Distroprefs::Iterator":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::HTTP::Credentials":{"file":"lib/CPAN/HTTP/Credentials.pm","version":1.9601},"CPAN::Exception::yaml_not_installed":{"version":5.5,"file":"lib/CPAN/Exception/yaml_not_installed.pm"},"CPAN::Shell":{"version":5.5009,"file":"lib/CPAN/Shell.pm"},"CPAN::Bundle":{"version":5.5005,"file":"lib/CPAN/Bundle.pm"},"CPAN::Queue":{"version":5.5003,"file":"lib/CPAN/Queue.pm"},"CPAN::Eval":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::FTP::netrc":{"version":1.01,"file":"lib/CPAN/FTP/netrc.pm"},"CPAN::Distroprefs::Result":{"version":6.0001,"file":"lib/CPAN/Distroprefs.pm"},"CPAN::Distrostatus":{"file":"lib/CPAN/Distrostatus.pm","version":5.5},"CPAN::Kwalify":{"file":"lib/CPAN/Kwalify.pm","version":"5.50"},"CPAN::Exception::RecursiveDependency":{"file":"lib/CPAN/Exception/RecursiveDependency.pm","version":5.5001},"CPAN::Plugin":{"file":"lib/CPAN/Plugin.pm","version":0.97},"CPAN::Distroprefs::Result::Success":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Prompt":{"file":"lib/CPAN/Prompt.pm","version":5.5},"CPAN::Distroprefs::Result::Error":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Distroprefs::Result::Warning":{"version":6.0001,"file":"lib/CPAN/Distroprefs.pm"},"CPAN::Complete":{"file":"lib/CPAN/Complete.pm","version":5.5001},"CPAN::Exception::yaml_process_error":{"file":"lib/CPAN/Exception/yaml_process_error.pm","version":5.5},"CPAN::FirstTime":{"version":5.5315,"file":"lib/CPAN/FirstTime.pm"},"CPAN::Distroprefs::Result::Fatal":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Nox":{"version":5.5001,"file":"lib/CPAN/Nox.pm"},"CPAN::Debug":{"version":5.5001,"file":"lib/CPAN/Debug.pm"},"CPAN::Mirrors":{"version":2.27,"file":"lib/CPAN/Mirrors.pm"},"CPAN::Index":{"file":"lib/CPAN/Index.pm","version":2.12},"CPAN::LWP::UserAgent":{"file":"lib/CPAN/LWP/UserAgent.pm","version":1.9601},"CPAN::Module":{"file":"lib/CPAN/Module.pm","version":5.5003},"CPAN::Plugin::Specfile":{"version":0.02,"file":"lib/CPAN/Plugin/Specfile.pm"},"CPAN::Queue::Item":{"version":5.5003,"file":"lib/CPAN/Queue.pm"},"CPAN::Distroprefs":{"version":6.0001,"file":"lib/CPAN/Distroprefs.pm"},"CPAN::HTTP::Client":{"file":"lib/CPAN/HTTP/Client.pm","version":1.9601},"CPAN::Author":{"file":"lib/CPAN/Author.pm","version":5.5002},"CPAN::DeferredCode":{"version":"5.50","file":"lib/CPAN/DeferredCode.pm"},"CPAN::Admin":{"version":5.501,"file":"lib/CPAN/Admin.pm"},"CPAN::Exception::RecursiveDependency::na":{"version":5.5001,"file":"lib/CPAN/Exception/RecursiveDependency.pm"},"CPAN::FTP":{"version":5.5013,"file":"lib/CPAN/FTP.pm"},"App::Cpan":{"version":1.676,"file":"lib/App/Cpan.pm"},"CPAN::CacheMgr":{"file":"lib/CPAN/CacheMgr.pm","version":5.5002},"CPAN::InfoObj":{"file":"lib/CPAN/InfoObj.pm","version":5.5},"CPAN::HandleConfig":{"version":5.5011,"file":"lib/CPAN/HandleConfig.pm"},"CPAN::Tarzip":{"file":"lib/CPAN/Tarzip.pm","version":5.5013},"CPAN::Distroprefs::Pref":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Exception::blocked_urllist":{"file":"lib/CPAN/Exception/blocked_urllist.pm","version":1.001},"CPAN":{"file":"lib/CPAN.pm","version":2.28},"CPAN::Mirrored::By":{"version":2.27,"file":"lib/CPAN/Mirrors.pm"}},"version":2.28,"dist":"CPAN-2.28","name":"CPAN"}perl5/x86_64-linux-thread-multi/.meta/IO-LockedFile-0.23/MYMETA.json000044400000001615152462503210020045 0ustar00{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "IO-LockedFile", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Fcntl" : "0", "IO::File" : "0" } } }, "release_status" : "stable", "version" : 0.23, "x_serialization_backend" : "JSON::PP version 4.06" } perl5/x86_64-linux-thread-multi/.meta/IO-LockedFile-0.23/install.json000044400000000414152462503210020513 0ustar00{"dist":"IO-LockedFile-0.23","pathname":"R/RA/RANI/IO-LockedFile-0.23.tar.gz","name":"IO::LockedFile","version":0.23,"provides":{"IO::LockedFile::Flock":{"file":"LockedFile/Flock.pm"},"IO::LockedFile":{"version":0.23,"file":"LockedFile.pm"}},"target":"IO::LockedFile"}perl5/x86_64-linux-thread-multi/.meta/version-0.9929/MYMETA.json000044400000002712152462503210017413 0ustar00{ "abstract" : "Structured version objects", "author" : [ "John Peacock " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "version", "no_index" : { "directory" : [ "t", "inc" ], "package" : [ "charstar" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "perl" : "5.006002" } }, "test" : { "requires" : { "File::Temp" : "0.13", "Test::More" : "0.45", "base" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-version@rt.cpan.org", "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=version" }, "repository" : { "type" : "git", "url" : "git://github.com/Perl/version.pm.git", "web" : "https://github.com/Perl/version.pm" } }, "version" : "0.9929", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/version-0.9929/install.json000044400000000574152462503210020071 0ustar00{"provides":{"version::vxs":{"file":"vutil/lib/version/vxs.pm","version":0.9929},"version::vpp":{"file":"vperl/vpp.pm","version":0.9929},"version":{"file":"lib/version.pm","version":0.9929},"version::regex":{"version":0.9929,"file":"lib/version/regex.pm"}},"version":0.9929,"pathname":"L/LE/LEONT/version-0.9929.tar.gz","target":"version","dist":"version-0.9929","name":"version"}perl5/x86_64-linux-thread-multi/.meta/Mozilla-CA-20211001/MYMETA.json000044400000002721152462503210017732 0ustar00{ "abstract" : "Mozilla's CA cert bundle in PEM format", "author" : [ "Gisle Aas " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "open_source" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Mozilla-CA", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "perl" : "5.006" } }, "test" : { "requires" : { "Test" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Mozilla-CA" }, "homepage" : "https://github.com/gisle/mozilla-ca", "license" : [ "https://www.mozilla.org/media/MPL/2.0/index.txt" ], "repository" : { "type" : "git", "url" : "https://github.com/gisle/mozilla-ca.git", "web" : "https://github.com/gisle/mozilla-ca" } }, "version" : "20211001", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/Mozilla-CA-20211001/install.json000044400000000331152462503210020377 0ustar00{"name":"Mozilla::CA","pathname":"A/AB/ABH/Mozilla-CA-20211001.tar.gz","dist":"Mozilla-CA-20211001","target":"Mozilla::CA","provides":{"Mozilla::CA":{"version":20211001,"file":"lib/Mozilla/CA.pm"}},"version":20211001}perl5/x86_64-linux-thread-multi/.meta/Canary-Stability-2013/MYMETA.json000044400000001435152462503210020721 0ustar00{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Canary-Stability", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } } }, "release_status" : "stable", "version" : "2013", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/Canary-Stability-2013/install.json000044400000000347152462503210021374 0ustar00{"target":"Canary::Stability","name":"Canary::Stability","provides":{"Canary::Stability":{"file":"Stability.pm","version":2013}},"pathname":"M/ML/MLEHMANN/Canary-Stability-2013.tar.gz","dist":"Canary-Stability-2013","version":2013}perl5/x86_64-linux-thread-multi/.meta/HTTP-Tiny-0.078/MYMETA.json000044400000013444152462503210017334 0ustar00{ "abstract" : "A small, simple, correct HTTP/1.1 client", "author" : [ "Christian Hansen ", "David Golden " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.023, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "HTTP-Tiny", "no_index" : { "directory" : [ "corpus", "examples", "t", "xt" ], "package" : [ "DB" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.17" }, "suggests" : { "JSON::PP" : "2.27300" } }, "develop" : { "requires" : { "Dist::Zilla" : "5", "Dist::Zilla::Plugin::Prereqs" : "0", "Dist::Zilla::Plugin::ReleaseStatus::FromVersion" : "0", "Dist::Zilla::Plugin::RemovePrereqs" : "0", "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.072", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Perl::Critic::Policy::Lax::ProhibitStringyEval::ExceptForRequire" : "0", "Pod::Coverage::TrustPod" : "0", "Pod::Wordlist" : "0", "Software::License::Perl_5" : "0", "Test::CPAN::Meta" : "0", "Test::MinimumVersion" : "0", "Test::More" : "0", "Test::Perl::Critic" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12", "Test::Version" : "1", "perl" : "5.006" } }, "runtime" : { "recommends" : { "HTTP::CookieJar" : "0.001", "IO::Socket::IP" : "0.32", "IO::Socket::SSL" : "1.42", "Mozilla::CA" : "20160104", "Net::SSLeay" : "1.49" }, "requires" : { "Carp" : "0", "Fcntl" : "0", "IO::Socket" : "0", "MIME::Base64" : "0", "Socket" : "0", "Time::Local" : "0", "bytes" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" }, "suggests" : { "IO::Socket::SSL" : "1.56" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "Data::Dumper" : "0", "Exporter" : "0", "ExtUtils::MakeMaker" : "0", "File::Basename" : "0", "File::Spec" : "0", "File::Temp" : "0", "IO::Dir" : "0", "IO::File" : "0", "IO::Socket::INET" : "0", "IPC::Cmd" : "0", "Test::More" : "0.96", "lib" : "0", "open" : "0" } } }, "provides" : { "HTTP::Tiny" : { "file" : "lib/HTTP/Tiny.pm", "version" : "0.078" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/chansen/p5-http-tiny/issues" }, "homepage" : "https://github.com/chansen/p5-http-tiny", "repository" : { "type" : "git", "url" : "https://github.com/chansen/p5-http-tiny.git", "web" : "https://github.com/chansen/p5-http-tiny" } }, "version" : "0.078", "x_authority" : "cpan:DAGOLDEN", "x_contributors" : [ "Alan Gardner ", "Alessandro Ghedini ", "A. Sinan Unur ", "Brad Gilbert ", "brian m. carlson ", "Chris Nehren ", "Chris Weyl ", "Claes Jakobsson ", "Clinton Gormley ", "Craig A. Berry ", "Craig Berry ", "David Golden ", "David Mitchell ", "Dean Pearce ", "Edward Zborowski ", "Felipe Gasper ", "Greg Kennedy ", "James E Keenan ", "James Raspass ", "Jeremy Mates ", "Jess Robinson ", "Karen Etheridge ", "Lukas Eklund ", "Martin J. Evans ", "Martin-Louis Bright ", "Matthew Horsfall ", "Michael R. Davis ", "Mike Doherty ", "Nicolas Rochelemagne ", "Olaf Alders ", "Olivier Mengué ", "Petr Písař ", "sanjay-cpu ", "Serguei Trouchelle ", "Shoichi Kaji ", "SkyMarshal ", "Sören Kornetzki ", "Steve Grazzini ", "Syohei YOSHIDA ", "Tatsuhiko Miyagawa ", "Tom Hukins ", "Tony Cook ", "Xavier Guimard " ], "x_generated_by_perl" : "v5.34.0", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } perl5/x86_64-linux-thread-multi/.meta/HTTP-Tiny-0.078/install.json000044400000000320152462503210017773 0ustar00{"version":"0.078","dist":"HTTP-Tiny-0.078","pathname":"D/DA/DAGOLDEN/HTTP-Tiny-0.078.tar.gz","provides":{"HTTP::Tiny":{"file":"lib/HTTP/Tiny.pm","version":"0.078"}},"target":"HTTP::Tiny","name":"HTTP::Tiny"}perl5/x86_64-linux-thread-multi/.meta/LWP-Protocol-https-6.10/MYMETA.json000044400000061634152462503210021151 0ustar00{ "abstract" : "Provide https support for LWP::UserAgent", "author" : [ "Gisle Aas " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "LWP-Protocol-https", "no_index" : { "directory" : [ "t", "xt" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" }, "suggests" : { "JSON::PP" : "2.27300" } }, "develop" : { "recommends" : { "Dist::Zilla::PluginBundle::Git::VersionManager" : "0.007" }, "requires" : { "File::Spec" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Changes" : "0.19", "Test::CPAN::Meta" : "0", "Test::CheckManifest" : "1.29", "Test::CleanNamespaces" : "0.15", "Test::EOL" : "0", "Test::Kwalitee" : "1.22", "Test::MinimumVersion" : "0", "Test::Mojibake" : "0", "Test::More" : "0.94", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Pod::Spelling::CommonMistakes" : "1.000", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12", "Test::Version" : "1" } }, "runtime" : { "requires" : { "IO::Socket::SSL" : "1.54", "LWP::Protocol::http" : "0", "LWP::UserAgent" : "6.06", "Mozilla::CA" : "20180117", "Net::HTTPS" : "6", "base" : "0", "perl" : "5.008001", "strict" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "File::Temp" : "0", "IO::Select" : "0", "IO::Socket::INET" : "0", "IO::Socket::SSL" : "1.54", "IO::Socket::SSL::Utils" : "0", "LWP::UserAgent" : "6.06", "Socket" : "0", "Test::More" : "0.96", "Test::RequiresInternet" : "0", "warnings" : "0" } } }, "provides" : { "LWP::Protocol::https" : { "file" : "lib/LWP/Protocol/https.pm", "version" : "6.10" }, "LWP::Protocol::https::Socket" : { "file" : "lib/LWP/Protocol/https.pm", "version" : "6.10" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/libwww-perl/LWP-Protocol-https/issues" }, "homepage" : "https://github.com/libwww-perl/LWP-Protocol-https", "repository" : { "type" : "git", "url" : "https://github.com/libwww-perl/LWP-Protocol-https.git", "web" : "https://github.com/libwww-perl/LWP-Protocol-https" }, "x_IRC" : "irc://irc.perl.org/#lwp", "x_MailingList" : "mailto:libwww@perl.org" }, "version" : "6.10", "x_Dist_Zilla" : { "perl" : { "version" : "5.030003" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "LICENSE", "META.json", "Makefile.PL", "README.md" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "Git::GatherDir", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::PruneCruft", "name" : "PruneCruft", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "MetaConfig", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Package", "config" : { "Dist::Zilla::Plugin::MetaProvides::Package" : { "finder_objects" : [ { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.017" } ], "include_underscores" : 0 }, "Dist::Zilla::Role::MetaProvider::Provider" : { "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004", "inherit_missing" : 1, "inherit_version" : 1, "meta_noindex" : 1 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "MetaProvides::Package", "version" : "2.004003" }, { "class" : "Dist::Zilla::Plugin::MetaNoIndex", "name" : "MetaNoIndex", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "MetaYAML", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "MetaJSON", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "MetaResources", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "dist.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." } }, "name" : "Git::Check", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.29.2", "include_authors" : 0, "include_releaser" : 1, "order_by" : "name", "paths" : [] } }, "name" : "Git::Contributors", "version" : "0.035" }, { "class" : "Dist::Zilla::Plugin::GithubMeta", "name" : "GithubMeta", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Authority", "name" : "Authority", "version" : "1.009" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "Manifest", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "License", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "Markdown_Readme", "version" : "0.163250" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "recommends" } }, "name" : "@Git::VersionManager/pluginbundle version", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::RewriteVersion::Transitional", "config" : { "Dist::Zilla::Plugin::RewriteVersion" : { "add_tarball_name" : 0, "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "skip_version_provider" : 0 }, "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {} }, "name" : "@Git::VersionManager/RewriteVersion::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Update", "name" : "@Git::VersionManager/MetaProvides::Update", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Changes" ], "match" : [] } }, "name" : "@Git::VersionManager/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "v%V%n%n%c", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "LICENSE", "META.json", "Makefile.PL" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/release snapshot", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v6.10", "tag_format" : "v%V", "tag_message" : "v%V" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/Git::Tag", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 }, "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {} }, "name" : "@Git::VersionManager/BumpVersionAfterRelease::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@Git::VersionManager/NextRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "increment $VERSION after %v release", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Build.PL", "Changes", "Makefile.PL" ], "allow_dirty_match" : [ "(?^:^lib/.*\\.pm$)" ], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/post-release commit", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::Prereqs::FromCPANfile", "name" : "Prereqs::FromCPANfile", "version" : "0.08" }, { "class" : "Dist::Zilla::Plugin::MakeMaker::Awesome", "config" : { "Dist::Zilla::Plugin::MakeMaker" : { "make_path" : "make", "version" : "6.017" }, "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "4", "version" : "6.017" } }, "name" : "MakeMaker::Awesome", "version" : "0.48" }, { "class" : "Dist::Zilla::Plugin::CheckChangeLog", "name" : "CheckChangeLog", "version" : "0.05" }, { "class" : "Dist::Zilla::Plugin::CheckChangesHasContent", "name" : "CheckChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::Test::Kwalitee", "config" : { "Dist::Zilla::Plugin::Test::Kwalitee" : { "filename" : "xt/author/kwalitee.t", "skiptest" : [ "has_readme" ] } }, "name" : "Test::Kwalitee", "version" : "2.12" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::Test::Version", "name" : "Test::Version", "version" : "1.09" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "Test::ReportPrereqs", "version" : "0.028" }, { "class" : "Dist::Zilla::Plugin::Test::Compile", "config" : { "Dist::Zilla::Plugin::Test::Compile" : { "bail_out_on_fail" : "1", "fail_on_warning" : "author", "fake_home" : 0, "filename" : "xt/author/00-compile.t", "module_finder" : [ ":InstallModules" ], "needs_display" : 0, "phase" : "develop", "script_finder" : [ ":PerlExecFiles" ], "skips" : [], "switch" : [] } }, "name" : "Test::Compile", "version" : "2.058" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "config" : { "Dist::Zilla::Plugin::Test::Portability" : { "options" : "" } }, "name" : "Test::Portability", "version" : "2.001000" }, { "class" : "Dist::Zilla::Plugin::Test::CleanNamespaces", "config" : { "Dist::Zilla::Plugin::Test::CleanNamespaces" : { "filename" : "xt/author/clean-namespaces.t", "skips" : [] } }, "name" : "Test::CleanNamespaces", "version" : "0.006" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":InstallModules", ":TestFiles" ], "trailing_whitespace" : 1 } }, "name" : "Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::MetaTests", "name" : "MetaTests", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Test::ChangesHasContent", "name" : "Test::ChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::Test::MinimumVersion", "config" : { "Dist::Zilla::Plugin::Test::MinimumVersion" : { "max_target_perl" : null } }, "name" : "Test::MinimumVersion", "version" : "2.000010" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "PodSyntaxTests", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", "name" : "Test::Pod::Coverage::Configurable", "version" : "0.07" }, { "class" : "Dist::Zilla::Plugin::Test::PodSpelling", "config" : { "Dist::Zilla::Plugin::Test::PodSpelling" : { "directories" : [ "bin", "lib" ], "spell_cmd" : "aspell list", "stopwords" : [], "wordlist" : "Pod::Wordlist" } }, "name" : "Test::PodSpelling", "version" : "2.007005" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "4" } }, "name" : "RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::CheckStrictVersion", "name" : "CheckStrictVersion", "version" : "0.001" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", "name" : "CopyFilesFromBuild", "version" : "0.170880" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "TestRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "ConfirmRelease", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "UploadToCPAN", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.29.2", "repo_root" : "." } }, "name" : "Git::Push", "version" : "2.047" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.017" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.017" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.017" } }, "x_authority" : "cpan:GAAS", "x_contributors" : [ "Adam Kennedy ", "Adam Sjogren ", "Alexandr Ciornii ", "Alexey Tourbin ", "Alex Kapranoff ", "amire80 ", "Andreas J. Koenig ", "Bill Mann ", "Bron Gondwana ", "Chase Whitener ", "Christopher J. Madsen ", "cpansprout ", "Dan Book ", "Daniel Hedlund ", "David E. Wheeler ", "David Golden ", "DAVIDRW ", "drieux ", "Father Chrysostomos ", "FWILES ", "Gavin Peters ", "Gianni Ceccarelli ", "Gisle Aas ", "Graeme Thompson ", "Hans-H. Froehlich ", "Ian Kilgore ", "Jacob J ", "Jakub Wilk ", "jefflee ", "JJ Merelo ", "john9art ", "Jon Jensen ", "Karen Etheridge ", "Leo Lapworth ", "Mark Stosberg ", "Michael G. Schwern ", "Mike Schilli ", "Mohammad S Anwar ", "murphy ", "Olaf Alders ", "Ondrej Hanak ", "Peter Rabbitson ", "phrstbrn ", "Randy Stauner ", "Robert Stone ", "Rolf Grossmann ", "ruff ", "sasao ", "Sean M. Burke ", "Shoichi Kaji ", "Slaven Rezic ", "Spiros Denaxas ", "Steffen Ullrich ", "Steve Hay ", "Tim Couzins ", "Todd Lipcon ", "Tom Hukins ", "Tony Finch ", "Toru Yamaguchi ", "uid39246 ", "Ville Skyttä ", "Yuri Karaban ", "Yury Zavarin ", "Zefram " ], "x_generated_by_perl" : "v5.30.3", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } perl5/x86_64-linux-thread-multi/.meta/LWP-Protocol-https-6.10/install.json000044400000000531152462503210021610 0ustar00{"target":"LWP::Protocol::https","provides":{"LWP::Protocol::https::Socket":{"version":"6.10","file":"lib/LWP/Protocol/https.pm"},"LWP::Protocol::https":{"version":"6.10","file":"lib/LWP/Protocol/https.pm"}},"version":"6.10","pathname":"O/OA/OALDERS/LWP-Protocol-https-6.10.tar.gz","name":"LWP::Protocol::https","dist":"LWP-Protocol-https-6.10"}perl5/x86_64-linux-thread-multi/.meta/DBD-mysql-4.050/MYMETA.json000044400000011155152462503210017357 0ustar00{ "abstract" : "A MySQL driver for the Perl5 Database Interface (DBI)", "author" : [ "Patrick Galbraith " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "DBD-mysql", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "DBI" : "1.609", "Data::Dumper" : "0", "Devel::CheckLib" : "1.09", "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "DBI" : "1.609", "perl" : "5.008001" } }, "test" : { "recommends" : { "Proc::ProcessTable" : "0" }, "requires" : { "Test::Deep" : "0", "Test::Simple" : "0.90", "Time::HiRes" : "0", "bigint" : "0" }, "suggests" : { "Test::DistManifest" : "0", "Test::Pod" : "1.00" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/perl5-dbi/DBD-mysql/issues" }, "homepage" : "http://dbi.perl.org/", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "https://github.com/perl5-dbi/DBD-mysql.git", "web" : "https://github.com/perl5-dbi/DBD-mysql" }, "x_IRC" : "irc://irc.perl.org/#dbi", "x_MailingList" : "mailto:dbi-dev@perl.org" }, "version" : "4.050", "x_contributors" : [ "Alceu Rodrigues de Freitas Junior ", "Alexandr Ciornii ", "Alexey Molchanov ", "Amiri Barksdale at Home ", "Andrew Miller ", "Aran Deltac ", "Bernt M. Johnsen ", "Chase Whitener ", "Chip Salzenberg ", "Chris Hammond ", "Chris Weyl ", "Christian Walde ", "Dagfinn Ilmari Mannsåker ", "Daisuke Murase ", "Damyan Ivanov ", "Dan Book ", "Daniël van Eeden ", "Dave Lambley ", "David Farrell ", "David Steinbrunner ", "Giovanni Bechis ", "Graham Ollis ", "H.Merijn Brand - Tux ", "Hanno ", "James McCoy ", "Jim Winstead ", "Juergen Weigert ", "Kenny Gryp ", "Lu Shengliang ", "Masahiro Chiba ", "Matthew Horsfall (alh) ", "Michiel Beijen ", "Mike Pomraning ", "Mohammad S Anwar ", "Pali ", "Patrick Galbraith ", "Perlover ", "Peter Botha ", "Petr Písař ", "Reini Urban ", "Rob Hoelz ", "Rob Van Dam ", "Rudy Lippan ", "Scimon ", "Sergey Zhuravlev ", "Sergiy Borodych ", "Sharif Nassar ", "Steffen Mueller ", "Steven Hartland ", "Taro Kobayashi <9re.3000@gmail.com>", "Tatsuhiko Miyagawa ", "Tim Mullin ", "Ville Skyttä ", "Vladimir Marek ", "katyavoid ", "kmx ", "tokuhirom ", "zefram ", "zentooo " ], "x_serialization_backend" : "JSON::PP version 4.06" } perl5/x86_64-linux-thread-multi/.meta/DBD-mysql-4.050/install.json000044400000001020152462503210020017 0ustar00{"name":"DBD::mysql","provides":{"DBD::mysql::dr":{"version":"4.050","file":"lib/DBD/mysql.pm"},"DBD::mysql":{"version":"4.050","file":"lib/DBD/mysql.pm"},"Bundle::DBD::mysql":{"version":"4.050","file":"lib/Bundle/DBD/mysql.pm"},"DBD::mysql::GetInfo":{"file":"lib/DBD/mysql/GetInfo.pm"},"DBD::mysql::st":{"version":"4.050","file":"lib/DBD/mysql.pm"},"DBD::mysql::db":{"file":"lib/DBD/mysql.pm","version":"4.050"}},"pathname":"D/DV/DVEEDEN/DBD-mysql-4.050.tar.gz","target":"DBD::mysql","dist":"DBD-mysql-4.050","version":"4.050"}perl5/x86_64-linux-thread-multi/.meta/Path-Class-0.37/MYMETA.json000044400000003147152462503210017505 0ustar00{ "abstract" : "Cross-platform path specification manipulation", "author" : [ "Ken Williams " ], "dynamic_config" : 0, "generated_by" : "Module::Build version 0.4224", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Path-Class", "prereqs" : { "build" : { "requires" : { "Module::Build" : "0.3601" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.30", "Module::Build" : "0.3601" } }, "runtime" : { "requires" : { "Carp" : 0, "Cwd" : 0, "Exporter" : 0, "File::Copy" : 0, "File::Path" : 0, "File::Spec" : "3.26", "File::Temp" : 0, "File::stat" : 0, "IO::Dir" : 0, "IO::File" : 0, "Perl::OSType" : 0, "Scalar::Util" : 0, "overload" : 0, "parent" : 0, "strict" : 0 } }, "test" : { "requires" : { "Test" : 0, "Test::More" : 0, "warnings" : 0 } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "http://github.com/kenahoo/Path-Class/issues" }, "repository" : { "type" : "git", "url" : "git://github.com/kenahoo/Path-Class.git" } }, "version" : "0.37", "x_serialization_backend" : "JSON::PP version 2.97001" } perl5/x86_64-linux-thread-multi/.meta/Path-Class-0.37/install.json000044400000000640152462503210020152 0ustar00{"version":0.37,"provides":{"Path::Class::Entity":{"version":0.37,"file":"lib/Path/Class/Entity.pm"},"Path::Class":{"version":0.37,"file":"lib/Path/Class.pm"},"Path::Class::File":{"file":"lib/Path/Class/File.pm","version":0.37},"Path::Class::Dir":{"version":0.37,"file":"lib/Path/Class/Dir.pm"}},"target":"Path::Class","dist":"Path-Class-0.37","pathname":"K/KW/KWILLIAMS/Path-Class-0.37.tar.gz","name":"Path::Class"}perl5/LWP.pm000044400000052263152462503210006601 0ustar00package LWP; our $VERSION = '6.58'; require LWP::UserAgent; # this should load everything you need sub Version { $VERSION; } 1; __END__ =pod =encoding utf-8 =head1 NAME LWP - The World-Wide Web library for Perl =head1 SYNOPSIS use LWP; print "This is libwww-perl-$LWP::VERSION\n"; =head1 DESCRIPTION The libwww-perl collection is a set of Perl modules which provides a simple and consistent application programming interface (API) to the World-Wide Web. The main focus of the library is to provide classes and functions that allow you to write WWW clients. The library also contain modules that are of more general use and even classes that help you implement simple HTTP servers. Most modules in this library provide an object oriented API. The user agent, requests sent and responses received from the WWW server are all represented by objects. This makes a simple and powerful interface to these services. The interface is easy to extend and customize for your own needs. The main features of the library are: =over 3 =item * Contains various reusable components (modules) that can be used separately or together. =item * Provides an object oriented model of HTTP-style communication. Within this framework we currently support access to C, C, C, C, C, C, and C resources. =item * Provides a full object oriented interface or a very simple procedural interface. =item * Supports the basic and digest authorization schemes. =item * Supports transparent redirect handling. =item * Supports access through proxy servers. =item * Provides parser for F files and a framework for constructing robots. =item * Supports parsing of HTML forms. =item * Implements HTTP content negotiation algorithm that can be used both in protocol modules and in server scripts (like CGI scripts). =item * Supports HTTP cookies. =item * Some simple command line clients, for instance C and C. =back =head1 HTTP STYLE COMMUNICATION The libwww-perl library is based on HTTP style communication. This section tries to describe what that means. Let us start with this quote from the HTTP specification document L: =over 3 =item * The HTTP protocol is based on a request/response paradigm. A client establishes a connection with a server and sends a request to the server in the form of a request method, URI, and protocol version, followed by a MIME-like message containing request modifiers, client information, and possible body content. The server responds with a status line, including the message's protocol version and a success or error code, followed by a MIME-like message containing server information, entity meta-information, and possible body content. =back What this means to libwww-perl is that communication always take place through these steps: First a I object is created and configured. This object is then passed to a server and we get a I object in return that we can examine. A request is always independent of any previous requests, i.e. the service is stateless. The same simple model is used for any kind of service we want to access. For example, if we want to fetch a document from a remote file server, then we send it a request that contains a name for that document and the response will contain the document itself. If we access a search engine, then the content of the request will contain the query parameters and the response will contain the query result. If we want to send a mail message to somebody then we send a request object which contains our message to the mail server and the response object will contain an acknowledgment that tells us that the message has been accepted and will be forwarded to the recipient(s). It is as simple as that! =head2 The Request Object The libwww-perl request object has the class name L. The fact that the class name uses C as a prefix only implies that we use the HTTP model of communication. It does not limit the kind of services we can try to pass this I to. For instance, we will send Ls both to ftp and gopher servers, as well as to the local file system. The main attributes of the request objects are: =over 3 =item * B is a short string that tells what kind of request this is. The most common methods are B, B, B and B. =item * B is a string denoting the protocol, server and the name of the "document" we want to access. The B might also encode various other parameters. =item * B contains additional information about the request and can also used to describe the content. The headers are a set of keyword/value pairs. =item * B is an arbitrary amount of data. =back =head2 The Response Object The libwww-perl response object has the class name L. The main attributes of objects of this class are: =over 3 =item * B is a numerical value that indicates the overall outcome of the request. =item * B is a short, human readable string that corresponds to the I. =item * B contains additional information about the response and describe the content. =item * B is an arbitrary amount of data. =back Since we don't want to handle all possible I values directly in our programs, a libwww-perl response object has methods that can be used to query what kind of response this is. The most commonly used response classification methods are: =over 3 =item is_success() The request was successfully received, understood or accepted. =item is_error() The request failed. The server or the resource might not be available, access to the resource might be denied or other things might have failed for some reason. =back =head2 The User Agent Let us assume that we have created a I object. What do we actually do with it in order to receive a I? The answer is that you pass it to a I object and this object takes care of all the things that need to be done (like low-level communication and error handling) and returns a I object. The user agent represents your application on the network and provides you with an interface that can accept I and return I. The user agent is an interface layer between your application code and the network. Through this interface you are able to access the various servers on the network. The class name for the user agent is L. Every libwww-perl application that wants to communicate should create at least one object of this class. The main method provided by this object is request(). This method takes an L object as argument and (eventually) returns a L object. The user agent has many other attributes that let you configure how it will interact with the network and with your application. =over 3 =item * B specifies how much time we give remote servers to respond before the library disconnects and creates an internal I response. =item * B specifies the name that your application uses when it presents itself on the network. =item * B can be set to the e-mail address of the person responsible for running the application. If this is set, then the address will be sent to the servers with every request. =item * B specifies whether we should initialize response headers from the C<< >> section of HTML documents. =item * B and B specify if and when to go through a proxy server. L =item * B provides a way to set up user names and passwords needed to access certain services. =back Many applications want even more control over how they interact with the network and they get this by sub-classing L. The library includes a sub-class, L, for robot applications. =head2 An Example This example shows how the user agent, a request and a response are represented in actual perl code: # Create a user agent object use LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->agent("MyApp/0.1 "); # Create a request my $req = HTTP::Request->new(POST => 'http://search.cpan.org/search'); $req->content_type('application/x-www-form-urlencoded'); $req->content('query=libwww-perl&mode=dist'); # Pass request to the user agent and get a response back my $res = $ua->request($req); # Check the outcome of the response if ($res->is_success) { print $res->content; } else { print $res->status_line, "\n"; } The C<$ua> is created once when the application starts up. New request objects should normally created for each request sent. =head1 NETWORK SUPPORT This section discusses the various protocol schemes and the HTTP style methods that headers may be used for each. For all requests, a "User-Agent" header is added and initialized from the C<< $ua->agent >> attribute before the request is handed to the network layer. In the same way, a "From" header is initialized from the $ua->from attribute. For all responses, the library adds a header called "Client-Date". This header holds the time when the response was received by your application. The format and semantics of the header are the same as the server created "Date" header. You may also encounter other "Client-XXX" headers. They are all generated by the library internally and are not received from the servers. =head2 HTTP Requests HTTP requests are just handed off to an HTTP server and it decides what happens. Few servers implement methods beside the usual "GET", "HEAD", "POST" and "PUT", but CGI-scripts may implement any method they like. If the server is not available then the library will generate an internal error response. The library automatically adds a "Host" and a "Content-Length" header to the HTTP request before it is sent over the network. For a GET request you might want to add a "If-Modified-Since" or "If-None-Match" header to make the request conditional. For a POST request you should add the "Content-Type" header. When you try to emulate HTML EFORM> handling you should usually let the value of the "Content-Type" header be "application/x-www-form-urlencoded". See L for examples of this. The libwww-perl HTTP implementation currently support the HTTP/1.1 and HTTP/1.0 protocol. The library allows you to access proxy server through HTTP. This means that you can set up the library to forward all types of request through the HTTP protocol module. See L for documentation of this. =head2 HTTPS Requests HTTPS requests are HTTP requests over an encrypted network connection using the SSL protocol developed by Netscape. Everything about HTTP requests above also apply to HTTPS requests. In addition the library will add the headers "Client-SSL-Cipher", "Client-SSL-Cert-Subject" and "Client-SSL-Cert-Issuer" to the response. These headers denote the encryption method used and the name of the server owner. The request can contain the header "If-SSL-Cert-Subject" in order to make the request conditional on the content of the server certificate. If the certificate subject does not match, no request is sent to the server and an internally generated error response is returned. The value of the "If-SSL-Cert-Subject" header is interpreted as a Perl regular expression. =head2 FTP Requests The library currently supports GET, HEAD and PUT requests. GET retrieves a file or a directory listing from an FTP server. PUT stores a file on a ftp server. You can specify a ftp account for servers that want this in addition to user name and password. This is specified by including an "Account" header in the request. User name/password can be specified using basic authorization or be encoded in the URL. Failed logins return an UNAUTHORIZED response with "WWW-Authenticate: Basic" and can be treated like basic authorization for HTTP. The library supports ftp ASCII transfer mode by specifying the "type=a" parameter in the URL. It also supports transfer of ranges for FTP transfers using the "Range" header. Directory listings are by default returned unprocessed (as returned from the ftp server) with the content media type reported to be "text/ftp-dir-listing". The L module provides methods for parsing of these directory listing. The ftp module is also able to convert directory listings to HTML and this can be requested via the standard HTTP content negotiation mechanisms (add an "Accept: text/html" header in the request if you want this). For normal file retrievals, the "Content-Type" is guessed based on the file name suffix. See L. The "If-Modified-Since" request header works for servers that implement the C command. It will probably not work for directory listings though. Example: $req = HTTP::Request->new(GET => 'ftp://me:passwd@ftp.some.where.com/'); $req->header(Accept => "text/html, */*;q=0.1"); =head2 News Requests Access to the USENET News system is implemented through the NNTP protocol. The name of the news server is obtained from the NNTP_SERVER environment variable and defaults to "news". It is not possible to specify the hostname of the NNTP server in news: URLs. The library supports GET and HEAD to retrieve news articles through the NNTP protocol. You can also post articles to newsgroups by using (surprise!) the POST method. GET on newsgroups is not implemented yet. Examples: $req = HTTP::Request->new(GET => 'news:abc1234@a.sn.no'); $req = HTTP::Request->new(POST => 'news:comp.lang.perl.test'); $req->header(Subject => 'This is a test', From => 'me@some.where.org'); $req->content(<new(GET => 'gopher://gopher.sn.no/'); =head2 File Request The library supports GET and HEAD methods for file requests. The "If-Modified-Since" header is supported. All other headers are ignored. The I component of the file URL must be empty or set to "localhost". Any other I value will be treated as an error. Directories are always converted to an HTML document. For normal files, the "Content-Type" and "Content-Encoding" in the response are guessed based on the file suffix. Example: $req = HTTP::Request->new(GET => 'file:/etc/passwd'); =head2 Mailto Request You can send (aka "POST") mail messages using the library. All headers specified for the request are passed on to the mail system. The "To" header is initialized from the mail address in the URL. Example: $req = HTTP::Request->new(POST => 'mailto:libwww@perl.org'); $req->header(Subject => "subscribe"); $req->content("Please subscribe me to the libwww-perl mailing list!\n"); =head2 CPAN Requests URLs with scheme C are redirected to a suitable CPAN mirror. If you have your own local mirror of CPAN you might tell LWP to use it for C URLs by an assignment like this: $LWP::Protocol::cpan::CPAN = "file:/local/CPAN/"; Suitable CPAN mirrors are also picked up from the configuration for the CPAN.pm, so if you have used that module a suitable mirror should be picked automatically. If neither of these apply, then a redirect to the generic CPAN http location is issued. Example request to download the newest perl: $req = HTTP::Request->new(GET => "cpan:src/latest.tar.gz"); =head1 OVERVIEW OF CLASSES AND PACKAGES This table should give you a quick overview of the classes provided by the library. Indentation shows class inheritance. LWP::MemberMixin -- Access to member variables of Perl5 classes LWP::UserAgent -- WWW user agent class LWP::RobotUA -- When developing a robot applications LWP::Protocol -- Interface to various protocol schemes LWP::Protocol::http -- http:// access LWP::Protocol::file -- file:// access LWP::Protocol::ftp -- ftp:// access ... LWP::Authen::Basic -- Handle 401 and 407 responses LWP::Authen::Digest HTTP::Headers -- MIME/RFC822 style header (used by HTTP::Message) HTTP::Message -- HTTP style message HTTP::Request -- HTTP request HTTP::Response -- HTTP response HTTP::Daemon -- A HTTP server class WWW::RobotRules -- Parse robots.txt files WWW::RobotRules::AnyDBM_File -- Persistent RobotRules Net::HTTP -- Low level HTTP client The following modules provide various functions and definitions. LWP -- This file. Library version number and documentation. LWP::MediaTypes -- MIME types configuration (text/html etc.) LWP::Simple -- Simplified procedural interface for common functions HTTP::Status -- HTTP status code (200 OK etc) HTTP::Date -- Date parsing module for HTTP date formats HTTP::Negotiate -- HTTP content negotiation calculation File::Listing -- Parse directory listings HTML::Form -- Processing for
    s in HTML documents =head1 MORE DOCUMENTATION All modules contain detailed information on the interfaces they provide. The L manpage is the libwww-perl cookbook that contain examples of typical usage of the library. You might want to take a look at how the scripts L, L, L and L are implemented. =head1 ENVIRONMENT The following environment variables are used by LWP: =over =item HOME The L functions will look for the F<.media.types> and F<.mime.types> files relative to you home directory. =item http_proxy =item ftp_proxy =item xxx_proxy =item no_proxy These environment variables can be set to enable communication through a proxy server. See the description of the C method in L. =item PERL_LWP_ENV_PROXY If set to a TRUE value, then the L will by default call C during initialization. This makes LWP honor the proxy variables described above. =item PERL_LWP_SSL_VERIFY_HOSTNAME The default C setting for L. If not set the default will be 1. Set it as 0 to disable hostname verification (the default prior to libwww-perl 5.840. =item PERL_LWP_SSL_CA_FILE =item PERL_LWP_SSL_CA_PATH The file and/or directory where the trusted Certificate Authority certificates is located. See L for details. =item PERL_HTTP_URI_CLASS Used to decide what URI objects to instantiate. The default is L. You might want to set it to L for compatibility with old times. =back =head1 AUTHORS LWP was made possible by contributions from Adam Newby, Albert Dvornik, Alexandre Duret-Lutz, Andreas Gustafsson, Andreas König, Andrew Pimlott, Andy Lester, Ben Coleman, Benjamin Low, Ben Low, Ben Tilly, Blair Zajac, Bob Dalgleish, BooK, Brad Hughes, Brian J. Murrell, Brian McCauley, Charles C. Fu, Charles Lane, Chris Nandor, Christian Gilmore, Chris W. Unger, Craig Macdonald, Dale Couch, Dan Kubb, Dave Dunkin, Dave W. Smith, David Coppit, David Dick, David D. Kilzer, Doug MacEachern, Edward Avis, erik, Gary Shea, Gisle Aas, Graham Barr, Gurusamy Sarathy, Hans de Graaff, Harald Joerg, Harry Bochner, Hugo, Ilya Zakharevich, INOUE Yoshinari, Ivan Panchenko, Jack Shirazi, James Tillman, Jan Dubois, Jared Rhine, Jim Stern, Joao Lopes, John Klar, Johnny Lee, Josh Kronengold, Josh Rai, Joshua Chamas, Joshua Hoblitt, Kartik Subbarao, Keiichiro Nagano, Ken Williams, KONISHI Katsuhiro, Lee T Lindley, Liam Quinn, Marc Hedlund, Marc Langheinrich, Mark D. Anderson, Marko Asplund, Mark Stosberg, Markus B Krüger, Markus Laker, Martijn Koster, Martin Thurn, Matthew Eldridge, Matthew.van.Eerde, Matt Sergeant, Michael A. Chase, Michael Quaranta, Michael Thompson, Mike Schilli, Moshe Kaminsky, Nathan Torkington, Nicolai Langfeldt, Norton Allen, Olly Betts, Paul J. Schinder, peterm, Philip Guenther, Daniel Buenzli, Pon Hwa Lin, Radoslaw Zielinski, Radu Greab, Randal L. Schwartz, Richard Chen, Robin Barker, Roy Fielding, Sander van Zoest, Sean M. Burke, shildreth, Slaven Rezic, Steve A Fink, Steve Hay, Steven Butler, Steve_Kilbane, Takanori Ugai, Thomas Lotterer, Tim Bunce, Tom Hughes, Tony Finch, Ville Skyttä, Ward Vandewege, William York, Yale Huang, and Yitzchak Scott-Thoennes. LWP owes a lot in motivation, design, and code, to the libwww-perl library for Perl4 by Roy Fielding, which included work from Alberto Accomazzi, James Casey, Brooks Cutter, Martijn Koster, Oscar Nierstrasz, Mel Melchner, Gertjan van Oosten, Jared Rhine, Jack Shirazi, Gene Spafford, Marc VanHeyningen, Steven E. Brenner, Marion Hakanson, Waldemar Kebsch, Tony Sanders, and Larry Wall; see the libwww-perl-0.40 library for details. =head1 COPYRIGHT Copyright 1995-2009, Gisle Aas Copyright 1995, Martijn Koster This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AVAILABILITY The latest version of this library is likely to be available from CPAN as well as: http://github.com/libwww-perl/libwww-perl The best place to discuss this code is on the mailing list. =cut perl5/Types/Serialiser.pm000044400000021674152462503210011347 0ustar00=head1 NAME Types::Serialiser - simple data types for common serialisation formats =encoding utf-8 =head1 SYNOPSIS =head1 DESCRIPTION This module provides some extra datatypes that are used by common serialisation formats such as JSON or CBOR. The idea is to have a repository of simple/small constants and containers that can be shared by different implementations so they become interoperable between each other. =cut package Types::Serialiser; use common::sense; # required to suppress annoying warnings our $VERSION = '1.01'; =head1 SIMPLE SCALAR CONSTANTS Simple scalar constants are values that are overloaded to act like simple Perl values, but have (class) type to differentiate them from normal Perl scalars. This is necessary because these have different representations in the serialisation formats. In the following, functions with zero or one arguments have a prototype of C<()> and C<($)>, respectively, so act as constants and unary operators. =head2 BOOLEANS (Types::Serialiser::Boolean class) This type has only two instances, true and false. A natural representation for these in Perl is C<1> and C<0>, but serialisation formats need to be able to differentiate between them and mere numbers. =over 4 =item $Types::Serialiser::true, Types::Serialiser::true This value represents the "true" value. In most contexts is acts like the number C<1>. It is up to you whether you use the variable form (C<$Types::Serialiser::true>) or the constant form (C). The constant is represented as a reference to a scalar containing C<1> - implementations are allowed to directly test for this. =item $Types::Serialiser::false, Types::Serialiser::false This value represents the "false" value. In most contexts is acts like the number C<0>. It is up to you whether you use the variable form (C<$Types::Serialiser::false>) or the constant form (C). The constant is represented as a reference to a scalar containing C<0> - implementations are allowed to directly test for this. =item Types::Serialiser::as_bool $value Converts a Perl scalar into a boolean, which is useful syntactic sugar. Strictly equivalent to: $value ? $Types::Serialiser::true : $Types::Serialiser::false =item $is_bool = Types::Serialiser::is_bool $value Returns true iff the C<$value> is either C<$Types::Serialiser::true> or C<$Types::Serialiser::false>. For example, you could differentiate between a perl true value and a C by using this: $value && Types::Serialiser::is_bool $value =item $is_true = Types::Serialiser::is_true $value Returns true iff C<$value> is C<$Types::Serialiser::true>. =item $is_false = Types::Serialiser::is_false $value Returns false iff C<$value> is C<$Types::Serialiser::false>. =back =head2 ERROR (Types::Serialiser::Error class) This class has only a single instance, C. It is used to signal an encoding or decoding error. In CBOR for example, and object that couldn't be encoded will be represented by a CBOR undefined value, which is represented by the error value in Perl. =over 4 =item $Types::Serialiser::error, Types::Serialiser::error This value represents the "error" value. Accessing values of this type will throw an exception. The constant is represented as a reference to a scalar containing C - implementations are allowed to directly test for this. =item $is_error = Types::Serialiser::is_error $value Returns false iff C<$value> is C<$Types::Serialiser::error>. =back =cut BEGIN { # for historical reasons, and to avoid extra dependencies in JSON::PP, # we alias *Types::Serialiser::Boolean with JSON::PP::Boolean. package JSON::PP::Boolean; *Types::Serialiser::Boolean:: = *JSON::PP::Boolean::; } { # this must done before blessing to work around bugs # in perl < 5.18 (it seems to be fixed in 5.18). package Types::Serialiser::BooleanBase; use overload "0+" => sub { ${$_[0]} }, "++" => sub { $_[0] = ${$_[0]} + 1 }, "--" => sub { $_[0] = ${$_[0]} - 1 }, fallback => 1; @Types::Serialiser::Boolean::ISA = Types::Serialiser::BooleanBase::; } our $true = do { bless \(my $dummy = 1), Types::Serialiser::Boolean:: }; our $false = do { bless \(my $dummy = 0), Types::Serialiser::Boolean:: }; our $error = do { bless \(my $dummy ), Types::Serialiser::Error:: }; sub true () { $true } sub false () { $false } sub error () { $error } sub as_bool($) { $_[0] ? $true : $false } sub is_bool ($) { UNIVERSAL::isa $_[0], Types::Serialiser::Boolean:: } sub is_true ($) { $_[0] && UNIVERSAL::isa $_[0], Types::Serialiser::Boolean:: } sub is_false ($) { !$_[0] && UNIVERSAL::isa $_[0], Types::Serialiser::Boolean:: } sub is_error ($) { UNIVERSAL::isa $_[0], Types::Serialiser::Error:: } package Types::Serialiser::Error; sub error { require Carp; Carp::croak ("caught attempt to use the Types::Serialiser::error value"); }; use overload "0+" => \&error, "++" => \&error, "--" => \&error, fallback => 1; =head1 NOTES FOR XS USERS The recommended way to detect whether a scalar is one of these objects is to check whether the stash is the C or C stash, and then follow the scalar reference to see if it's C<1> (true), C<0> (false) or C (error). While it is possible to use an isa test, directly comparing stash pointers is faster and guaranteed to work. For historical reasons, the C stash is just an alias for C. When printed, the classname with usually be C, but isa tests and stash pointer comparison will normally work correctly (i.e. Types::Serialiser::true ISA JSON::PP::Boolean, but also ISA Types::Serialiser::Boolean). =head1 A GENERIC OBJECT SERIALIATION PROTOCOL This section explains the object serialisation protocol used by L. It is meant to be generic enough to support any kind of generic object serialiser. This protocol is called "the Types::Serialiser object serialisation protocol". =head2 ENCODING When the encoder encounters an object that it cannot otherwise encode (for example, L can encode a few special types itself, and will first attempt to use the special C serialisation protocol), it will look up the C method on the object. Note that the C method will normally be called I encoding, and I change the data structure that is being encoded in any way, or it might cause memory corruption or worse. If it exists, it will call it with two arguments: the object to serialise, and a constant string that indicates the name of the data model. For example L uses C, and the L and L modules (or any other JSON serialiser), would use C as second argument. The C method can then return zero or more values to identify the object instance. The serialiser is then supposed to encode the class name and all of these return values (which must be encodable in the format) using the relevant form for Perl objects. In CBOR for example, there is a registered tag number for encoded perl objects. The values that C returns must be serialisable with the serialiser that calls it. Therefore, it is recommended to use simple types such as strings and numbers, and maybe array references and hashes (basically, the JSON data model). You can always use a more complex format for a specific data model by checking the second argument, the data model. The "data model" is not the same as the "data format" - the data model indicates what types and kinds of return values can be returned from C. For example, in C it is permissible to return tagged CBOR values, while JSON does not support these at all, so C would be a valid (but too limited) data model name for C. similarly, a serialising format that supports more or less the same data model as JSON could use C as data model without losing anything. =head2 DECODING When the decoder then encounters such an encoded perl object, it should look up the C method on the stored classname, and invoke it with the classname, the constant string to identify the data model/data format, and all the return values returned by C. =head2 EXAMPLES See the C section in the L manpage for more details, an example implementation, and code examples. Here is an example C/C method pair: sub My::Object::FREEZE { my ($self, $model) = @_; ($self->{type}, $self->{id}, $self->{variant}) } sub My::Object::THAW { my ($class, $model, $type, $id, $variant) = @_; $class->new (type => $type, id => $id, variant => $variant) } =head1 BUGS The use of L makes this module much heavier than it should be (on my system, this module: 4kB RSS, overload: 260kB RSS). =head1 SEE ALSO Currently, L and L use these types. =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ =cut 1 perl5/Types/Serialiser/Error.pm000044400000000703152462503210012426 0ustar00=head1 NAME Types::Serialiser::Error - dummy module for Types::Serialiser =head1 SYNOPSIS # do not "use" yourself =head1 DESCRIPTION This module exists only to provide overload resolution for Storable and similar modules that assume that class name equals module name. See L for more info about this class. =cut use Types::Serialiser (); =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ =cut 1 perl5/Log/NullLogLite.pm000044400000006754152462503210011056 0ustar00package Log::NullLogLite; use strict; use vars qw($VERSION @ISA); $VERSION = 0.82; # According to the Null pattern. # # Log::NullLogLite inherits from Log::LogLite and implement the Null # Object Pattern. use Log::LogLite; @ISA = ("Log::LogLite"); package Log::NullLogLite; use strict; ########################################## # new($filepath) # new($filepath,$level) # new($filepath,$level,$default_message) ########################################## # the constructor sub new { my $proto = shift; # get the class name my $class = ref($proto) || $proto; my $self = {}; bless ($self, $class); return $self; } # of new ######################## # write($message, $level) ######################## # will log the message in the log file only if $level>=LEVEL sub write { my $self = shift; } # of write ########################## # level() # level($level) ########################## # an interface to LEVEL sub level { my $self = shift; return -1; } # of level ########################### # default_message() # default_message($message) ########################### # an interface to DEFAULT_MESSAGE sub default_message { my $self = shift; return ""; } # of default_message 1; __END__ ############################################################################ =head1 NAME Log::NullLogLite - The C class implements the Null Object pattern for the C class. =head1 SYNOPSIS use Log::NullLogLite; # create new Log::NullLogLite object my $log = new Log::NullLogLite(); ... # we had an error (this entry will not be written to the log # file because we use Log::NullLogLite object). $log->write("Could not open the file ".$file_name.": $!", 4); =head1 DESCRIPTION The C class is derived from the C class and implement the Null Object Pattern to let us to use the C class with B C objects. We might want to do that if we use a C object in our code, and we do not want always to actually define a C object (i.e. not always we want to write to a log file). In such a case we will create a C object instead of the C object, and will use that object instead. The object has all the methods that the C object has, but those methods do nothing. Thus our code will continue to run without any change, yet we will not have to define a log file path for the C object, and no log will be created. =head1 CONSTRUCTOR =over 4 =item new ( FILEPATH [,LEVEL [,DEFAULT_MESSAGE ]] ) The constructor. The parameters will not have any affect. Returns the new Log::NullLogLite object. =back =head1 METHODS =over 4 =item write( MESSAGE [, LEVEL ] ) Does nothing. The parameters will not have any affect. Returns nothing. =item level( [ LEVEL ] ) Does nothing. The parameters will not have any affect. Returns -1. =item default_message( [ MESSAGE ] ) Does nothing. The parameters will not have any affect. Returns empty string (""). =head1 AUTHOR Rani Pinchuk, rani@cpan.org =head1 COPYRIGHT Copyright (c) 2001-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, The Null Object Pattern - Bobby Woolf - PLoP96 - published in Pattern Languages of Program Design 3 (http://cseng.aw.com/book/0,,0201310112,00.html) =cut perl5/Log/LogLite.pm000044400000020542152462503210010212 0ustar00package Log::LogLite; use strict; use vars qw($VERSION); $VERSION = 0.82; use Carp; use IO::LockedFile 0.21; my $TEMPLATE = '[] <> '; my $LOG_LINE_NUMBERS = 0; # by default we do not log the line numbers ########################################## # new($filepath) # new($filepath,$level) # new($filepath,$level,$default_message) ########################################## # the constructor sub new { my $proto = shift; # get the class name my $class = ref($proto) || $proto; my $self = {}; # private data $self->{FILE_PATH} = shift; # get the file path of the config file $self->{LEVEL} = shift || 5; # the default level is 5 # report when: # 0 the application is unusable # 1 the application is going to be unusable # 2 critical conditions # 3 error conditions # 4 warning conditions # 5 normal but significant condition # 6 informational # 7+ debug-level messages $self->{DEFAULT_MESSAGE} = shift || ""; # the default message $self->{TEMPLATE} = shift || $TEMPLATE; # the template $self->{LOG_LINE_NUMBERS} = $LOG_LINE_NUMBERS; # we create IO::LockedFile object that can be locked later $self->{FH} = new IO::LockedFile({ lock => 0 }, ">>".$self->{FILE_PATH}); unless ($self->{FH}->opened) { croak("Log::LogLite: Cannot open the log file $self->{FILE_PATH}"); } bless ($self, $class); return $self; } # of new ########################## # write($message, $level) ########################## # will log the message in the log file only if $level>=LEVEL sub write { my $self = shift; my $message = shift; # get the message are informational my $level = shift || "-"; if ($level ne "-" && $level > $self->{LEVEL}) { # if the level of this message is higher # then the deafult level - do nothing return; } # lock the log file before we append $self->{FH}->lock(); # parse the template my $line = $self->{TEMPLATE}; $line =~ s!!date_string()!igoe; $line =~ s!!$level!igo; $line =~ s!!$self->called_by()!igoe; $line =~ s!!$self->{DEFAULT_MESSAGE}!igo; $line =~ s!!$message!igo; print {$self->{FH}} $line; # unlock the file $self->{FH}->unlock(); } # of write ########################## # template() # template($template) ########################## sub template { my $self = shift; if (@_) { $self->{TEMPLATE} = shift } return $self->{TEMPLATE}; } # of template ########################## # level() # level($level) ########################## # an interface to LEVEL sub level { my $self = shift; if (@_) { $self->{LEVEL} = shift } return $self->{LEVEL}; } # of level ########################### # default_message() # default_message($message) ########################### # an interface to DEFAULT_MESSAGE sub default_message { my $self = shift; if (@_) { $self->{DEFAULT_MESSAGE} = shift } return $self->{DEFAULT_MESSAGE}; } # of default_message ########################## # log_line_numbers() # log_line_numbers($log_line_numbers) ########################## # an interface to LOG_LINE_NUMBERS sub log_line_numbers { my $self = shift; if (@_) { $self->{LOG_LINE_NUMBERS} = shift } return $self->{LOG_LINE_NUMBERS}; } # of log_line_numbers ####################### # date_string() ####################### sub date_string { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # note that there is no Y2K bug here. see localtime in perlfunc. return sprintf("%02d/%02d/%04d %02d:%02d:%02d", $mday, $mon + 1, $year + 1900, $hour, $min, $sec); } # of date_string ####################### # called_by ####################### sub called_by { my $self = shift; my $depth = 2; my $args; my $pack; my $file; my $line; my $subr; my $has_args; my $wantarray; my $evaltext; my $is_require; my $hints; my $bitmask; my @subr; my $str = ""; while (1) { ($pack, $file, $line, $subr, $has_args, $wantarray, $evaltext, $is_require, $hints, $bitmask) = caller($depth); unless (defined($subr)) { last; } $depth++; $line = ($self->{LOG_LINE_NUMBERS}) ? "$file:".$line."-->" : ""; push(@subr, $line.$subr); } @subr = reverse(@subr); foreach $subr (@subr) { $str .= $subr; $str .= " > "; } $str =~ s/ > $/: /; return $str; } # of called_by 1; __END__ ############################################################################ =head1 NAME Log::LogLite - The C class helps us create simple logs for our application. =head1 SYNOPSIS use Log::LogLite; my $LOG_DIRECTORY = "/where/ever/our/log/file/should/be"; my $ERROR_LOG_LEVEL = 6; # create new Log::LogLite object my $log = new Log::LogLite($LOG_DIRECTORY."/error.log", $ERROR_LOG_LEVEL); ... # we had an error $log->write("Could not open the file ".$file_name.": $!", 4); =head1 DESCRIPTION In order to have a log we have first to create a C object. The c object is created with a logging level. The default logging level is 5. After the C object is created, each call to the C method may write a new line in the log file. If the level of the message is lower or equal to the logging level, the message will be written to the log file. The format of the logging messages can be controled by changing the template, and by defining a default message. The class uses the IO::LockedFile class. =head1 CONSTRUCTOR =over 4 =item new ( FILEPATH [,LEVEL [,DEFAULT_MESSAGE ]] ) The constructor. FILEPATH is the path of the log file. LEVEL is the defined logging level - the LEVEL data member. DEFAULT_MESSAGE will define the DEFAULT_MESSAGE data member - a message that will be added to the message of each entry in the log (according to the TEMPLATE data member, see below). The levels can be any levels that the user chooses to use. There are, though, recommended levels: 0 the application is unusable 1 the application is going to be unusable 2 critical conditions 3 error conditions 4 warning conditions 5 normal but significant condition 6 informational 7+ debug-level messages The default value of LEVEL is 5. The default value of DEFAULT_MESSAGE is "". Returns the new object. =back =head1 METHODS =over 4 =item write( MESSAGE [, LEVEL ] ) If LEVEL is less or equal to the LEVEL data member, or if LEVEL is undefined, the string in MESSAGE will be written to the log file. Does not return anything. =item level( [ LEVEL ] ) Access method to the LEVEL data member. If LEVEL is defined, the LEVEL data member will get its value. Returns the value of the LEVEL data member. =item default_message( [ MESSAGE ] ) Access method to the DEFAULT_MESSAGE data member. If MESSAGE is defined, the DEFAULT_MESSAGE data member will get its value. Returns the value of the DEFAULT_MESSAGE data member. =item log_line_numbers( [ BOOLEAN ] ) If this flag is set to true, the string will hold the file that calls the subroutine and the line where the call is issued. The default value is zero. =item template( [ TEMPLATE ] ) Access method to the TEMPLATE data member. The TEMPLATE data member is a string that defines how the log entries will look like. The default TEMPLATE is: '[] <> ' Where: will be replaced by a string that represent the date. For example: 09/01/2000 17:00:13 will be replaced by the level of the entry. will be replaced by a call trace string. For example: CGIDaemon::listen > MyCGIDaemon::accepted will be replaced by the value of the DEFAULT_MESSAGE data member. will be replaced by the message string that is sent to the C method. Returns the value of the TEMPLATE data member. =head1 AUTHOR Rani Pinchuk, rani@cpan.org =head1 COPYRIGHT Copyright (c) 2001-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =cut perl5/Net/HTTP.pm000044400000023621152462503210007440 0ustar00package Net::HTTP; our $VERSION = '6.21'; use strict; use warnings; our $SOCKET_CLASS; unless ($SOCKET_CLASS) { # Try several, in order of capability and preference if (eval { require IO::Socket::IP }) { $SOCKET_CLASS = "IO::Socket::IP"; # IPv4+IPv6 } elsif (eval { require IO::Socket::INET6 }) { $SOCKET_CLASS = "IO::Socket::INET6"; # IPv4+IPv6 } elsif (eval { require IO::Socket::INET }) { $SOCKET_CLASS = "IO::Socket::INET"; # IPv4 only } else { require IO::Socket; $SOCKET_CLASS = "IO::Socket::INET"; } } require Net::HTTP::Methods; require Carp; our @ISA = ($SOCKET_CLASS, 'Net::HTTP::Methods'); sub new { my $class = shift; Carp::croak("No Host option provided") unless @_; $class->SUPER::new(@_); } sub configure { my($self, $cnf) = @_; $self->http_configure($cnf); } sub http_connect { my($self, $cnf) = @_; $self->SUPER::configure($cnf); } 1; =pod =encoding UTF-8 =head1 NAME Net::HTTP - Low-level HTTP connection (client) =head1 VERSION version 6.21 =head1 SYNOPSIS use Net::HTTP; my $s = Net::HTTP->new(Host => "www.perl.com") || die $@; $s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0"); my($code, $mess, %h) = $s->read_response_headers; while (1) { my $buf; my $n = $s->read_entity_body($buf, 1024); die "read failed: $!" unless defined $n; last unless $n; print $buf; } =head1 DESCRIPTION The C class is a low-level HTTP client. An instance of the C class represents a connection to an HTTP server. The HTTP protocol is described in RFC 2616. The C class supports C and C. C is a sub-class of one of C (IPv6+IPv4), C (IPv6+IPv4), or C (IPv4 only). You can mix the methods described below with reading and writing from the socket directly. This is not necessary a good idea, unless you know what you are doing. The following methods are provided (in addition to those of C): =over =item $s = Net::HTTP->new( %options ) The C constructor method takes the same options as C's as well as these: Host: Initial host attribute value KeepAlive: Initial keep_alive attribute value SendTE: Initial send_te attribute_value HTTPVersion: Initial http_version attribute value PeerHTTPVersion: Initial peer_http_version attribute value MaxLineLength: Initial max_line_length attribute value MaxHeaderLines: Initial max_header_lines attribute value The C option is also the default for C's C. The C defaults to 80 if not provided. The C specification can also be embedded in the C by preceding it with a ":", and closing the IPv6 address on brackets "[]" if necessary: "192.0.2.1:80","[2001:db8::1]:80","any.example.com:80". The C option provided by C's constructor method is not allowed. If unable to connect to the given HTTP server then the constructor returns C and $@ contains the reason. After a successful connect, a C object is returned. =item $s->host Get/set the default value of the C header to send. The $host must not be set to an empty string (or C) for HTTP/1.1. =item $s->keep_alive Get/set the I value. If this value is TRUE then the request will be sent with headers indicating that the server should try to keep the connection open so that multiple requests can be sent. The actual headers set will depend on the value of the C and C attributes. =item $s->send_te Get/set the a value indicating if the request will be sent with a "TE" header to indicate the transfer encodings that the server can choose to use. The list of encodings announced as accepted by this client depends on availability of the following modules: C for I, and C for I. =item $s->http_version Get/set the HTTP version number that this client should announce. This value can only be set to "1.0" or "1.1". The default is "1.1". =item $s->peer_http_version Get/set the protocol version number of our peer. This value will initially be "1.0", but will be updated by a successful read_response_headers() method call. =item $s->max_line_length Get/set a limit on the length of response line and response header lines. The default is 8192. A value of 0 means no limit. =item $s->max_header_length Get/set a limit on the number of header lines that a response can have. The default is 128. A value of 0 means no limit. =item $s->format_request($method, $uri, %headers, [$content]) Format a request message and return it as a string. If the headers do not include a C header, then a header is inserted with the value of the C attribute. Headers like C and C might also be added depending on the status of the C attribute. If $content is given (and it is non-empty), then a C header is automatically added unless it was already present. =item $s->write_request($method, $uri, %headers, [$content]) Format and send a request message. Arguments are the same as for format_request(). Returns true if successful. =item $s->format_chunk( $data ) Returns the string to be written for the given chunk of data. =item $s->write_chunk($data) Will write a new chunk of request entity body data. This method should only be used if the C header with a value of C was sent in the request. Note, writing zero-length data is a no-op. Use the write_chunk_eof() method to signal end of entity body data. Returns true if successful. =item $s->format_chunk_eof( %trailers ) Returns the string to be written for signaling EOF when a C of C is used. =item $s->write_chunk_eof( %trailers ) Will write eof marker for chunked data and optional trailers. Note that trailers should not really be used unless is was signaled with a C header. Returns true if successful. =item ($code, $mess, %headers) = $s->read_response_headers( %opts ) Read response headers from server and return it. The $code is the 3 digit HTTP status code (see L) and $mess is the textual message that came with it. Headers are then returned as key/value pairs. Since key letter casing is not normalized and the same key can even occur multiple times, assigning these values directly to a hash is not wise. Only the $code is returned if this method is called in scalar context. As a side effect this method updates the 'peer_http_version' attribute. Options might be passed in as key/value pairs. There are currently only two options supported; C and C. The C option will make read_response_headers() more forgiving towards servers that have not learned how to speak HTTP properly. The C option is a boolean flag, and is enabled by passing in a TRUE value. The C option can be used to capture bad header lines when C is enabled. The value should be an array reference. Bad header lines will be pushed onto the array. The C option must be specified in order to communicate with pre-HTTP/1.0 servers that don't describe the response outcome or the data they send back with a header block. For these servers peer_http_version is set to "0.9" and this method returns (200, "Assumed OK"). The method will raise an exception (die) if the server does not speak proper HTTP or if the C or C limits are reached. If the C option is turned on and C and C checks are turned off, then no exception will be raised and this method will always return a response code. =item $n = $s->read_entity_body($buf, $size); Reads chunks of the entity body content. Basically the same interface as for read() and sysread(), but the buffer offset argument is not supported yet. This method should only be called after a successful read_response_headers() call. The return value will be C on read errors, 0 on EOF, -1 if no data could be returned this time, otherwise the number of bytes assigned to $buf. The $buf is set to "" when the return value is -1. You normally want to retry this call if this function returns either -1 or C with C<$!> as EINTR or EAGAIN (see L). EINTR can happen if the application catches signals and EAGAIN can happen if you made the socket non-blocking. This method will raise exceptions (die) if the server does not speak proper HTTP. This can only happen when reading chunked data. =item %headers = $s->get_trailers After read_entity_body() has returned 0 to indicate end of the entity body, you might call this method to pick up any trailers. =item $s->_rbuf Get/set the read buffer content. The read_response_headers() and read_entity_body() methods use an internal buffer which they will look for data before they actually sysread more from the socket itself. If they read too much, the remaining data will be left in this buffer. =item $s->_rbuf_length Returns the number of bytes in the read buffer. This should always be the same as: length($s->_rbuf) but might be more efficient. =back =head1 SUBCLASSING The read_response_headers() and read_entity_body() will invoke the sysread() method when they need more data. Subclasses might want to override this method to control how reading takes place. The object itself is a glob. Subclasses should avoid using hash key names prefixed with C and C. =head1 SEE ALSO L, L, L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # ABSTRACT: Low-level HTTP connection (client) perl5/Net/HTTP/NB.pm000044400000004731152462503210007740 0ustar00package Net::HTTP::NB; our $VERSION = '6.21'; use strict; use warnings; use base 'Net::HTTP'; sub can_read { return 1; } sub sysread { my $self = $_[0]; if (${*$self}{'httpnb_read_count'}++) { ${*$self}{'http_buf'} = ${*$self}{'httpnb_save'}; die "Multi-read\n"; } my $buf; my $offset = $_[3] || 0; my $n = sysread($self, $_[1], $_[2], $offset); ${*$self}{'httpnb_save'} .= substr($_[1], $offset); return $n; } sub read_response_headers { my $self = shift; ${*$self}{'httpnb_read_count'} = 0; ${*$self}{'httpnb_save'} = ${*$self}{'http_buf'}; my @h = eval { $self->SUPER::read_response_headers(@_) }; if ($@) { return if $@ eq "Multi-read\n"; die; } return @h; } sub read_entity_body { my $self = shift; ${*$self}{'httpnb_read_count'} = 0; ${*$self}{'httpnb_save'} = ${*$self}{'http_buf'}; # XXX I'm not so sure this does the correct thing in case of # transfer-encoding transforms my $n = eval { $self->SUPER::read_entity_body(@_); }; if ($@) { $_[0] = ""; return -1; } return $n; } 1; =pod =encoding UTF-8 =head1 NAME Net::HTTP::NB - Non-blocking HTTP client =head1 VERSION version 6.21 =head1 SYNOPSIS use Net::HTTP::NB; my $s = Net::HTTP::NB->new(Host => "www.perl.com") || die $@; $s->write_request(GET => "/"); use IO::Select; my $sel = IO::Select->new($s); READ_HEADER: { die "Header timeout" unless $sel->can_read(10); my($code, $mess, %h) = $s->read_response_headers; redo READ_HEADER unless $code; } while (1) { die "Body timeout" unless $sel->can_read(10); my $buf; my $n = $s->read_entity_body($buf, 1024); last unless $n; print $buf; } =head1 DESCRIPTION Same interface as C but it will never try multiple reads when the read_response_headers() or read_entity_body() methods are invoked. This make it possible to multiplex multiple Net::HTTP::NB using select without risk blocking. If read_response_headers() did not see enough data to complete the headers an empty list is returned. If read_entity_body() did not see new entity data in its read the value -1 is returned. =head1 SEE ALSO L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Non-blocking HTTP client perl5/Net/HTTP/Methods.pm000044400000042133152462503210011042 0ustar00package Net::HTTP::Methods; our $VERSION = '6.21'; use strict; use warnings; use URI; my $CRLF = "\015\012"; # "\r\n" is not portable *_bytes = defined(&utf8::downgrade) ? sub { unless (utf8::downgrade($_[0], 1)) { require Carp; Carp::croak("Wide character in HTTP request (bytes required)"); } return $_[0]; } : sub { return $_[0]; }; sub new { my $class = shift; unshift(@_, "Host") if @_ == 1; my %cnf = @_; require Symbol; my $self = bless Symbol::gensym(), $class; return $self->http_configure(\%cnf); } sub http_configure { my($self, $cnf) = @_; die "Listen option not allowed" if $cnf->{Listen}; my $explicit_host = (exists $cnf->{Host}); my $host = delete $cnf->{Host}; # All this because $cnf->{PeerAddr} = 0 is actually valid. my $peer; for my $key (qw{PeerAddr PeerHost}) { next if !defined($cnf->{$key}) || q{} eq $cnf->{$key}; $peer = $cnf->{$key}; last; } if (!defined $peer) { die "No Host option provided" unless $host; $cnf->{PeerAddr} = $peer = $host; } # CONNECTIONS # PREFER: port number from PeerAddr, then PeerPort, then http_default_port my $peer_uri = URI->new("http://$peer"); $cnf->{"PeerPort"} = $peer_uri->_port || $cnf->{PeerPort} || $self->http_default_port; $cnf->{"PeerAddr"} = $peer_uri->host; # HOST header: # If specified but blank, ignore. # If specified with a value, add the port number # If not specified, set to PeerAddr and port number # ALWAYS: If IPv6 address, use [brackets] (thanks to the URI package) # ALWAYS: omit port number if http_default_port if (($host) || (! $explicit_host)) { my $uri = ($explicit_host) ? URI->new("http://$host") : $peer_uri->clone; if (!$uri->_port) { # Always use *our* $self->http_default_port instead of URI's (Covers HTTP, HTTPS) $uri->port( $cnf->{PeerPort} || $self->http_default_port); } my $host_port = $uri->host_port; # Returns host:port or [ipv6]:port my $remove = ":" . $self->http_default_port; # we want to remove the default port number if (substr($host_port,0-length($remove)) eq $remove) { substr($host_port,0-length($remove)) = ""; } $host = $host_port; } $cnf->{Proto} = 'tcp'; my $keep_alive = delete $cnf->{KeepAlive}; my $http_version = delete $cnf->{HTTPVersion}; $http_version = "1.1" unless defined $http_version; my $peer_http_version = delete $cnf->{PeerHTTPVersion}; $peer_http_version = "1.0" unless defined $peer_http_version; my $send_te = delete $cnf->{SendTE}; my $max_line_length = delete $cnf->{MaxLineLength}; $max_line_length = 8*1024 unless defined $max_line_length; my $max_header_lines = delete $cnf->{MaxHeaderLines}; $max_header_lines = 128 unless defined $max_header_lines; return undef unless $self->http_connect($cnf); $self->host($host); $self->keep_alive($keep_alive); $self->send_te($send_te); $self->http_version($http_version); $self->peer_http_version($peer_http_version); $self->max_line_length($max_line_length); $self->max_header_lines($max_header_lines); ${*$self}{'http_buf'} = ""; return $self; } sub http_default_port { 80; } # set up property accessors for my $method (qw(host keep_alive send_te max_line_length max_header_lines peer_http_version)) { my $prop_name = "http_" . $method; no strict 'refs'; *$method = sub { my $self = shift; my $old = ${*$self}{$prop_name}; ${*$self}{$prop_name} = shift if @_; return $old; }; } # we want this one to be a bit smarter sub http_version { my $self = shift; my $old = ${*$self}{'http_version'}; if (@_) { my $v = shift; $v = "1.0" if $v eq "1"; # float unless ($v eq "1.0" or $v eq "1.1") { require Carp; Carp::croak("Unsupported HTTP version '$v'"); } ${*$self}{'http_version'} = $v; } $old; } sub format_request { my $self = shift; my $method = shift; my $uri = shift; my $content = (@_ % 2) ? pop : ""; for ($method, $uri) { require Carp; Carp::croak("Bad method or uri") if /\s/ || !length; } push(@{${*$self}{'http_request_method'}}, $method); my $ver = ${*$self}{'http_version'}; my $peer_ver = ${*$self}{'http_peer_http_version'} || "1.0"; my @h; my @connection; my %given = (host => 0, "content-length" => 0, "te" => 0); while (@_) { my($k, $v) = splice(@_, 0, 2); my $lc_k = lc($k); if ($lc_k eq "connection") { $v =~ s/^\s+//; $v =~ s/\s+$//; push(@connection, split(/\s*,\s*/, $v)); next; } if (exists $given{$lc_k}) { $given{$lc_k}++; } push(@h, "$k: $v"); } if (length($content) && !$given{'content-length'}) { push(@h, "Content-Length: " . length($content)); } my @h2; if ($given{te}) { push(@connection, "TE") unless grep lc($_) eq "te", @connection; } elsif ($self->send_te && gunzip_ok()) { # gzip is less wanted since the IO::Uncompress::Gunzip interface for # it does not really allow chunked decoding to take place easily. push(@h2, "TE: deflate,gzip;q=0.3"); push(@connection, "TE"); } unless (grep lc($_) eq "close", @connection) { if ($self->keep_alive) { if ($peer_ver eq "1.0") { # from looking at Netscape's headers push(@h2, "Keep-Alive: 300"); unshift(@connection, "Keep-Alive"); } } else { push(@connection, "close") if $ver ge "1.1"; } } push(@h2, "Connection: " . join(", ", @connection)) if @connection; unless ($given{host}) { my $h = ${*$self}{'http_host'}; push(@h2, "Host: $h") if $h; } return _bytes(join($CRLF, "$method $uri HTTP/$ver", @h2, @h, "", $content)); } sub write_request { my $self = shift; $self->print($self->format_request(@_)); } sub format_chunk { my $self = shift; return $_[0] unless defined($_[0]) && length($_[0]); return _bytes(sprintf("%x", length($_[0])) . $CRLF . $_[0] . $CRLF); } sub write_chunk { my $self = shift; return 1 unless defined($_[0]) && length($_[0]); $self->print(_bytes(sprintf("%x", length($_[0])) . $CRLF . $_[0] . $CRLF)); } sub format_chunk_eof { my $self = shift; my @h; while (@_) { push(@h, sprintf "%s: %s$CRLF", splice(@_, 0, 2)); } return _bytes(join("", "0$CRLF", @h, $CRLF)); } sub write_chunk_eof { my $self = shift; $self->print($self->format_chunk_eof(@_)); } sub my_read { die if @_ > 3; my $self = shift; my $len = $_[1]; for (${*$self}{'http_buf'}) { if (length) { $_[0] = substr($_, 0, $len, ""); return length($_[0]); } else { die "read timeout" unless $self->can_read; return $self->sysread($_[0], $len); } } } sub my_readline { my $self = shift; my $what = shift; for (${*$self}{'http_buf'}) { my $max_line_length = ${*$self}{'http_max_line_length'}; my $pos; while (1) { # find line ending $pos = index($_, "\012"); last if $pos >= 0; die "$what line too long (limit is $max_line_length)" if $max_line_length && length($_) > $max_line_length; # need to read more data to find a line ending my $new_bytes = 0; READ: { # wait until bytes start arriving $self->can_read or die "read timeout"; # consume all incoming bytes my $bytes_read = $self->sysread($_, 1024, length); if(defined $bytes_read) { $new_bytes += $bytes_read; } elsif($!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK}) { redo READ; } else { # if we have already accumulated some data let's at # least return that as a line length or die "$what read failed: $!"; } # no line-ending, no new bytes return length($_) ? substr($_, 0, length($_), "") : undef if $new_bytes==0; } } die "$what line too long ($pos; limit is $max_line_length)" if $max_line_length && $pos > $max_line_length; my $line = substr($_, 0, $pos+1, ""); $line =~ s/(\015?\012)\z// || die "Assert"; return wantarray ? ($line, $1) : $line; } } sub can_read { my $self = shift; return 1 unless defined(fileno($self)); return 1 if $self->isa('IO::Socket::SSL') && $self->pending; return 1 if $self->isa('Net::SSL') && $self->can('pending') && $self->pending; # With no timeout, wait forever. An explicit timeout of 0 can be # used to just check if the socket is readable without waiting. my $timeout = @_ ? shift : (${*$self}{io_socket_timeout} || undef); my $fbits = ''; vec($fbits, fileno($self), 1) = 1; SELECT: { my $before; $before = time if $timeout; my $nfound = select($fbits, undef, undef, $timeout); if ($nfound < 0) { if ($!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK}) { # don't really think EAGAIN/EWOULDBLOCK can happen here if ($timeout) { $timeout -= time - $before; $timeout = 0 if $timeout < 0; } redo SELECT; } die "select failed: $!"; } return $nfound > 0; } } sub _rbuf { my $self = shift; if (@_) { for (${*$self}{'http_buf'}) { my $old; $old = $_ if defined wantarray; $_ = shift; return $old; } } else { return ${*$self}{'http_buf'}; } } sub _rbuf_length { my $self = shift; return length ${*$self}{'http_buf'}; } sub _read_header_lines { my $self = shift; my $junk_out = shift; my @headers; my $line_count = 0; my $max_header_lines = ${*$self}{'http_max_header_lines'}; while (my $line = my_readline($self, 'Header')) { if ($line =~ /^(\S+?)\s*:\s*(.*)/s) { push(@headers, $1, $2); } elsif (@headers && $line =~ s/^\s+//) { $headers[-1] .= " " . $line; } elsif ($junk_out) { push(@$junk_out, $line); } else { die "Bad header: '$line'\n"; } if ($max_header_lines) { $line_count++; if ($line_count >= $max_header_lines) { die "Too many header lines (limit is $max_header_lines)"; } } } return @headers; } sub read_response_headers { my($self, %opt) = @_; my $laxed = $opt{laxed}; my($status, $eol) = my_readline($self, 'Status'); unless (defined $status) { die "Server closed connection without sending any data back"; } my($peer_ver, $code, $message) = split(/\s+/, $status, 3); if (!$peer_ver || $peer_ver !~ s,^HTTP/,, || $code !~ /^[1-5]\d\d$/) { die "Bad response status line: '$status'" unless $laxed; # assume HTTP/0.9 ${*$self}{'http_peer_http_version'} = "0.9"; ${*$self}{'http_status'} = "200"; substr(${*$self}{'http_buf'}, 0, 0) = $status . ($eol || ""); return 200 unless wantarray; return (200, "Assumed OK"); }; ${*$self}{'http_peer_http_version'} = $peer_ver; ${*$self}{'http_status'} = $code; my $junk_out; if ($laxed) { $junk_out = $opt{junk_out} || []; } my @headers = $self->_read_header_lines($junk_out); # pick out headers that read_entity_body might need my @te; my $content_length; for (my $i = 0; $i < @headers; $i += 2) { my $h = lc($headers[$i]); if ($h eq 'transfer-encoding') { my $te = $headers[$i+1]; $te =~ s/^\s+//; $te =~ s/\s+$//; push(@te, $te) if length($te); } elsif ($h eq 'content-length') { # ignore bogus and overflow values if ($headers[$i+1] =~ /^\s*(\d{1,15})(?:\s|$)/) { $content_length = $1; } } } ${*$self}{'http_te'} = join(",", @te); ${*$self}{'http_content_length'} = $content_length; ${*$self}{'http_first_body'}++; delete ${*$self}{'http_trailers'}; return $code unless wantarray; return ($code, $message, @headers); } sub read_entity_body { my $self = shift; my $buf_ref = \$_[0]; my $size = $_[1]; die "Offset not supported yet" if $_[2]; my $chunked; my $bytes; if (${*$self}{'http_first_body'}) { ${*$self}{'http_first_body'} = 0; delete ${*$self}{'http_chunked'}; delete ${*$self}{'http_bytes'}; my $method = shift(@{${*$self}{'http_request_method'}}); my $status = ${*$self}{'http_status'}; if ($method eq "HEAD") { # this response is always empty regardless of other headers $bytes = 0; } elsif (my $te = ${*$self}{'http_te'}) { my @te = split(/\s*,\s*/, lc($te)); die "Chunked must be last Transfer-Encoding '$te'" unless pop(@te) eq "chunked"; pop(@te) while @te && $te[-1] eq "chunked"; # ignore repeated chunked spec for (@te) { if ($_ eq "deflate" && inflate_ok()) { #require Compress::Raw::Zlib; my ($i, $status) = Compress::Raw::Zlib::Inflate->new(); die "Can't make inflator: $status" unless $i; $_ = sub { my $out; $i->inflate($_[0], \$out); $out } } elsif ($_ eq "gzip" && gunzip_ok()) { #require IO::Uncompress::Gunzip; my @buf; $_ = sub { push(@buf, $_[0]); return "" unless $_[1]; my $input = join("", @buf); my $output; IO::Uncompress::Gunzip::gunzip(\$input, \$output, Transparent => 0) or die "Can't gunzip content: $IO::Uncompress::Gunzip::GunzipError"; return \$output; }; } elsif ($_ eq "identity") { $_ = sub { $_[0] }; } else { die "Can't handle transfer encoding '$te'"; } } @te = reverse(@te); ${*$self}{'http_te2'} = @te ? \@te : ""; $chunked = -1; } elsif (defined(my $content_length = ${*$self}{'http_content_length'})) { $bytes = $content_length; } elsif ($status =~ /^(?:1|[23]04)/) { # RFC 2616 says that these responses should always be empty # but that does not appear to be true in practice [RT#17907] $bytes = 0; } else { # XXX Multi-Part types are self delimiting, but RFC 2616 says we # only has to deal with 'multipart/byteranges' # Read until EOF } } else { $chunked = ${*$self}{'http_chunked'}; $bytes = ${*$self}{'http_bytes'}; } if (defined $chunked) { # The state encoded in $chunked is: # $chunked == 0: read CRLF after chunk, then chunk header # $chunked == -1: read chunk header # $chunked > 0: bytes left in current chunk to read if ($chunked <= 0) { my $line = my_readline($self, 'Entity body'); if ($chunked == 0) { die "Missing newline after chunk data: '$line'" if !defined($line) || $line ne ""; $line = my_readline($self, 'Entity body'); } die "EOF when chunk header expected" unless defined($line); my $chunk_len = $line; $chunk_len =~ s/;.*//; # ignore potential chunk parameters unless ($chunk_len =~ /^([\da-fA-F]+)\s*$/) { die "Bad chunk-size in HTTP response: $line"; } $chunked = hex($1); ${*$self}{'http_chunked'} = $chunked; if ($chunked == 0) { ${*$self}{'http_trailers'} = [$self->_read_header_lines]; $$buf_ref = ""; my $n = 0; if (my $transforms = delete ${*$self}{'http_te2'}) { for (@$transforms) { $$buf_ref = &$_($$buf_ref, 1); } $n = length($$buf_ref); } # in case somebody tries to read more, make sure we continue # to return EOF delete ${*$self}{'http_chunked'}; ${*$self}{'http_bytes'} = 0; return $n; } } my $n = $chunked; $n = $size if $size && $size < $n; $n = my_read($self, $$buf_ref, $n); return undef unless defined $n; ${*$self}{'http_chunked'} = $chunked - $n; if ($n > 0) { if (my $transforms = ${*$self}{'http_te2'}) { for (@$transforms) { $$buf_ref = &$_($$buf_ref, 0); } $n = length($$buf_ref); $n = -1 if $n == 0; } } return $n; } elsif (defined $bytes) { unless ($bytes) { $$buf_ref = ""; return 0; } my $n = $bytes; $n = $size if $size && $size < $n; $n = my_read($self, $$buf_ref, $n); ${*$self}{'http_bytes'} = defined $n ? $bytes - $n : $bytes; return $n; } else { # read until eof $size ||= 8*1024; return my_read($self, $$buf_ref, $size); } } sub get_trailers { my $self = shift; @{${*$self}{'http_trailers'} || []}; } BEGIN { my $gunzip_ok; my $inflate_ok; sub gunzip_ok { return $gunzip_ok if defined $gunzip_ok; # Try to load IO::Uncompress::Gunzip. local $@; local $SIG{__DIE__}; $gunzip_ok = 0; eval { require IO::Uncompress::Gunzip; $gunzip_ok++; }; return $gunzip_ok; } sub inflate_ok { return $inflate_ok if defined $inflate_ok; # Try to load Compress::Raw::Zlib. local $@; local $SIG{__DIE__}; $inflate_ok = 0; eval { require Compress::Raw::Zlib; $inflate_ok++; }; return $inflate_ok; } } # BEGIN 1; =pod =encoding UTF-8 =head1 NAME Net::HTTP::Methods - Methods shared by Net::HTTP and Net::HTTPS =head1 VERSION version 6.21 =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # ABSTRACT: Methods shared by Net::HTTP and Net::HTTPS perl5/Net/HTTPS.pm000044400000006716152462503210007571 0ustar00package Net::HTTPS; our $VERSION = '6.21'; use strict; use warnings; # Figure out which SSL implementation to use our $SSL_SOCKET_CLASS; if ($SSL_SOCKET_CLASS) { # somebody already set it } elsif ($SSL_SOCKET_CLASS = $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}) { unless ($SSL_SOCKET_CLASS =~ /^(IO::Socket::SSL|Net::SSL)\z/) { die "Bad socket class [$SSL_SOCKET_CLASS]"; } eval "require $SSL_SOCKET_CLASS"; die $@ if $@; } elsif ($IO::Socket::SSL::VERSION) { $SSL_SOCKET_CLASS = "IO::Socket::SSL"; # it was already loaded } elsif ($Net::SSL::VERSION) { $SSL_SOCKET_CLASS = "Net::SSL"; } else { eval { require IO::Socket::SSL; }; if ($@) { my $old_errsv = $@; eval { require Net::SSL; # from Crypt-SSLeay }; if ($@) { $old_errsv =~ s/\s\(\@INC contains:.*\)/)/g; die $old_errsv . $@; } $SSL_SOCKET_CLASS = "Net::SSL"; } else { $SSL_SOCKET_CLASS = "IO::Socket::SSL"; } } require Net::HTTP::Methods; our @ISA=($SSL_SOCKET_CLASS, 'Net::HTTP::Methods'); sub configure { my($self, $cnf) = @_; $self->http_configure($cnf); } sub http_connect { my($self, $cnf) = @_; if ($self->isa("Net::SSL")) { if ($cnf->{SSL_verify_mode}) { if (my $f = $cnf->{SSL_ca_file}) { $ENV{HTTPS_CA_FILE} = $f; } if (my $f = $cnf->{SSL_ca_path}) { $ENV{HTTPS_CA_DIR} = $f; } } if ($cnf->{SSL_verifycn_scheme}) { $@ = "Net::SSL from Crypt-SSLeay can't verify hostnames; either install IO::Socket::SSL or turn off verification by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0"; return undef; } } $self->SUPER::configure($cnf); } sub http_default_port { 443; } if ($SSL_SOCKET_CLASS eq "Net::SSL") { # The underlying SSLeay classes fails to work if the socket is # placed in non-blocking mode. This override of the blocking # method makes sure it stays the way it was created. *blocking = sub { }; } 1; =pod =encoding UTF-8 =head1 NAME Net::HTTPS - Low-level HTTP over SSL/TLS connection (client) =head1 VERSION version 6.21 =head1 DESCRIPTION The C is a low-level HTTP over SSL/TLS client. The interface is the same as the interface for C, but the constructor takes additional parameters as accepted by L. The C object is an C too, which makes it inherit additional methods from that base class. For historical reasons this module also supports using C (from the Crypt-SSLeay distribution) as its SSL driver and base class. This base is automatically selected if available and C isn't. You might also force which implementation to use by setting $Net::HTTPS::SSL_SOCKET_CLASS before loading this module. If not set this variable is initialized from the C environment variable. =head1 ENVIRONMENT You might set the C environment variable to the name of the base SSL implementation (and Net::HTTPS base class) to use. The default is C. Currently the only other supported value is C. =head1 SEE ALSO L, L =head1 AUTHOR Gisle Aas =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001-2017 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Low-level HTTP over SSL/TLS connection (client) perl5/Devel/CheckLib.pm000044400000046277152462503210010652 0ustar00# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $ package Devel::CheckLib; use 5.00405; #postfix foreach use strict; use vars qw($VERSION @ISA @EXPORT); $VERSION = '1.14'; use Config qw(%Config); use Text::ParseWords 'quotewords'; use File::Spec; use File::Temp; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(assert_lib check_lib_or_exit check_lib); # localising prevents the warningness leaking out of this module local $^W = 1; # use warnings is a 5.6-ism _findcc(); # bomb out early if there's no compiler =head1 NAME Devel::CheckLib - check that a library is available =head1 DESCRIPTION Devel::CheckLib is a perl module that checks whether a particular C library and its headers are available. =head1 SYNOPSIS use Devel::CheckLib; check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' ); check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] ); # or prompt for path to library and then do this: check_lib_or_exit( lib => 'jpeg', libpath => $additional_path ); =head1 USING IT IN Makefile.PL or Build.PL If you want to use this from Makefile.PL or Build.PL, do not simply copy the module into your distribution as this may cause problems when PAUSE and search.cpan.org index the distro. Instead, use the use-devel-checklib script. =head1 HOW IT WORKS You pass named parameters to a function, describing to it how to build and link to the libraries. It works by trying to compile some code - which defaults to this: int main(int argc, char *argv[]) { return 0; } and linking it to the specified libraries. If something pops out the end which looks executable, it gets executed, and if main() returns 0 we know that it worked. That tiny program is built once for each library that you specify, and (without linking) once for each header file. If you want to check for the presence of particular functions in a library, or even that those functions return particular results, then you can pass your own function body for main() thus: check_lib_or_exit( function => 'foo();if(libversion() > 5) return 0; else return 1;' incpath => ... libpath => ... lib => ... header => ... ); In that case, it will fail to build if either foo() or libversion() don't exist, and main() will return the wrong value if libversion()'s return value isn't what you want. =head1 FUNCTIONS All of these take the same named parameters and are exported by default. To avoid exporting them, C. =head2 assert_lib This takes several named parameters, all of which are optional, and dies with an error message if any of the libraries listed can not be found. B: dying in a Makefile.PL or Build.PL may provoke a 'FAIL' report from CPAN Testers' automated smoke testers. Use C instead. The named parameters are: =over =item lib Must be either a string with the name of a single library or a reference to an array of strings of library names. Depending on the compiler found, library names will be fed to the compiler either as C<-l> arguments or as C<.lib> file names. (E.g. C<-ljpeg> or C) =item libpath a string or an array of strings representing additional paths to search for libraries. =item LIBS a C-style space-separated list of libraries (each preceded by '-l') and directories (preceded by '-L'). This can also be supplied on the command-line. =item debug If true - emit information during processing that can be used for debugging. =back And libraries are no use without header files, so ... =over =item header Must be either a string with the name of a single header file or a reference to an array of strings of header file names. =item incpath a string or an array of strings representing additional paths to search for headers. =item INC a C-style space-separated list of incpaths, each preceded by '-I'. This can also be supplied on the command-line. =item ccflags Extra flags to pass to the compiler. =item ldflags Extra flags to pass to the linker. =item analyze_binary a callback function that will be invoked in order to perform custom analysis of the generated binary. The callback arguments are the library name and the path to the binary just compiled. It is possible to use this callback, for instance, to inspect the binary for further dependencies. =item not_execute Do not try to execute generated binary. Only check that compilation has not failed. =back =head2 check_lib_or_exit This behaves exactly the same as C except that instead of dieing, it warns (with exactly the same error message) and exits. This is intended for use in Makefile.PL / Build.PL when you might want to prompt the user for various paths and things before checking that what they've told you is sane. If any library or header is missing, it exits with an exit value of 0 to avoid causing a CPAN Testers 'FAIL' report. CPAN Testers should ignore this result -- which is what you want if an external library dependency is not available. =head2 check_lib This behaves exactly the same as C except that it is silent, returning false instead of dieing, or true otherwise. =cut sub check_lib_or_exit { eval 'assert_lib(@_)'; if($@) { warn $@; exit; } } sub check_lib { eval 'assert_lib(@_)'; return $@ ? 0 : 1; } # borrowed from Text::ParseWords sub _parse_line { my($delimiter, $keep, $line) = @_; my($word, @pieces); no warnings 'uninitialized'; # we will be testing undef strings while (length($line)) { # This pattern is optimised to be stack conservative on older perls. # Do not refactor without being careful and testing it on very long strings. # See Perl bug #42980 for an example of a stack busting input. $line =~ s/^ (?: # double quoted string (") # $quote ((?>[^\\"]*(?:\\.[^\\"]*)*))" # $quoted | # --OR-- # singe quoted string (') # $quote ((?>[^\\']*(?:\\.[^\\']*)*))' # $quoted | # --OR-- # unquoted string ( # $unquoted (?:\\.|[^\\"'])*? ) # followed by ( # $delim \Z(?!\n) # EOL | # --OR-- (?-x:$delimiter) # delimiter | # --OR-- (?!^)(?=["']) # a quote ) )//xs or return; # extended layout my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6); return() unless( defined($quote) || length($unquoted) || length($delim)); if ($keep) { $quoted = "$quote$quoted$quote"; } else { $unquoted =~ s/\\(.)/$1/sg; if (defined $quote) { $quoted =~ s/\\(.)/$1/sg if ($quote eq '"'); } } $word .= substr($line, 0, 0); # leave results tainted $word .= defined $quote ? $quoted : $unquoted; if (length($delim)) { push(@pieces, $word); push(@pieces, $delim) if ($keep eq 'delimiters'); undef $word; } if (!length($line)) { push(@pieces, $word); } } return(@pieces); } sub assert_lib { my %args = @_; my (@libs, @libpaths, @headers, @incpaths); # FIXME: these four just SCREAM "refactor" at me @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) if $args{lib}; @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) if $args{libpath}; @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) if $args{header}; @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) if $args{incpath}; my $analyze_binary = $args{analyze_binary}; my $not_execute = $args{not_execute}; my @argv = @ARGV; push @argv, _parse_line('\s+', 0, $ENV{PERL_MM_OPT}||''); # work-a-like for Makefile.PL's LIBS and INC arguments # if given as command-line argument, append to %args for my $arg (@argv) { for my $mm_attr_key (qw(LIBS INC)) { if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) { # it is tempting to put some \s* into the expression, but the # MM command-line parser only accepts LIBS etc. followed by =, # so we should not be any more lenient with whitespace than that $args{$mm_attr_key} .= " $mm_attr_value"; } } } # using special form of split to trim whitespace if(defined($args{LIBS})) { foreach my $arg (split(' ', $args{LIBS})) { die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/); push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2); } } if(defined($args{INC})) { foreach my $arg (split(' ', $args{INC})) { die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/); push @incpaths, substr($arg, 2); } } my ($cc, $ld) = _findcc($args{debug}, $args{ccflags}, $args{ldflags}); my @missing; my @wrongresult; my @wronganalysis; my @use_headers; # first figure out which headers we can't find ... for my $header (@headers) { push @use_headers, $header; my($ch, $cfile) = File::Temp::tempfile( 'assertlibXXXXXXXX', SUFFIX => '.c' ); my $ofile = $cfile; $ofile =~ s/\.c$/$Config{_o}/; print $ch qq{#include <$_>\n} for @use_headers; print $ch qq{int main(void) { return 0; }\n}; close($ch); my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe}; my @sys_cmd; # FIXME: re-factor - almost identical code later when linking if ( $Config{cc} eq 'cl' ) { # Microsoft compiler require Win32; @sys_cmd = ( @$cc, $cfile, "/Fe$exefile", (map { '/I'.Win32::GetShortPathName($_) } @incpaths), "/link", @$ld, split(' ', $Config{libs}), ); } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland @sys_cmd = ( @$cc, @$ld, (map { "-I$_" } @incpaths), "-o$exefile", $cfile ); } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ... @sys_cmd = ( @$cc, (map { "-I$_" } @incpaths), $cfile, @$ld, "-o", "$exefile" ); } warn "# @sys_cmd\n" if $args{debug}; my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); push @missing, $header if $rv != 0 || ! -f $exefile; _cleanup_exe($exefile); unlink $cfile; } # now do each library in turn with headers my($ch, $cfile) = File::Temp::tempfile( 'assertlibXXXXXXXX', SUFFIX => '.c' ); my $ofile = $cfile; $ofile =~ s/\.c$/$Config{_o}/; print $ch qq{#include <$_>\n} foreach (@headers); print $ch "int main(int argc, char *argv[]) { ".($args{function} || 'return 0;')." }\n"; close($ch); for my $lib ( @libs ) { my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe}; my @sys_cmd; if ( $Config{cc} eq 'cl' ) { # Microsoft compiler require Win32; my @libpath = map { q{/libpath:} . Win32::GetShortPathName($_) } @libpaths; # this is horribly sensitive to the order of arguments @sys_cmd = ( @$cc, $cfile, "${lib}.lib", "/Fe$exefile", (map { '/I'.Win32::GetShortPathName($_) } @incpaths), "/link", @$ld, split(' ', $Config{libs}), (map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths), ); } elsif($Config{cc} eq 'CC/DECC') { # VMS } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland @sys_cmd = ( @$cc, @$ld, "-o$exefile", (map { "-I$_" } @incpaths), (map { "-L$_" } @libpaths), "-l$lib", $cfile); } else { # Unix-ish # gcc, Sun, AIX (gcc, cc) @sys_cmd = ( @$cc, (map { "-I$_" } @incpaths), $cfile, (map { "-L$_" } @libpaths), "-l$lib", @$ld, "-o", "$exefile", ); } warn "# @sys_cmd\n" if $args{debug}; local $ENV{LD_RUN_PATH} = join(":", grep $_, @libpaths, $ENV{LD_RUN_PATH}) unless $^O eq 'MSWin32'; local $ENV{PATH} = join(";", @libpaths).";".$ENV{PATH} if $^O eq 'MSWin32'; my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); if ($rv != 0 || ! -f $exefile) { push @missing, $lib; } else { chmod 0755, $exefile; my $absexefile = File::Spec->rel2abs($exefile); $absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/; if (!$not_execute && system($absexefile) != 0) { push @wrongresult, $lib; } else { if ($analyze_binary) { push @wronganalysis, $lib if !$analyze_binary->($lib, $exefile) } } } _cleanup_exe($exefile); } unlink $cfile; my $miss_string = join( q{, }, map { qq{'$_'} } @missing ); die("Can't link/include C library $miss_string, aborting.\n") if @missing; my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult); die("wrong result: $wrong_string\n") if @wrongresult; my $analysis_string = join(q{, }, map { qq{'$_'} } @wronganalysis ); die("wrong analysis: $analysis_string") if @wronganalysis; } sub _cleanup_exe { my ($exefile) = @_; my $ofile = $exefile; $ofile =~ s/$Config{_exe}$/$Config{_o}/; # List of files to remove my @rmfiles; push @rmfiles, $exefile, $ofile, "$exefile\.manifest"; if ( $Config{cc} eq 'cl' ) { # MSVC also creates foo.ilk and foo.pdb my $ilkfile = $exefile; $ilkfile =~ s/$Config{_exe}$/.ilk/; my $pdbfile = $exefile; $pdbfile =~ s/$Config{_exe}$/.pdb/; push @rmfiles, $ilkfile, $pdbfile; } foreach (@rmfiles) { if ( -f $_ ) { unlink $_ or warn "Could not remove $_: $!"; } } return } # return ($cc, $ld) # where $cc is an array ref of compiler name, compiler flags # where $ld is an array ref of linker flags sub _findcc { my ($debug, $user_ccflags, $user_ldflags) = @_; # Need to use $keep=1 to work with MSWin32 backslashes and quotes my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile my @Config_ldflags = (); for my $config_val ( @Config{qw(ldflags)} ){ push @Config_ldflags, $config_val if ( $config_val =~ /\S/ ); } my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||'', $user_ccflags||''); my @ldflags = grep { length && $_ !~ m/^-Wl/ } quotewords('\s+', 1, @Config_ldflags, $user_ldflags||''); my @paths = split(/$Config{path_sep}/, $ENV{PATH}); my @cc = split(/\s+/, $Config{cc}); if (check_compiler ($cc[0], $debug)) { return ( [ @cc, @ccflags ], \@ldflags ); } # Find the extension for executables. my $exe = $Config{_exe}; if ($^O eq 'cygwin') { $exe = ''; } foreach my $path (@paths) { # Look for "$path/$cc[0].exe" my $compiler = File::Spec->catfile($path, $cc[0]) . $exe; if (check_compiler ($compiler, $debug)) { return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags) } next if ! $exe; # Look for "$path/$cc[0]" without the .exe, if necessary. $compiler = File::Spec->catfile($path, $cc[0]); if (check_compiler ($compiler, $debug)) { return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags) } } die("Couldn't find your C compiler.\n"); } sub check_compiler { my ($compiler, $debug) = @_; if (-f $compiler && -x $compiler) { if ($debug) { warn("# Compiler seems to be $compiler\n"); } return 1; } return ''; } # code substantially borrowed from IPC::Run3 sub _quiet_system { my (@cmd) = @_; # save handles local *STDOUT_SAVE; local *STDERR_SAVE; open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT"; open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR"; # redirect to nowhere local *DEV_NULL; open DEV_NULL, ">" . File::Spec->devnull or die "CheckLib: $! opening handle to null device"; open STDOUT, ">&" . fileno DEV_NULL or die "CheckLib: $! redirecting STDOUT to null handle"; open STDERR, ">&" . fileno DEV_NULL or die "CheckLib: $! redirecting STDERR to null handle"; # run system command my $rv = system(@cmd); # restore handles open STDOUT, ">&" . fileno STDOUT_SAVE or die "CheckLib: $! restoring STDOUT handle"; open STDERR, ">&" . fileno STDERR_SAVE or die "CheckLib: $! restoring STDERR handle"; return $rv; } =head1 PLATFORMS SUPPORTED You must have a C compiler installed. We check for C<$Config{cc}>, both literally as it is in Config.pm and also in the $PATH. It has been tested with varying degrees of rigorousness on: =over =item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin) =item Sun's compiler tools on Solaris =item IBM's tools on AIX =item SGI's tools on Irix 6.5 =item Microsoft's tools on Windows =item MinGW on Windows (with Strawberry Perl) =item Borland's tools on Windows =item QNX =back =head1 WARNINGS, BUGS and FEEDBACK This is a very early release intended primarily for feedback from people who have discussed it. The interface may change and it has not been adequately tested. Feedback is most welcome, including constructive criticism. Bug reports should be made using L or by email. When submitting a bug report, please include the output from running: perl -V perl -MDevel::CheckLib -e0 =head1 SEE ALSO L L =head1 AUTHORS David Cantrell Edavid@cantrell.org.ukE David Golden Edagolden@cpan.orgE Yasuhiro Matsumoto Emattn@cpan.orgE Thanks to the cpan-testers-discuss mailing list for prompting us to write it in the first place; to Chris Williams for help with Borland support; to Tony Cook for help with Microsoft compiler command-line options =head1 COPYRIGHT and LICENCE Copyright 2007 David Cantrell. Portions copyright 2007 David Golden. This module is free-as-in-speech software, and may be used, distributed, and modified under the same conditions as perl itself. =head1 CONSPIRACY This module is also free-as-in-mason software. =cut 1; perl5/cPanelUserConfig.pm000064400000001061152462503210011316 0ustar00# cpanel - cPanelUserConfig.pm Copyright(c) 2021 cPanel, L.L.C. # All Rights Reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited BEGIN { if ( $> != 0 ) { my $b__dir = ( getpwuid($>) )[7] . '/perl'; unshift @INC, $b__dir . '5/lib/perl5', $b__dir . '5/lib/perl5/x86_64-linux-thread-multi', map { $b__dir . $_ } grep { $_ ne '.' } @INC; } } 1; perl5/JSON.pm000044400000172121152462503210006704 0ustar00package JSON; use strict; use Carp (); use Exporter; BEGIN { @JSON::ISA = 'Exporter' } @JSON::EXPORT = qw(from_json to_json jsonToObj objToJson encode_json decode_json); BEGIN { $JSON::VERSION = '4.03'; $JSON::DEBUG = 0 unless (defined $JSON::DEBUG); $JSON::DEBUG = $ENV{ PERL_JSON_DEBUG } if exists $ENV{ PERL_JSON_DEBUG }; } my %RequiredVersion = ( 'JSON::PP' => '2.27203', 'JSON::XS' => '2.34', ); # XS and PP common methods my @PublicMethods = qw/ ascii latin1 utf8 pretty indent space_before space_after relaxed canonical allow_nonref allow_blessed convert_blessed filter_json_object filter_json_single_key_object shrink max_depth max_size encode decode decode_prefix allow_unknown /; my @Properties = qw/ ascii latin1 utf8 indent space_before space_after relaxed canonical allow_nonref allow_blessed convert_blessed shrink max_depth max_size allow_unknown /; my @XSOnlyMethods = qw//; # Currently nothing my @PublicMethodsSince4_0 = qw/allow_tags/; my @PropertiesSince4_0 = qw/allow_tags/; my @PPOnlyMethods = qw/ indent_length sort_by allow_singlequote allow_bignum loose allow_barekey escape_slash as_nonblessed /; # JSON::PP specific # used in _load_xs and _load_pp ($INSTALL_ONLY is not used currently) my $_INSTALL_DONT_DIE = 1; # When _load_xs fails to load XS, don't die. my $_ALLOW_UNSUPPORTED = 0; my $_UNIV_CONV_BLESSED = 0; # Check the environment variable to decide worker module. unless ($JSON::Backend) { $JSON::DEBUG and Carp::carp("Check used worker module..."); my $backend = exists $ENV{PERL_JSON_BACKEND} ? $ENV{PERL_JSON_BACKEND} : 1; if ($backend eq '1') { $backend = 'JSON::XS,JSON::PP'; } elsif ($backend eq '0') { $backend = 'JSON::PP'; } elsif ($backend eq '2') { $backend = 'JSON::XS'; } $backend =~ s/\s+//g; my @backend_modules = split /,/, $backend; while(my $module = shift @backend_modules) { if ($module =~ /JSON::XS/) { _load_xs($module, @backend_modules ? $_INSTALL_DONT_DIE : 0); } elsif ($module =~ /JSON::PP/) { _load_pp($module); } elsif ($module =~ /JSON::backportPP/) { _load_pp($module); } else { Carp::croak "The value of environmental variable 'PERL_JSON_BACKEND' is invalid."; } last if $JSON::Backend; } } sub import { my $pkg = shift; my @what_to_export; my $no_export; for my $tag (@_) { if ($tag eq '-support_by_pp') { if (!$_ALLOW_UNSUPPORTED++) { JSON::Backend::XS ->support_by_pp(@PPOnlyMethods) if ($JSON::Backend->is_xs); } next; } elsif ($tag eq '-no_export') { $no_export++, next; } elsif ( $tag eq '-convert_blessed_universally' ) { my $org_encode = $JSON::Backend->can('encode'); eval q| require B; local $^W; no strict 'refs'; *{"${JSON::Backend}\::encode"} = sub { # only works with Perl 5.18+ local *UNIVERSAL::TO_JSON = sub { my $b_obj = B::svref_2object( $_[0] ); return $b_obj->isa('B::HV') ? { %{ $_[0] } } : $b_obj->isa('B::AV') ? [ @{ $_[0] } ] : undef ; }; $org_encode->(@_); }; | if ( !$_UNIV_CONV_BLESSED++ ); next; } push @what_to_export, $tag; } return if ($no_export); __PACKAGE__->export_to_level(1, $pkg, @what_to_export); } # OBSOLETED sub jsonToObj { my $alternative = 'from_json'; if (defined $_[0] and UNIVERSAL::isa($_[0], 'JSON')) { shift @_; $alternative = 'decode'; } Carp::carp "'jsonToObj' will be obsoleted. Please use '$alternative' instead."; return JSON::from_json(@_); }; sub objToJson { my $alternative = 'to_json'; if (defined $_[0] and UNIVERSAL::isa($_[0], 'JSON')) { shift @_; $alternative = 'encode'; } Carp::carp "'objToJson' will be obsoleted. Please use '$alternative' instead."; JSON::to_json(@_); }; # INTERFACES sub to_json ($@) { if ( ref($_[0]) eq 'JSON' or (@_ > 2 and $_[0] eq 'JSON') ) { Carp::croak "to_json should not be called as a method."; } my $json = JSON->new; if (@_ == 2 and ref $_[1] eq 'HASH') { my $opt = $_[1]; for my $method (keys %$opt) { $json->$method( $opt->{$method} ); } } $json->encode($_[0]); } sub from_json ($@) { if ( ref($_[0]) eq 'JSON' or $_[0] eq 'JSON' ) { Carp::croak "from_json should not be called as a method."; } my $json = JSON->new; if (@_ == 2 and ref $_[1] eq 'HASH') { my $opt = $_[1]; for my $method (keys %$opt) { $json->$method( $opt->{$method} ); } } return $json->decode( $_[0] ); } sub true { $JSON::true } sub false { $JSON::false } sub boolean { # might be called as method or as function, so pop() to get the last arg instead of shift() to get the first pop() ? $JSON::true : $JSON::false } sub null { undef; } sub require_xs_version { $RequiredVersion{'JSON::XS'}; } sub backend { my $proto = shift; $JSON::Backend; } #*module = *backend; sub is_xs { return $_[0]->backend->is_xs; } sub is_pp { return $_[0]->backend->is_pp; } sub pureperl_only_methods { @PPOnlyMethods; } sub property { my ($self, $name, $value) = @_; if (@_ == 1) { my %props; for $name (@Properties) { my $method = 'get_' . $name; if ($name eq 'max_size') { my $value = $self->$method(); $props{$name} = $value == 1 ? 0 : $value; next; } $props{$name} = $self->$method(); } return \%props; } elsif (@_ > 3) { Carp::croak('property() can take only the option within 2 arguments.'); } elsif (@_ == 2) { if ( my $method = $self->can('get_' . $name) ) { if ($name eq 'max_size') { my $value = $self->$method(); return $value == 1 ? 0 : $value; } $self->$method(); } } else { $self->$name($value); } } # INTERNAL sub __load_xs { my ($module, $opt) = @_; $JSON::DEBUG and Carp::carp "Load $module."; my $required_version = $RequiredVersion{$module} || ''; eval qq| use $module $required_version (); |; if ($@) { if (defined $opt and $opt & $_INSTALL_DONT_DIE) { $JSON::DEBUG and Carp::carp "Can't load $module...($@)"; return 0; } Carp::croak $@; } $JSON::BackendModuleXS = $module; return 1; } sub _load_xs { my ($module, $opt) = @_; __load_xs($module, $opt) or return; my $data = join("", ); # this code is from Jcode 2.xx. close(DATA); eval $data; JSON::Backend::XS->init($module); return 1; }; sub __load_pp { my ($module, $opt) = @_; $JSON::DEBUG and Carp::carp "Load $module."; my $required_version = $RequiredVersion{$module} || ''; eval qq| use $module $required_version () |; if ($@) { if ( $module eq 'JSON::PP' ) { $JSON::DEBUG and Carp::carp "Can't load $module ($@), so try to load JSON::backportPP"; $module = 'JSON::backportPP'; local $^W; # if PP installed but invalid version, backportPP redefines methods. eval qq| require $module |; } Carp::croak $@ if $@; } $JSON::BackendModulePP = $module; return 1; } sub _load_pp { my ($module, $opt) = @_; __load_pp($module, $opt); JSON::Backend::PP->init($module); }; # # Helper classes for Backend Module (PP) # package JSON::Backend::PP; sub init { my ($class, $module) = @_; # name may vary, but the module should (always) be a JSON::PP local $^W; no strict qw(refs); # this routine may be called after JSON::Backend::XS init was called. *{"JSON::decode_json"} = \&{"JSON::PP::decode_json"}; *{"JSON::encode_json"} = \&{"JSON::PP::encode_json"}; *{"JSON::is_bool"} = \&{"JSON::PP::is_bool"}; $JSON::true = ${"JSON::PP::true"}; $JSON::false = ${"JSON::PP::false"}; push @JSON::Backend::PP::ISA, 'JSON::PP'; push @JSON::ISA, $class; $JSON::Backend = $class; $JSON::BackendModule = $module; my $version = ${"$class\::VERSION"} = $module->VERSION; $version =~ s/_//; if ($version < 3.99) { push @XSOnlyMethods, qw/allow_tags get_allow_tags/; } else { push @Properties, 'allow_tags'; } for my $method (@XSOnlyMethods) { *{"JSON::$method"} = sub { Carp::carp("$method is not supported by $module $version."); $_[0]; }; } return 1; } sub is_xs { 0 }; sub is_pp { 1 }; # # To save memory, the below lines are read only when XS backend is used. # package JSON; 1; __DATA__ # # Helper classes for Backend Module (XS) # package JSON::Backend::XS; sub init { my ($class, $module) = @_; local $^W; no strict qw(refs); *{"JSON::decode_json"} = \&{"$module\::decode_json"}; *{"JSON::encode_json"} = \&{"$module\::encode_json"}; *{"JSON::is_bool"} = \&{"$module\::is_bool"}; $JSON::true = ${"$module\::true"}; $JSON::false = ${"$module\::false"}; push @JSON::Backend::XS::ISA, $module; push @JSON::ISA, $class; $JSON::Backend = $class; $JSON::BackendModule = $module; ${"$class\::VERSION"} = $module->VERSION; if ( $module->VERSION < 3 ) { eval 'package JSON::PP::Boolean'; push @{"$module\::Boolean::ISA"}, qw(JSON::PP::Boolean); } for my $method (@PPOnlyMethods) { *{"JSON::$method"} = sub { Carp::carp("$method is not supported by $module."); $_[0]; }; } return 1; } sub is_xs { 1 }; sub is_pp { 0 }; sub support_by_pp { my ($class, @methods) = @_; JSON::__load_pp('JSON::PP'); local $^W; no strict qw(refs); for my $method (@methods) { my $pp_method = JSON::PP->can($method) or next; *{"JSON::$method"} = sub { if (!$_[0]->isa('JSON::PP')) { my $xs_self = $_[0]; my $pp_self = JSON::PP->new; for (@Properties) { my $getter = "get_$_"; $pp_self->$_($xs_self->$getter); } $_[0] = $pp_self; } $pp_method->(@_); }; } $JSON::DEBUG and Carp::carp("set -support_by_pp mode."); } 1; __END__ =head1 NAME JSON - JSON (JavaScript Object Notation) encoder/decoder =head1 SYNOPSIS use JSON; # imports encode_json, decode_json, to_json and from_json. # simple and fast interfaces (expect/generate UTF-8) $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; # OO-interface $json = JSON->new->allow_nonref; $json_text = $json->encode( $perl_scalar ); $perl_scalar = $json->decode( $json_text ); $pretty_printed = $json->pretty->encode( $perl_scalar ); # pretty-printing =head1 VERSION 4.02 =head1 DESCRIPTION This module is a thin wrapper for L-compatible modules with a few additional features. All the backend modules convert a Perl data structure to a JSON text and vice versa. This module uses L by default, and when JSON::XS is not available, falls back on L, which is in the Perl core since 5.14. If JSON::PP is not available either, this module then falls back on JSON::backportPP (which is actually JSON::PP in a different .pm file) bundled in the same distribution as this module. You can also explicitly specify to use L, a fork of JSON::XS by Reini Urban. All these backend modules have slight incompatibilities between them, including extra features that other modules don't support, but as long as you use only common features (most important ones are described below), migration from backend to backend should be reasonably easy. For details, see each backend module you use. =head1 CHOOSING BACKEND This module respects an environmental variable called C when it decides a backend module to use. If this environmental variable is not set, it tries to load JSON::XS, and if JSON::XS is not available, it falls back on JSON::PP, and then JSON::backportPP if JSON::PP is not available either. If you always don't want it to fall back on pure perl modules, set the variable like this (C may be C, C and the likes, depending on your environment): > export PERL_JSON_BACKEND=JSON::XS If you prefer Cpanel::JSON::XS to JSON::XS, then: > export PERL_JSON_BACKEND=Cpanel::JSON::XS,JSON::XS,JSON::PP You may also want to set this variable at the top of your test files, in order not to be bothered with incompatibilities between backends (you need to wrap this in C, and set before actually C-ing JSON module, as it decides its backend as soon as it's loaded): BEGIN { $ENV{PERL_JSON_BACKEND}='JSON::backportPP'; } use JSON; =head1 USING OPTIONAL FEATURES There are a few options you can set when you C this module. These historical options are only kept for backward compatibility, and should not be used in a new application. =over =item -support_by_pp BEGIN { $ENV{PERL_JSON_BACKEND} = 'JSON::XS' } use JSON -support_by_pp; my $json = JSON->new; # escape_slash is for JSON::PP only. $json->allow_nonref->escape_slash->encode("/"); With this option, this module loads its pure perl backend along with its XS backend (if available), and lets the XS backend to watch if you set a flag only JSON::PP supports. When you do, the internal JSON::XS object is replaced with a newly created JSON::PP object with the setting copied from the XS object, so that you can use JSON::PP flags (and its slower C/C methods) from then on. In other words, this is not something that allows you to hook JSON::XS to change its behavior while keeping its speed. JSON::XS and JSON::PP objects are quite different (JSON::XS object is a blessed scalar reference, while JSON::PP object is a blessed hash reference), and can't share their internals. To avoid needless overhead (by copying settings), you are advised not to use this option and just to use JSON::PP explicitly when you need JSON::PP features. =item -convert_blessed_universally use JSON -convert_blessed_universally; my $json = JSON->new->allow_nonref->convert_blessed; my $object = bless {foo => 'bar'}, 'Foo'; $json->encode($object); # => {"foo":"bar"} JSON::XS-compatible backend modules don't encode blessed objects by default (except for their boolean values, which are typically blessed JSON::PP::Boolean objects). If you need to encode a data structure that may contain objects, you usually need to look into the structure and replace objects with alternative non-blessed values, or enable C and provide a C method for each object's (base) class that may be found in the structure, in order to let the methods replace the objects with whatever scalar values the methods return. If you need to serialise data structures that may contain arbitrary objects, it's probably better to use other serialisers (such as L or L for example), but if you do want to use this module for that purpose, C<-convert_blessed_universally> option may help, which tweaks C method of the backend to install C method (locally) before encoding, so that all the objects that don't have their own C method can fall back on the method in the C namespace. Note that you still need to enable C flag to actually encode objects in a data structure, and C method installed by this option only converts blessed hash/array references into their unblessed clone (including private keys/values that are not supposed to be exposed). Other blessed references will be converted into null. This feature is experimental and may be removed in the future. =item -no_export When you don't want to import functional interfaces from a module, you usually supply C<()> to its C statement. use JSON (); # no functional interfaces If you don't want to import functional interfaces, but you also want to use any of the above options, add C<-no_export> to the option list. # no functional interfaces, while JSON::PP support is enabled. use JSON -support_by_pp, -no_export; =back =head1 FUNCTIONAL INTERFACE This section is taken from JSON::XS. C and C are exported by default. This module also exports C and C for backward compatibility. These are slower, and may expect/generate different stuff from what C and C do, depending on their options. It's better just to use Object-Oriented interfaces than using these two functions. =head2 encode_json $json_text = encode_json $perl_scalar Converts the given Perl data structure to a UTF-8 encoded, binary string (that is, the string contains octets only). Croaks on error. This function call is functionally identical to: $json_text = JSON->new->utf8->encode($perl_scalar) Except being faster. =head2 decode_json $perl_scalar = decode_json $json_text The opposite of C: expects an UTF-8 (binary) string and tries to parse that as an UTF-8 encoded JSON text, returning the resulting reference. Croaks on error. This function call is functionally identical to: $perl_scalar = JSON->new->utf8->decode($json_text) Except being faster. =head2 to_json $json_text = to_json($perl_scalar[, $optional_hashref]) Converts the given Perl data structure to a Unicode string by default. Croaks on error. Basically, this function call is functionally identical to: $json_text = JSON->new->encode($perl_scalar) Except being slower. You can pass an optional hash reference to modify its behavior, but that may change what C expects/generates (see C for details). $json_text = to_json($perl_scalar, {utf8 => 1, pretty => 1}) # => JSON->new->utf8(1)->pretty(1)->encode($perl_scalar) =head2 from_json $perl_scalar = from_json($json_text[, $optional_hashref]) The opposite of C: expects a Unicode string and tries to parse it, returning the resulting reference. Croaks on error. Basically, this function call is functionally identical to: $perl_scalar = JSON->new->decode($json_text) You can pass an optional hash reference to modify its behavior, but that may change what C expects/generates (see C for details). $perl_scalar = from_json($json_text, {utf8 => 1}) # => JSON->new->utf8(1)->decode($json_text) =head2 JSON::is_bool $is_boolean = JSON::is_bool($scalar) Returns true if the passed scalar represents either JSON::true or JSON::false, two constants that act like C<1> and C<0> respectively and are also used to represent JSON C and C in Perl strings. See L, below, for more information on how JSON values are mapped to Perl. =head1 COMMON OBJECT-ORIENTED INTERFACE This section is also taken from JSON::XS. The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. =head2 new $json = JSON->new Creates a new JSON::XS-compatible backend object that can be used to de/encode JSON strings. All boolean flags described below are by default I (with the exception of C, which defaults to I since version C<4.0>). The mutators for flags all return the backend object again and thus calls can be chained: my $json = JSON->new->utf8->space_after->encode({a => [1,2]}) => {"a": [1, 2]} =head2 ascii $json = $json->ascii([$enable]) $enabled = $json->get_ascii If C<$enable> is true (or missing), then the C method will not generate characters outside the code range C<0..127> (which is ASCII). Any Unicode characters outside that range will be escaped using either a single \uXXXX (BMP characters) or a double \uHHHH\uLLLLL escape sequence, as per RFC4627. The resulting encoded JSON text can be treated as a native Unicode string, an ascii-encoded, latin1-encoded or UTF-8 encoded string, or any other superset of ASCII. If C<$enable> is false, then the C method will not escape Unicode characters unless required by the JSON syntax or other flags. This results in a faster and more compact format. See also the section I later in this document. The main use for this flag is to produce JSON texts that can be transmitted over a 7-bit channel, as the encoded JSON texts will not contain any 8 bit characters. JSON->new->ascii(1)->encode([chr 0x10401]) => ["\ud801\udc01"] =head2 latin1 $json = $json->latin1([$enable]) $enabled = $json->get_latin1 If C<$enable> is true (or missing), then the C method will encode the resulting JSON text as latin1 (or iso-8859-1), escaping any characters outside the code range C<0..255>. The resulting string can be treated as a latin1-encoded JSON text or a native Unicode string. The C method will not be affected in any way by this flag, as C by default expects Unicode, which is a strict superset of latin1. If C<$enable> is false, then the C method will not escape Unicode characters unless required by the JSON syntax or other flags. See also the section I later in this document. The main use for this flag is efficiently encoding binary data as JSON text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting JSON text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for JSON. It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other JSON encoders/decoders. JSON->new->latin1->encode (["\x{89}\x{abc}"] => ["\x{89}\\u0abc"] # (perl syntax, U+abc escaped, U+89 not) =head2 utf8 $json = $json->utf8([$enable]) $enabled = $json->get_utf8 If C<$enable> is true (or missing), then the C method will encode the JSON result into UTF-8, as required by many protocols, while the C method expects to be handled an UTF-8-encoded string. Please note that UTF-8-encoded strings do not contain any characters outside the range C<0..255>, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the UTF-16 and UTF-32 encoding families, as described in RFC4627. If C<$enable> is false, then the C method will return the JSON string as a (non-encoded) Unicode string, while C expects thus a Unicode string. Any decoding or encoding (e.g. to UTF-8 or UTF-16) needs to be done yourself, e.g. using the Encode module. See also the section I later in this document. Example, output UTF-16BE-encoded JSON: use Encode; $jsontext = encode "UTF-16BE", JSON->new->encode ($object); Example, decode UTF-32LE-encoded JSON: use Encode; $object = JSON->new->decode (decode "UTF-32LE", $jsontext); =head2 pretty $json = $json->pretty([$enable]) This enables (or disables) all of the C, C and C (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. =head2 indent $json = $json->indent([$enable]) $enabled = $json->get_indent If C<$enable> is true (or missing), then the C method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. If C<$enable> is false, no newlines or indenting will be produced, and the resulting JSON text is guaranteed not to contain any C. This setting has no effect when decoding JSON texts. =head2 space_before $json = $json->space_before([$enable]) $enabled = $json->get_space_before If C<$enable> is true (or missing), then the C method will add an extra optional space before the C<:> separating keys from values in JSON objects. If C<$enable> is false, then the C method will not add any extra space at those places. This setting has no effect when decoding JSON texts. You will also most likely combine this setting with C. Example, space_before enabled, space_after and indent disabled: {"key" :"value"} =head2 space_after $json = $json->space_after([$enable]) $enabled = $json->get_space_after If C<$enable> is true (or missing), then the C method will add an extra optional space after the C<:> separating keys from values in JSON objects and extra whitespace after the C<,> separating key-value pairs and array members. If C<$enable> is false, then the C method will not add any extra space at those places. This setting has no effect when decoding JSON texts. Example, space_before and indent disabled, space_after enabled: {"key": "value"} =head2 relaxed $json = $json->relaxed([$enable]) $enabled = $json->get_relaxed If C<$enable> is true (or missing), then C will accept some extensions to normal JSON syntax (see below). C will not be affected in any way. I. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) If C<$enable> is false (the default), then C will only accept valid JSON texts. Currently accepted extensions are: =over 4 =item * list items can have an end-comma JSON I array elements and key-value pairs with commas. This can be annoying if you write JSON texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: [ 1, 2, <- this comma not normally allowed ] { "k1": "v1", "k2": "v2", <- this comma not normally allowed } =item * shell-style '#'-comments Whenever JSON allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. [ 1, # this comment not allowed in JSON # neither this one... ] =back =head2 canonical $json = $json->canonical([$enable]) $enabled = $json->get_canonical If C<$enable> is true (or missing), then the C method will output JSON objects by sorting their keys. This is adding a comparatively high overhead. If C<$enable> is false, then the C method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). This option is useful if you want the same data structure to be encoded as the same JSON text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. This setting has no effect when decoding JSON texts. This setting has currently no effect on tied hashes. =head2 allow_nonref $json = $json->allow_nonref([$enable]) $enabled = $json->get_allow_nonref Unlike other boolean options, this option is enabled by default beginning with version C<4.0>. If C<$enable> is true (or missing), then the C method can convert a non-reference into its corresponding string, number or null JSON value, which is an extension to RFC4627. Likewise, C will accept those JSON values instead of croaking. If C<$enable> is false, then the C method will croak if it isn't passed an arrayref or hashref, as JSON texts must either be an object or array. Likewise, C will croak if given something that is not a JSON object or array. Example, encode a Perl scalar as JSON value with enabled C, resulting in an invalid JSON text: JSON->new->allow_nonref->encode ("Hello, World!") => "Hello, World!" =head2 allow_unknown $json = $json->allow_unknown ([$enable]) $enabled = $json->get_allow_unknown If C<$enable> is true (or missing), then C will I throw an exception when it encounters values it cannot represent in JSON (for example, filehandles) but instead will encode a JSON C value. Note that blessed objects are not included here and are handled separately by c. If C<$enable> is false (the default), then C will throw an exception when it encounters anything it cannot encode as JSON. This option does not affect C in any way, and it is recommended to leave it off unless you know your communications partner. =head2 allow_blessed $json = $json->allow_blessed([$enable]) $enabled = $json->get_allow_blessed See L for details. If C<$enable> is true (or missing), then the C method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a JSON C value is encoded instead of the object. If C<$enable> is false (the default), then C will throw an exception when it encounters a blessed object that it cannot convert otherwise. This setting has no effect on C. =head2 convert_blessed $json = $json->convert_blessed([$enable]) $enabled = $json->get_convert_blessed See L for details. If C<$enable> is true (or missing), then C, upon encountering a blessed object, will check for the availability of the C method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. The C method may safely call die if it wants. If C returns other blessed objects, those will be handled in the same way. C must take care of not causing an endless recursion cycle (== crash) in this case. The name of C was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any C function or method. If C<$enable> is false (the default), then C will not consider this type of conversion. This setting has no effect on C. =head2 allow_tags (since version 3.0) $json = $json->allow_tags([$enable]) $enabled = $json->get_allow_tags See L for details. If C<$enable> is true (or missing), then C, upon encountering a blessed object, will check for the availability of the C method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged JSON value (that JSON decoders cannot decode). It also causes C to parse such tagged JSON values and deserialise them via a call to the C method. If C<$enable> is false (the default), then C will not consider this type of conversion, and tagged JSON values will cause a parse error in C, as if tags were not part of the grammar. =head2 boolean_values (since version 4.0) $json->boolean_values([$false, $true]) ($false, $true) = $json->get_boolean_values By default, JSON booleans will be decoded as overloaded C<$JSON::false> and C<$JSON::true> objects. With this method you can specify your own boolean values for decoding - on decode, JSON C will be decoded as a copy of C<$false>, and JSON C will be decoded as C<$true> ("copy" here is the same thing as assigning a value to another variable, i.e. C<$copy = $false>). This is useful when you want to pass a decoded data structure directly to other serialisers like YAML, Data::MessagePack and so on. Note that this works only when you C. You can set incompatible boolean objects (like L), but when you C a data structure with such boolean objects, you still need to enable C (and add a C method if necessary). Calling this method without any arguments will reset the booleans to their default values. C will return both C<$false> and C<$true> values, or the empty list when they are set to the default. =head2 filter_json_object $json = $json->filter_json_object([$coderef]) When C<$coderef> is specified, it will be called from C each time it decodes a JSON object. The only argument is a reference to the newly-created hash. If the code references returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (NOTE: I C, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. When C<$coderef> is omitted or undefined, any existing callback will be removed and C will not change the deserialised hash in any way. Example, convert all JSON objects into the integer 5: my $js = JSON->new->filter_json_object(sub { 5 }); # returns [5] $js->decode('[{}]'); # returns 5 $js->decode('{"a":1, "b":2}'); =head2 filter_json_single_key_object $json = $json->filter_json_single_key_object($key [=> $coderef]) Works remotely similar to C, but is only called for JSON objects having a single key named C<$key>. This C<$coderef> is called before the one specified via C, if any. It gets passed the single value in the JSON object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even C but the empty list), the callback from C will be called next, as if no single-key callback were specified. If C<$coderef> is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. As this callback gets called less often then the C one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key JSON objects are as close to the type-tagged value concept as JSON gets (it's basically an ID/VALUE tuple). Of course, JSON does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. Typical names for the single object key are C<__class_whatever__>, or C<$__dollars_are_rarely_used__$> or C<}ugly_brace_placement>, or even things like C<__class_md5sum(classname)__>, to reduce the risk of clashing with real hashes. Example, decode JSON objects of the form C<< { "__widget__" => } >> into the corresponding C<< $WIDGET{} >> object: # return whatever is in $WIDGET{5}: JSON ->new ->filter_json_single_key_object (__widget__ => sub { $WIDGET{ $_[0] } }) ->decode ('{"__widget__": 5') # this can be used with a TO_JSON method in some "widget" class # for serialisation to json: sub WidgetBase::TO_JSON { my ($self) = @_; unless ($self->{id}) { $self->{id} = ..get..some..id..; $WIDGET{$self->{id}} = $self; } { __widget__ => $self->{id} } } =head2 max_depth $json = $json->max_depth([$maximum_nesting_depth]) $max_depth = $json->get_max_depth Sets the maximum nesting level (default C<512>) accepted while encoding or decoding. If a higher nesting level is detected in JSON text or a Perl data structure, then the encoder and decoder will stop and croak at that point. Nesting level is defined by number of hash- or arrayrefs that the encoder needs to traverse to reach a given point or the number of C<{> or C<[> characters without their matching closing parenthesis crossed to reach a given character in a string. Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. If no argument is given, the highest possible setting will be used, which is rarely useful. See L for more info on why this is useful. =head2 max_size $json = $json->max_size([$maximum_string_size]) $max_size = $json->get_max_size Set the maximum length a JSON text may have (in bytes) where decoding is being attempted. The default is C<0>, meaning no limit. When C is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on C (yet). If no argument is given, the limit check will be deactivated (same as when C<0> is specified). See L for more info on why this is useful. =head2 encode $json_text = $json->encode($perl_scalar) Converts the given Perl value or data structure to its JSON representation. Croaks on error. =head2 decode $perl_scalar = $json->decode($json_text) The opposite of C: expects a JSON text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. =head2 decode_prefix ($perl_scalar, $characters) = $json->decode_prefix($json_text) This works like the C method, but instead of raising an exception when there is trailing garbage after the first JSON object, it will silently stop parsing there and return the number of characters consumed so far. This is useful if your JSON texts are not delimited by an outer protocol and you need to know where the JSON text ends. JSON->new->decode_prefix ("[1] the tail") => ([1], 3) =head1 ADDITIONAL METHODS The following methods are for this module only. =head2 backend $backend = $json->backend Since 2.92, C method returns an abstract backend module used currently, which should be JSON::Backend::XS (which inherits JSON::XS or Cpanel::JSON::XS), or JSON::Backend::PP (which inherits JSON::PP), not to monkey-patch the actual backend module globally. If you need to know what is used actually, use C, instead of string comparison. =head2 is_xs $boolean = $json->is_xs Returns true if the backend inherits JSON::XS or Cpanel::JSON::XS. =head2 is_pp $boolean = $json->is_pp Returns true if the backend inherits JSON::PP. =head2 property $settings = $json->property() Returns a reference to a hash that holds all the common flag settings. $json = $json->property('utf8' => 1) $value = $json->property('utf8') # 1 You can use this to get/set a value of a particular flag. =head2 boolean $boolean_object = JSON->boolean($scalar) Returns $JSON::true if $scalar contains a true value, $JSON::false otherwise. You can use this as a full-qualified function (C). =head1 INCREMENTAL PARSING This section is also taken from JSON::XS. In some cases, there is the need for incremental parsing of JSON texts. While this module always has to keep both JSON text and resulting Perl data structure in memory at one time, it does allow you to parse a JSON stream incrementally. It does so by accumulating text until it has a full JSON object, which it then can decode. This process is similar to using C to see if a full JSON object is available, but is much more efficient (and can be implemented with a minimum of method calls). This module will only attempt to parse the JSON text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid JSON text has been seen. This means you need to set resource limits (e.g. C) to ensure the parser will stop parsing in the presence if syntax errors. The following methods implement this incremental parser. =head2 incr_parse $json->incr_parse( [$string] ) # void context $obj_or_undef = $json->incr_parse( [$string] ) # scalar context @obj_or_empty = $json->incr_parse( [$string] ) # list context This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). If C<$string> is given, then this string is appended to the already existing JSON fragment stored in the C<$json> object. After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. If the method is called in scalar context, then it will try to extract exactly I JSON object. If that is successful, it will return this object, otherwise it will return C. If there is a parse error, this method will croak just as C would do (one can then use C to skip the erroneous part). This is the most common way of using the method. And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the JSON objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed JSON texts will be lost. Example: Parse some JSON arrays/objects in a given string and return them. my @objs = JSON->new->incr_parse ("[5][7][1,2]"); =head2 incr_text $lvalue_string = $json->incr_text This method returns the currently stored JSON fragment as an lvalue, that is, you can manipulate it. This I works when a preceding call to C in I successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it I fail under real world conditions). As a special exception, you can also call this method before having parsed anything. That means you can only use this function to look at or manipulate text before or after complete JSON objects, not while the parser is in the middle of parsing a JSON object. This function is useful in two cases: a) finding the trailing text after a JSON object or b) parsing multiple JSON objects separated by non-JSON text (such as commas). =head2 incr_skip $json->incr_skip This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after C died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. The difference to C is that only text until the parse error occurred is removed. =head2 incr_reset $json->incr_reset This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. This is useful if you want to repeatedly parse JSON objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. =head1 MAPPING Most of this section is also taken from JSON::XS. This section describes how the backend modules map Perl values to JSON values and vice versa. These mappings are designed to "do the right thing" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). For the more enlightened: note that in the following descriptions, lowercase I refers to the Perl interpreter, while uppercase I refers to the abstract Perl language itself. =head2 JSON -> PERL =over 4 =item object A JSON object becomes a reference to a hash in Perl. No ordering of object keys is preserved (JSON does not preserver object key ordering itself). =item array A JSON array becomes a reference to an array in Perl. =item string A JSON string becomes a string scalar in Perl - Unicode codepoints in JSON are represented by the same codepoints in the Perl string, so no manual decoding is necessary. =item number A JSON number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. If the number consists of digits only, this module will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the JSON number will be re-encoded to a JSON string). Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the JSON number will still be re-encoded as a JSON number). Note that precision is not accuracy - binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, this module only guarantees precision up to but not including the least significant bit. =item true, false These JSON atoms become C and C, respectively. They are overloaded to act almost exactly like the numbers C<1> and C<0>. You can check whether a scalar is a JSON boolean by using the C function. =item null A JSON null atom becomes C in Perl. =item shell-style comments (C<< # I >>) As a nonstandard extension to the JSON syntax that is enabled by the C setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. =item tagged values (C<< (I)I >>). Another nonstandard extension to the JSON syntax, enabled with the C setting, are tagged values. In this implementation, the I must be a perl package/class name encoded as a JSON string, and the I must be a JSON array encoding optional constructor arguments. See L, below, for details. =back =head2 PERL -> JSON The mapping from Perl to JSON is slightly more difficult, as Perl is a truly typeless language, so we can only guess which JSON type is meant by a Perl value. =over 4 =item hash references Perl hash references become JSON objects. As there is no inherent ordering in hash keys (or JSON objects), they will usually be encoded in a pseudo-random order. This module can optionally sort the hash keys (determined by the I flag), so the same data structure will serialise to the same JSON text (given same settings and version of the same backend), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some JSON text against another for equality. =item array references Perl array references become JSON arrays. =item other references Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers C<0> and C<1>, which get turned into C and C atoms in JSON. You can also use C and C to improve readability. encode_json [\0,JSON::true] # yields [false,true] =item JSON::true, JSON::false, JSON::null These special values become JSON true and JSON false values, respectively. You can also use C<\1> and C<\0> directly if you want. =item blessed objects Blessed objects are not directly representable in JSON, but C allows various ways of handling objects. See L, below, for details. =item simple scalars Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: this module will encode undefined scalars as JSON C values, scalars that have last been used in a string context before encoding as JSON strings, and anything else as number value: # dump as number encode_json [2] # yields [2] encode_json [-3.0e17] # yields [-3e+17] my $value = 5; encode_json [$value] # yields [5] # used as string, so dump as string print $value; encode_json [$value] # yields ["5"] # undef becomes null encode_json [undef] # yields [null] You can force the type to be a string by stringifying it: my $x = 3.1; # some variable containing a number "$x"; # stringified $x .= ""; # another, more awkward way to stringify print $x; # perl does it for you, too, quite often You can force the type to be a number by numifying it: my $x = "3"; # some variable containing a string $x += 0; # numify it, ensuring it will be dumped as a number $x *= 1; # same thing, the choice is yours. You can not currently force the type in other, less obscure, ways. Tell me if you need this capability (but don't forget to explain why it's needed :). Since version 2.91_01, JSON::PP uses a different number detection logic that converts a scalar that is possible to turn into a number safely. The new logic is slightly faster, and tends to help people who use older perl or who want to encode complicated data structure. However, this may results in a different JSON text from the one JSON::XS encodes (and thus may break tests that compare entire JSON texts). If you do need the previous behavior for better compatibility or for finer control, set PERL_JSON_PP_USE_B environmental variable to true before you C JSON. Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's - these cannot be represented in JSON, and it is an error to pass those in. JSON.pm backend modules trust what you pass to C method (or C function) is a clean, validated data structure with values that can be represented as valid JSON values only, because it's not from an external data source (as opposed to JSON texts you pass to C or C, which JSON backends consider tainted and don't trust). As JSON backends don't know exactly what you and consumers of your JSON texts want the unexpected values to be (you may want to convert them into null, or to stringify them with or without normalisation (string representation of infinities/NaN may vary depending on platforms), or to croak without conversion), you're advised to do what you and your consumers need before you encode, and also not to numify values that may start with values that look like a number (including infinities/NaN), without validating. =back =head2 OBJECT SERIALISATION As JSON cannot directly represent Perl objects, you have to choose between a pure JSON representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the JSON syntax, tagged values. =head3 SERIALISATION What happens when this module encounters a Perl object depends on the C, C and C settings, which are used in this order: =over 4 =item 1. C is enabled and the object has a C method. In this case, C creates a tagged JSON value, using a nonstandard extension to the JSON syntax. This works by invoking the C method on the object, with the first argument being the object to serialise, and the second argument being the constant string C to distinguish it from other serialisers. The C method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged JSON value in the following format: ("classname")[FREEZE return values...] e.g.: ("URI")["http://www.google.com/"] ("MyDate")[2013,10,29] ("ImageData::JPEG")["Z3...VlCg=="] For example, the hypothetical C C method might use the objects C and C members to encode the object: sub My::Object::FREEZE { my ($self, $serialiser) = @_; ($self->{type}, $self->{id}) } =item 2. C is enabled and the object has a C method. In this case, the C method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into JSON. This scalar replaces the object in the JSON text. For example, the following C method will convert all L objects to JSON strings when serialised. The fact that these values originally were L objects is lost. sub URI::TO_JSON { my ($uri) = @_; $uri->as_string } =item 3. C is enabled. The object will be serialised as a JSON null value. =item 4. none of the above If none of the settings are enabled or the respective methods are missing, this module throws an exception. =back =head3 DESERIALISATION For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case C decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the C or C callbacks to get some real objects our of your JSON. This section only considers the tagged value case: a tagged JSON object is encountered during decoding and C is disabled, a parse error will result (as if tagged values were not part of the grammar). If C is enabled, this module will look up the C method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. Otherwise, the C method is invoked with the classname as first argument, the constant string C as second argument, and all the values from the JSON array (the values originally returned by the C method) as remaining arguments. The method must then return the object. While technically you can return any Perl scalar, you might have to enable the C setting to make that work in all cases, so better return an actual blessed reference. As an example, let's implement a C function that regenerates the C from the C example earlier: sub My::Object::THAW { my ($class, $serialiser, $type, $id) = @_; $class->new (type => $type, id => $id) } =head1 ENCODING/CODESET FLAG NOTES This section is taken from JSON::XS. The interested reader might have seen a number of flags that signify encodings or codesets - C, C and C. There seems to be some confusion on what these do, so here is a short comparison: C controls whether the JSON text created by C (and expected by C) is UTF-8 encoded or not, while C and C only control whether C escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. Care has been taken to make all flags symmetrical with respect to C and C, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used - in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. Below comes a verbose discussion of these flags. Note that a "codeset" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and I them, in our case into octets. Unicode is (among other things) a codeset, UTF-8 is an encoding, and ISO-8859-1 (= latin 1) and ASCII are both codesets I encodings at the same time, which can be confusing. =over 4 =item C flag disabled When C is disabled (the default), then C/C generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except "(re-)interpreting" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). This is useful when you want to do the encoding yourself (e.g. when you want to have UTF-16 encoded JSON texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to UTF-8 you certainly do NOT want to UTF-8 encode your data first and have Perl encode it another time). =item C flag enabled If the C-flag is enabled, C/C will encode all characters using the corresponding UTF-8 multi-byte sequence, and will expect your input strings to be encoded as UTF-8, that is, no "character" of the input string must have any value > 255, as UTF-8 does not allow that. The C flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get an UTF-8 encoded octet/binary string in Perl. =item C or C flags enabled With C (or C) enabled, C will escape characters with ordinal values > 255 (> 127 with C) and encode the remaining characters as specified by the C flag. If C is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a ISO-8859-1 string, and a Unicode string with all character values < 128 is the same thing as an ASCII string in Perl). If C is enabled, you still get a correct UTF-8-encoded string, regardless of these flags, just some more characters will be escaped using C<\uXXXX> then before. Note that ISO-8859-1-I strings are not compatible with UTF-8 encoding, while ASCII-encoded strings are. That is because the ISO-8859-1 encoding is NOT a subset of UTF-8 (despite the ISO-8859-1 I being a subset of Unicode), while ASCII is. Surprisingly, C will ignore these flags and so treat all input values as governed by the C flag. If it is disabled, this allows you to decode ISO-8859-1- and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode UTF-8 encoded strings. So neither C nor C are incompatible with the C flag - they only govern when the JSON output engine escapes a character or not. The main use for C is to relatively efficiently store binary data as JSON, at the expense of breaking compatibility with most JSON decoders. The main use for C is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as UTF-8, ISO-8859-1, ASCII, KOI8-R or most about any character set and 8-bit-encoding, and still get the same data structure back. This is useful when your channel for JSON transfer is not 8-bit clean or the encoding might be mangled in between (e.g. in mail), and works because ASCII is a proper subset of most 8-bit and multibyte encodings in use in the world. =back =head1 BACKWARD INCOMPATIBILITY Since version 2.90, stringification (and string comparison) for C and C has not been overloaded. It shouldn't matter as long as you treat them as boolean values, but a code that expects they are stringified as "true" or "false" doesn't work as you have expected any more. if (JSON::true eq 'true') { # now fails print "The result is $JSON::true now."; # => The result is 1 now. And now these boolean values don't inherit JSON::Boolean, either. When you need to test a value is a JSON boolean value or not, use C function, instead of testing the value inherits a particular boolean class or not. =head1 BUGS Please report bugs on backend selection and additional features this module provides to RT or GitHub issues for this module: L L As for bugs on a specific behavior, please report to the author of the backend module you are using. As for new features and requests to change common behaviors, please ask the author of JSON::XS (Marc Lehmann, Eschmorp[at]schmorp.deE) first, by email (important!), to keep compatibility among JSON.pm backends. =head1 SEE ALSO L, L, L for backends. L, an alternative that prefers Cpanel::JSON::XS. C(L) RFC7159 (L) RFC8259 (L) =head1 AUTHOR Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE JSON::XS was written by Marc Lehmann Eschmorp[at]schmorp.deE The release of this new version owes to the courtesy of Marc Lehmann. =head1 CURRENT MAINTAINER Kenichi Ishigaki, Eishigaki[at]cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2005-2013 by Makamaka Hannyaharamitu Most of the documentation is taken from JSON::XS by Marc Lehmann This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/IO/LockedFile/Flock.pm000044400000002730152462503210011477 0ustar00package IO::LockedFile::Flock; use strict; use Fcntl ':flock'; # import LOCK_* constants use Carp; use vars qw( @ISA ); @ISA = qw( IO::LockedFile ); ###################### # lock ###################### sub lock { my $self = shift; my $lock_type = $self->is_writable() ? LOCK_EX : LOCK_SH; my $got_lock = 0; if ( ! $self->should_block() ) { $got_lock = flock( $self, $lock_type | LOCK_NB ); } else { $got_lock = flock($self, $lock_type) or croak( "Cannot lock: $!"); } $self->SUPER::lock() if ($got_lock); return $got_lock; } ###################### # unlock ###################### sub unlock { my $self = shift; flock($self, LOCK_UN); # or croak( ref( $self ) . ": Cannot unlock: $!"); $self->SUPER::unlock; } 1; __END__ ########################################################################### =head1 NAME IO::LockedFile::Flock Class implements the IO::LockedFile class for the Flock scheme. =head1 SYNOPSIS See IO::LockedFile; =head1 DESCRIPTION This class implements the two methods lock and unlock for the Flock scheme. =head1 AUTHORS Rani Pinchuk, rani@cpan.org Rob Napier, rnapier@employees.org =head1 COPYRIGHT Copyright (c) 2001-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L =cut perl5/IO/LockedFile.pm000044400000037150152462503210010445 0ustar00package IO::LockedFile; use strict; use vars qw($VERSION @ISA); $VERSION = 0.23; use IO::File; @ISA = ("IO::File"); # subclass of IO::File use strict; use Carp; # Set default options my %Options; _set_option( __PACKAGE__, ( block => 1, lock => 1, scheme => 'Flock', _locked => 0, _writable => 0 ) ); ########################### # new ########################### # the constructor sub new { my $proto = shift; # get the class name my $class = ref($proto) || $proto; my $self = $class->SUPER::new(); # the object is also file handle # Grab our options (if they're there); my $options = {}; $options = shift if ref($_[0]) eq 'HASH'; if ( exists $options->{ scheme } ) { # User-specified scheme (may have to load it) $class = join( '::', __PACKAGE__, $options->{ scheme } ); eval "require $class"; croak "Unable to load $class: $@" if $@; } elsif ( $class eq __PACKAGE__ ) { # User didn't specify anything (or subclass), so do it for her $class .= '::' . get_scheme( $class ); } bless ($self, $class); # Store our options $self->_set_option( %{ $options } ); # if receives any parameters, call our open with those parameters if (@_) { $self->open(@_) or return undef; } return $self; } # of new ############################ # open ############################ sub open { my $self = shift; my $writable = 0; if ( scalar(@_) == 1 ) { # Perl mode. Look at first character # Quick sanity check. We can't lock a pipe if (( substr( $_[0], 0, 1 ) eq '|' ) || ( substr( $_[0], -1, 1 ) eq '|' ) ) { croak "Cannot lock a pipe" } # OK, now look at first character $writable = substr( $_[0], 0, 1 ) eq '>'; } elsif ( $_[1] =~ /^\d+$/ ) { # Numeric mode require Fcntl; $writable = ( ( $_[1] & O_APPEND ) || ( $_[1] & O_CREAT ) || ( $_[1] & O_TRUNC ) ); } else { # POSIX mode (we know there were enough parameters since our # SUPER succeeded). $writable = ( $_[1] ne 'r' ); } $self->_set_writable( $writable ); # call open of the super class (IO::File) with the rest of the parameters $self->SUPER::open(@_) or return undef; if ( $self->should_lock() ) { $self->lock() or return undef; } return 1; } # of open ######################## # lock ######################## sub lock { my $self = shift; $self->_set_locked( 1 ); return 1; } # of lock ######################## # unlock ######################## sub unlock { my $self = shift; $self->_set_locked( 0 ); return 1; } # of unlock ######################## # close ######################## sub close { my $self = shift; # if the file was opened - unlock it $self->unlock() if ($self->opened() and $self->have_lock()); $self->SUPER::close(); } # of close ####################### # have_lock ####################### sub have_lock { my $self = shift; return $self->_get_option( '_locked' ); } # of have_lock ####################### # _set_locked ####################### sub _set_locked { my ( $self, $value ) = @_; return $self->_set_option( '_locked', $value ); } # of _set_locked ####################### # is_writable ####################### sub is_writable { my $self = shift; return $self->_get_option( '_writable' ); } # of is_writable ####################### # _set_writable ####################### sub _set_writable { my ( $self, $value ) = @_; return $self->_set_option( '_writable', $value ); } # of _set_writable ####################### # should_block ####################### sub should_block { my $self = shift; return $self->_get_option( 'block' ); } # of should_block ####################### # should_lock ####################### sub should_lock { my $self = shift; return $self->_get_option( 'lock' ); } # of should_lock ####################### # print ####################### sub print { my ( $self, @args ) = @_; my $was_locked = $self->have_lock(); if ( ! $was_locked ) { return 0 unless $self->lock(); } my $rc = $self->SUPER::print( @args ); $self->unlock unless $was_locked; return $rc; } # of print ####################### # truncate ####################### sub truncate { my ( $self, @args ) = @_; my $was_locked = $self->have_lock(); if ( ! $was_locked ) { return 0 unless $self->lock(); } my $rc = $self->SUPER::truncate( @args ); $self->unlock() unless $was_locked; return $rc; } # of truncate ####################### # get_scheme ####################### sub get_scheme { my $self = shift; return _get_option( $self, 'scheme' ); } # of get_scheme ####################### # DESTROY ####################### sub DESTROY { my $self = shift; # if the file was opened, close (and unlock) it $self->close; } # of DESTROY ###################### # _get_option ###################### sub _get_option { my( $self, $key ) = @_; # Is the option set here? if ( exists $Options{ $self } && exists $Options{ $self }->{ $key } ) { return $Options{ $self }->{ $key } } # If we're an object, check out class elsif ( ref( $self ) ) { return _get_option( ref( $self ), $key ); } # If we're a class other than this one, check defaults elsif ( $self ne __PACKAGE__ ) { return _get_option( __PACKAGE__, $key ); } # It's nowhere. Probably a typo else { croak "Bad option fetch: $key\n"; } } # of _get_option ###################### # _set_option ###################### sub _set_option { my( $self, %hash ) = @_; while ( my( $key, $value ) = each %hash ) { $Options{ $self }->{ $key } = $value; } } # of _set_option ###################### # import ###################### sub import { my $pkg = shift; my( %config ); if ( @_ == 1 ) { $config{ scheme } = shift; } else { %config = @_; } my $scheme = $config{ scheme } || $pkg->get_scheme; my $class = __PACKAGE__ . "::$scheme"; eval "require $class"; croak "Unable to load $class: $@" if $@; $class->_set_option( %config ); } # of import 1; __END__ ########################################################################### =head1 NAME IO::LockedFile Class - supply object methods for locking files =head1 SYNOPSIS use IO::LockedFile; # create new locked file object. $file will hold a file handle. # if the file is already locked, the method will not return until the # file is unlocked my $file = new IO::LockedFile(">locked1.txt"); # when we close the file - it become unlocked. $file->close(); # suppose we did not have the line above, we can also delete the # object, and the file is automatically unlocked and closed. $file = undef; =head1 DESCRIPTION In its simplistic use, the B class gives us the same interface of the B class with the unique difference that the files we deal with are locked using the B mechanism (using the C function). If during the running of the process, it crashed - the file will be automatically unlocked. Actually - if the B object goes out of scope, the file is automatically closed and unlocked. So, if you are just interested in having locked files with C, you can skip most of the documentation below. If, on the other hand, you are interested in locking files with other schemes then B, or you want to control the behavior of the locking (having non blocking lock for example), read on. Actually the class B is kind of abstract class. Why abstract? Because methods of this class call the methods C and C. But those methods are not really implemented in this class. They suppose to be implemented in the derived classes of B. Why "kind" of abstract? Because the constructor of this class will return an object! How abstract class can create objects? This is done by having the constructor returning object that is actually an object of one of the derived classes of B. So by default the constructor of B will return an object of B. For example, the following: use IO::LockedFile; $lock = new IO::LockedFile(">bla"); print ref($lock); Will give: IO::LockedFile::Flock So what are the conclusions here? First of all - do not be surprised to get object of derived class from the constructor of B. Secondly - by changing the default behavior of the constructor of B, we can get object of other class which means that we have a locked file that is locked with other scheme. The default behavior of the constructor is determined by the global options. We can access this global options, or the options per object using the method C and C. We can set the global options in the use line: use IO::LockedFile 'Flock'; # set the default scheme to be Flock use IO::LockedFile ( scheme => Flock ); We can also set the options of a new object by passing the options to the constructor, as we will see below. We can change the options of an existing object by using the C method. Which options are available? =over 4 =item I The I let us define which derived class we use for the object we create. See below which derived classes are available. The default scheme is 'Flock'. =item I The I option can be 1 or 0 (true or false). If it is 1, a call to the C method or to the constructor will be blocked if the file we try to open is already locked. This means that those methods will not return till the file is unlocked. If the value of the I option is 0, the C and the constructor will return immediately in any case. If the file is locked, those methods will return undef. The default value of the I option is 1. =item I The I option can be 1 or 0 (true or false). It defines if the file we open when we create the object will be opened locked. Sometimes, we want to have a file that can be locked, yet we do not want to open it locked from the beginning. For example if we want to print into a log file, usually we want to lock that file only when we print into it. Yet, it might be that when we open the file in the beginning we do not print into it immediately. In that case we will prefer to open the file as unlocked, and later we will lock it when needed. The default value of the I option is 1. =back There might be extra options that are used by one of the derived classes. So according to the scheme you choose to use, please look in the manual page of the class that implement that scheme. Finally, some information that is connected to a certain scheme will be found in the classes that are derived from this class. For example, compatibility issues will be discussed in each derived classes. The classes that currently implement the interface that B defines are: =over 4 =item * B =back =head1 CONSTRUCTOR =over 4 =item new ( FILENAME [,MODE [,PERMS]] ) Creates an object that belong to one of the derived classes of C. If it receives any parameters, they are passed to the method C. if the C fails, the object is destroyed. Otherwise, it is returned to the caller. The object will be the file handle of that opened file. =item new ( OPTIONS, FILENAME [,MODE [,PERMS]] ) This version of the constructor is the same as above, with the difference that we send as the first parameter a reference to a hash - OPTIONS. This hash let us change for this object only, the options from the default options. So for example if we want to change the I option from its default we can do it as follow: $file = new IO::LockedFile( { lock => 0 }, ">locked_later.txt" ); =back =head1 METHODS =over 4 =item open ( FILENAME [,MODE [,PERMS]] ) The method let us open the file FILENAME. By default, the file will be opened as a locked file, and if the file that is opened is already locked, the method will not return until the file is unlocked. Of course this default behavior can be controlled by setting other options. The object will be the file handle of that opened file. The parameters that should be provided to this method are the same as the parameters that the method C of B accepts. (like ">file.txt" for example). Note that the open method checks if the file is opened for reading or for writing, and only then calls the lock method of the derived class that is being used. This way, for example, when using the B scheme, the lock will be a shared lock for a file that is being read, and exclusive lock for a file that is opened to be write. =item close ( ) The file will be closed and unlocked. The method returns the same as the close method of B. =item lock ( ) Practically this method does nothing, and returns 1 (true). This method will be overridden by the derived class that implements the scheme we use. When it is overridden, the method suppose to lock the file according to the scheme we use. If the file is already locked, and the I option is 1 (true), the method will not return until the file is unlocked, and locked again by the method. If the I option is 0 (false), the method will return 0 immediately. Besides, the lock method is aware if the file was opened for reading or for writing. Thus, for example, when using the B scheme, the method will create a shared lock for a file that is being read, and exclusive lock for a file that is opened to be write. =item unlock ( ) Practically this method does nothing, and returns 1 (true). This method will be overridden by the derived class that implements the scheme we use. When it is overridden, the method suppose to unlock the file according to the scheme we use, and return 1 (true) on success and 0 (false) on failure. =item have_lock ( ) Will return 1 (true) if the file is already locked by this object. Will return 0 (false) otherwise. Note that this will not tell us anything about the situation of the file itself - thus we should not use this method in order to check if the file is locked by someone else. =item print ( ) This method is exactly like the C method of B, with the difference that when using this method, if the file is unlocked, then before printing to it, it will be locked and afterward it will be unlocked. =item truncate ( ) This method is exactly like the C method of B, with the difference that when using this method, if the file is unlocked, then before truncating it, it will be locked and afterward it will be unlocked. =item is_writable ( ) This method will return 1 (true) if the file was opened to write. Will return 0 (false) otherwise. =item should_block ( ) This method will return 1 (true) if the block option set to 1. Will return 0 (false) otherwise. =item should_lock ( ) This method will return 1 (true) if the lock option set to 1. Will return 0 (false) otherwise. =item get_scheme ( ) This method will return the name of the scheme that is currently used. =back =head1 AUTHORS Rani Pinchuk, rani@cpan.org Rob Napier, rnapier@employees.org =head1 COPYRIGHT Copyright (c) 2001-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L =cut perl5/Expect.pm000044400000304137152462503210007367 0ustar00# -*-cperl-*- # This module is copyrighted as per the usual perl legalese: # Copyright (c) 1997 Austin Schutz. # expect() interface & functionality enhancements (c) 1999 Roland Giersig. # # All rights reserved. This program is free software; you can # redistribute it and/or modify it under the same terms as Perl # itself. # # Don't blame/flame me if you bust your stuff. # Austin Schutz # # This module now is maintained by # Dave Jacoby # use 5.006; package Expect; use strict; use warnings; use IO::Pty 1.11; # We need make_slave_controlling_terminal() use IO::Tty; use POSIX qw(:sys_wait_h :unistd_h); # For WNOHANG and isatty use Fcntl qw(:DEFAULT); # For checking file handle settings. use Carp qw(cluck croak carp confess); use IO::Handle (); use Exporter qw(import); use Errno; # This is necessary to make routines within Expect work. @Expect::ISA = qw(IO::Pty); @Expect::EXPORT = qw(expect exp_continue exp_continue_timeout); BEGIN { $Expect::VERSION = '1.35'; # These are defaults which may be changed per object, or set as # the user wishes. # This will be unset, since the default behavior differs between # spawned processes and initialized filehandles. # $Expect::Log_Stdout = 1; $Expect::Log_Group = 1; $Expect::Debug = 0; $Expect::Exp_Max_Accum = 0; # unlimited $Expect::Exp_Internal = 0; $Expect::IgnoreEintr = 0; $Expect::Manual_Stty = 0; $Expect::Multiline_Matching = 1; $Expect::Do_Soft_Close = 0; @Expect::Before_List = (); @Expect::After_List = (); %Expect::Spawned_PIDs = (); } sub version { my ($version) = @_; warn "Version $version is later than $Expect::VERSION. It may not be supported" if ( defined($version) && ( $version > $Expect::VERSION ) ); die "Versions before 1.03 are not supported in this release" if ( ( defined($version) ) && ( $version < 1.03 ) ); return $Expect::VERSION; } sub new { my ($class, @args) = @_; $class = ref($class) if ref($class); # so we can be called as $exp->new() # Create the pty which we will use to pass process info. my ($self) = IO::Pty->new; die "$class: Could not assign a pty" unless $self; bless $self => $class; $self->autoflush(1); # This is defined here since the default is different for # initialized handles as opposed to spawned processes. ${*$self}{exp_Log_Stdout} = 1; $self->_init_vars(); if (@args) { # we got add'l parms, so pass them to spawn return $self->spawn(@args); } return $self; } sub spawn { my ($class, @cmd) = @_; # spawn is passed command line args. my $self; if ( ref($class) ) { $self = $class; } else { $self = $class->new(); } croak "Cannot reuse an object with an already spawned command" if exists ${*$self}{"exp_Command"}; ${*$self}{"exp_Command"} = \@cmd; # set up pipe to detect childs exec error pipe( FROM_CHILD, TO_PARENT ) or die "Cannot open pipe: $!"; pipe( FROM_PARENT, TO_CHILD ) or die "Cannot open pipe: $!"; TO_PARENT->autoflush(1); TO_CHILD->autoflush(1); eval { fcntl( TO_PARENT, Fcntl::F_SETFD, Fcntl::FD_CLOEXEC ); }; my $pid = fork; unless ( defined($pid) ) { warn "Cannot fork: $!" if $^W; return; } if ($pid) { # parent my $errno; ${*$self}{exp_Pid} = $pid; close TO_PARENT; close FROM_PARENT; $self->close_slave(); $self->set_raw() if $self->raw_pty and isatty($self); close TO_CHILD; # so child gets EOF and can go ahead # now wait for child exec (eof due to close-on-exit) or exec error my $errstatus = sysread( FROM_CHILD, $errno, 256 ); die "Cannot sync with child: $!" if not defined $errstatus; close FROM_CHILD; if ($errstatus) { $! = $errno + 0; warn "Cannot exec(@cmd): $!\n" if $^W; return; } } else { # child close FROM_CHILD; close TO_CHILD; $self->make_slave_controlling_terminal(); my $slv = $self->slave() or die "Cannot get slave: $!"; $slv->set_raw() if $self->raw_pty; close($self); # wait for parent before we detach my $buffer; my $errstatus = sysread( FROM_PARENT, $buffer, 256 ); die "Cannot sync with parent: $!" if not defined $errstatus; close FROM_PARENT; close(STDIN); open( STDIN, "<&" . $slv->fileno() ) or die "Couldn't reopen STDIN for reading, $!\n"; close(STDOUT); open( STDOUT, ">&" . $slv->fileno() ) or die "Couldn't reopen STDOUT for writing, $!\n"; close(STDERR); open( STDERR, ">&" . $slv->fileno() ) or die "Couldn't reopen STDERR for writing, $!\n"; { exec(@cmd) }; print TO_PARENT $! + 0; die "Cannot exec(@cmd): $!\n"; } # This is sort of for code compatibility, and to make debugging a little # easier. By code compatibility I mean that previously the process's # handle was referenced by $process{Pty_Handle} instead of just $process. # This is almost like 'naming' the handle to the process. # I think this also reflects Tcl Expect-like behavior. ${*$self}{exp_Pty_Handle} = "spawn id(" . $self->fileno() . ")"; if ( ( ${*$self}{"exp_Debug"} ) or ( ${*$self}{"exp_Exp_Internal"} ) ) { cluck( "Spawned '@cmd'\r\n", "\t${*$self}{exp_Pty_Handle}\r\n", "\tPid: ${*$self}{exp_Pid}\r\n", "\tTty: " . $self->SUPER::ttyname() . "\r\n", ); } $Expect::Spawned_PIDs{ ${*$self}{exp_Pid} } = undef; return $self; } sub exp_init { my ($class, $self) = @_; # take a filehandle, for use later with expect() or interconnect() . # All the functions are written for reading from a tty, so if the naming # scheme looks odd, that's why. bless $self, $class; croak "exp_init not passed a file object, stopped" unless defined( $self->fileno() ); $self->autoflush(1); # Define standard variables.. debug states, etc. $self->_init_vars(); # Turn of logging. By default we don't want crap from a file to get spewed # on screen as we read it. ${*$self}{exp_Log_Stdout} = 0; ${*$self}{exp_Pty_Handle} = "handle id(" . $self->fileno() . ")"; ${*$self}{exp_Pty_Handle} = "STDIN" if $self->fileno() == fileno(STDIN); print STDERR "Initialized ${*$self}{exp_Pty_Handle}.'\r\n" if ${*$self}{"exp_Debug"}; return $self; } # make an alias *init = \&exp_init; ###################################################################### # We're happy OOP people. No direct access to stuff. # For standard read-writeable parameters, we define some autoload magic... my %Writeable_Vars = ( debug => 'exp_Debug', exp_internal => 'exp_Exp_Internal', do_soft_close => 'exp_Do_Soft_Close', max_accum => 'exp_Max_Accum', match_max => 'exp_Max_Accum', notransfer => 'exp_NoTransfer', log_stdout => 'exp_Log_Stdout', log_user => 'exp_Log_Stdout', log_group => 'exp_Log_Group', manual_stty => 'exp_Manual_Stty', restart_timeout_upon_receive => 'exp_Continue', raw_pty => 'exp_Raw_Pty', ); my %Readable_Vars = ( pid => 'exp_Pid', exp_pid => 'exp_Pid', exp_match_number => 'exp_Match_Number', match_number => 'exp_Match_Number', exp_error => 'exp_Error', error => 'exp_Error', exp_command => 'exp_Command', command => 'exp_Command', exp_match => 'exp_Match', match => 'exp_Match', exp_matchlist => 'exp_Matchlist', matchlist => 'exp_Matchlist', exp_before => 'exp_Before', before => 'exp_Before', exp_after => 'exp_After', after => 'exp_After', exp_exitstatus => 'exp_Exit', exitstatus => 'exp_Exit', exp_pty_handle => 'exp_Pty_Handle', pty_handle => 'exp_Pty_Handle', exp_logfile => 'exp_Log_File', logfile => 'exp_Log_File', %Writeable_Vars, ); sub AUTOLOAD { my ($self, @args) = @_; my $type = ref($self) or croak "$self is not an object"; use vars qw($AUTOLOAD); my $name = $AUTOLOAD; $name =~ s/.*:://; # strip fully-qualified portion unless ( exists $Readable_Vars{$name} ) { croak "ERROR: cannot find method `$name' in class $type"; } my $varname = $Readable_Vars{$name}; my $tmp; $tmp = ${*$self}{$varname} if exists ${*$self}{$varname}; if (@args) { if ( exists $Writeable_Vars{$name} ) { my $ref = ref($tmp); if ( $ref eq 'ARRAY' ) { ${*$self}{$varname} = [@args]; } elsif ( $ref eq 'HASH' ) { ${*$self}{$varname} = {@args}; } else { ${*$self}{$varname} = shift @args; } } else { carp "Trying to set read-only variable `$name'" if $^W; } } my $ref = ref($tmp); return ( wantarray ? @{$tmp} : $tmp ) if ( $ref eq 'ARRAY' ); return ( wantarray ? %{$tmp} : $tmp ) if ( $ref eq 'HASH' ); return $tmp; } ###################################################################### sub set_seq { my ( $self, $escape_sequence, $function, $params, @args ) = @_; # Set an escape sequence/function combo for a read handle for interconnect. # Ex: $read_handle->set_seq('',\&function,\@parameters); ${ ${*$self}{exp_Function} }{$escape_sequence} = $function; if ( ( !defined($function) ) || ( $function eq 'undef' ) ) { ${ ${*$self}{exp_Function} }{$escape_sequence} = \&_undef; } ${ ${*$self}{exp_Parameters} }{$escape_sequence} = $params; # This'll be a joy to execute. :) if ( ${*$self}{"exp_Debug"} ) { print STDERR "Escape seq. '" . $escape_sequence; print STDERR "' function for ${*$self}{exp_Pty_Handle} set to '"; print STDERR ${ ${*$self}{exp_Function} }{$escape_sequence}; print STDERR "(" . join( ',', @args ) . ")'\r\n"; } } sub set_group { my ($self, @args) = @_; # Make sure we can read from the read handle if ( !defined( $args[0] ) ) { if ( defined( ${*$self}{exp_Listen_Group} ) ) { return @{ ${*$self}{exp_Listen_Group} }; } else { # Refrain from referencing an undef return; } } @{ ${*$self}{exp_Listen_Group} } = (); if ( $self->_get_mode() !~ 'r' ) { warn( "Attempting to set a handle group on ${*$self}{exp_Pty_Handle}, ", "a non-readable handle!\r\n" ); } while ( my $write_handle = shift @args ) { if ( $write_handle->_get_mode() !~ 'w' ) { warn( "Attempting to set a non-writeable listen handle ", "${*$write_handle}{exp_Pty_handle} for ", "${*$self}{exp_Pty_Handle}!\r\n" ); } push( @{ ${*$self}{exp_Listen_Group} }, $write_handle ); } } sub log_file { my ($self, $file, $mode) = @_; $mode ||= "a"; return ( ${*$self}{exp_Log_File} ) if @_ < 2; # we got no param, return filehandle # $e->log_file(undef) is an acceptable call hence we need to check the number of parameters here if ( ${*$self}{exp_Log_File} and ref( ${*$self}{exp_Log_File} ) ne 'CODE' ) { close( ${*$self}{exp_Log_File} ); } ${*$self}{exp_Log_File} = undef; return if ( not $file ); my $fh = $file; if ( not ref($file) ) { # it's a filename $fh = IO::File->new( $file, $mode ) or croak "Cannot open logfile $file: $!"; } if ( ref($file) ne 'CODE' ) { croak "Given logfile doesn't have a 'print' method" if not $fh->can("print"); $fh->autoflush(1); # so logfile is up to date } ${*$self}{exp_Log_File} = $fh; return $fh; } # I'm going to leave this here in case I might need to change something. # Previously this was calling `stty`, in a most bastardized manner. sub exp_stty { my ($self) = shift; my ($mode) = "@_"; return unless defined $mode; if ( not defined $INC{"IO/Stty.pm"} ) { carp "IO::Stty not installed, cannot change mode"; return; } if ( ${*$self}{"exp_Debug"} ) { print STDERR "Setting ${*$self}{exp_Pty_Handle} to tty mode '$mode'\r\n"; } unless ( POSIX::isatty($self) ) { if ( ${*$self}{"exp_Debug"} or $^W ) { warn "${*$self}{exp_Pty_Handle} is not a tty. Not changing mode"; } return ''; # No undef to avoid warnings elsewhere. } IO::Stty::stty( $self, split( /\s/, $mode ) ); } *stty = \&exp_stty; # If we want to clear the buffer. Otherwise Accum will grow during send_slow # etc. and contain the remainder after matches. sub clear_accum { my ($self) = @_; return $self->set_accum(''); } sub set_accum { my ($self, $accum) = @_; my $old_accum = ${*$self}{exp_Accum}; ${*$self}{exp_Accum} = $accum; # return the contents of the accumulator. return $old_accum; } sub get_accum { my ($self) = @_; return ${*$self}{exp_Accum}; } ###################################################################### # define constants for pattern subs sub exp_continue {"exp_continue"} sub exp_continue_timeout {"exp_continue_timeout"} ###################################################################### # Expect on multiple objects at once. # # Call as Expect::expect($timeout, -i => \@exp_list, @patternlist, # -i => $exp, @pattern_list, ...); # or $exp->expect($timeout, @patternlist, -i => \@exp_list, @patternlist, # -i => $exp, @pattern_list, ...); # # Patterns are arrays that consist of # [ $pattern_type, $pattern, $sub, @subparms ] # # Optional $pattern_type is '-re' (RegExp, default) or '-ex' (exact); # # $sub is optional CODE ref, which is called as &{$sub}($exp, @subparms) # if pattern matched; may return exp_continue or exp_continue_timeout. # # Old-style syntax (pure pattern strings with optional type) also supported. # sub expect { my $self; print STDERR ("expect(@_) called...\n") if $Expect::Debug; if ( defined( $_[0] ) ) { if ( ref( $_[0] ) and $_[0]->isa('Expect') ) { $self = shift; } elsif ( $_[0] eq 'Expect' ) { shift; # or as Expect->expect } } croak "expect(): not enough arguments, should be expect(timeout, [patterns...])" if @_ < 1; my $timeout = shift; my $timeout_hook = undef; my @object_list; my %patterns; my @pattern_list; my @timeout_list; my $curr_list; if ($self) { $curr_list = [$self]; } else { # called directly, so first parameter must be '-i' to establish # object list. $curr_list = []; croak "expect(): ERROR: if called directly (not as \$obj->expect(...), but as Expect::expect(...), first parameter MUST be '-i' to set an object (list) for the patterns to work on." if ( $_[0] ne '-i' ); } # Let's make a list of patterns wanting to be evaled as regexps. my $parm; my $parm_nr = 1; while ( defined( $parm = shift ) ) { print STDERR ("expect(): handling param '$parm'...\n") if $Expect::Debug; if ( ref($parm) ) { if ( ref($parm) eq 'ARRAY' ) { my $err = _add_patterns_to_list( \@pattern_list, \@timeout_list, $parm_nr, $parm ); carp( "expect(): Warning: multiple `timeout' patterns (", scalar(@timeout_list), ").\r\n" ) if @timeout_list > 1; $timeout_hook = $timeout_list[-1] if $timeout_list[-1]; croak $err if $err; $parm_nr++; } else { croak("expect(): Unknown pattern ref $parm"); } } else { # not a ref, is an option or raw pattern if ( substr( $parm, 0, 1 ) eq '-' ) { # it's an option print STDERR ("expect(): handling option '$parm'...\n") if $Expect::Debug; if ( $parm eq '-i' ) { # first add collected patterns to object list if ( scalar(@$curr_list) ) { push @object_list, $curr_list if not exists $patterns{"$curr_list"}; push @{ $patterns{"$curr_list"} }, @pattern_list; @pattern_list = (); } # now put parm(s) into current object list if ( ref( $_[0] ) eq 'ARRAY' ) { $curr_list = shift; } else { $curr_list = [shift]; } } elsif ( $parm eq '-re' or $parm eq '-ex' ) { if ( ref( $_[1] ) eq 'CODE' ) { push @pattern_list, [ $parm_nr, $parm, shift, shift ]; } else { push @pattern_list, [ $parm_nr, $parm, shift, undef ]; } $parm_nr++; } else { croak("Unknown option $parm"); } } else { # a plain pattern, check if it is followed by a CODE ref if ( ref( $_[0] ) eq 'CODE' ) { if ( $parm eq 'timeout' ) { push @timeout_list, shift; carp( "expect(): Warning: multiple `timeout' patterns (", scalar(@timeout_list), ").\r\n" ) if @timeout_list > 1; $timeout_hook = $timeout_list[-1] if $timeout_list[-1]; } elsif ( $parm eq 'eof' ) { push @pattern_list, [ $parm_nr, "-$parm", undef, shift ]; } else { push @pattern_list, [ $parm_nr, '-ex', $parm, shift ]; } } else { print STDERR ("expect(): exact match '$parm'...\n") if $Expect::Debug; push @pattern_list, [ $parm_nr, '-ex', $parm, undef ]; } $parm_nr++; } } } # add rest of collected patterns to object list carp "expect(): Empty object list" unless $curr_list; push @object_list, $curr_list if not exists $patterns{"$curr_list"}; push @{ $patterns{"$curr_list"} }, @pattern_list; my $debug = $self ? ${*$self}{exp_Debug} : $Expect::Debug; my $internal = $self ? ${*$self}{exp_Exp_Internal} : $Expect::Exp_Internal; # now start matching... if (@Expect::Before_List) { print STDERR ("Starting BEFORE pattern matching...\r\n") if ( $debug or $internal ); _multi_expect( 0, undef, @Expect::Before_List ); } cluck("Starting EXPECT pattern matching...\r\n") if ( $debug or $internal ); my @ret; @ret = _multi_expect( $timeout, $timeout_hook, map { [ $_, @{ $patterns{"$_"} } ] } @object_list ); if (@Expect::After_List) { print STDERR ("Starting AFTER pattern matching...\r\n") if ( $debug or $internal ); _multi_expect( 0, undef, @Expect::After_List ); } return wantarray ? @ret : $ret[0]; } ###################################################################### # the real workhorse # sub _multi_expect { my ($timeout, $timeout_hook, @params) = @_; if ($timeout_hook) { croak "Unknown timeout_hook type $timeout_hook" unless ( ref($timeout_hook) eq 'CODE' or ref($timeout_hook) eq 'ARRAY' ); } foreach my $pat (@params) { my @patterns = @{$pat}[ 1 .. $#{$pat} ]; foreach my $exp ( @{ $pat->[0] } ) { ${*$exp}{exp_New_Data} = 1; # first round we always try to match if ( exists ${*$exp}{"exp_Max_Accum"} and ${*$exp}{"exp_Max_Accum"} ) { ${*$exp}{exp_Accum} = $exp->_trim_length( ${*$exp}{exp_Accum}, ${*$exp}{exp_Max_Accum} ); } print STDERR ( "${*$exp}{exp_Pty_Handle}: beginning expect.\r\n", "\tTimeout: ", ( defined($timeout) ? $timeout : "unlimited" ), " seconds.\r\n", "\tCurrent time: " . localtime() . "\r\n", ) if $Expect::Debug; # What are we expecting? What do you expect? :-) if ( ${*$exp}{exp_Exp_Internal} ) { print STDERR "${*$exp}{exp_Pty_Handle}: list of patterns:\r\n"; foreach my $pattern (@patterns) { print STDERR ( ' ', defined( $pattern->[0] ) ? '#' . $pattern->[0] . ': ' : '', $pattern->[1], " `", _make_readable( $pattern->[2] ), "'\r\n" ); } print STDERR "\r\n"; } } } my $successful_pattern; my $exp_matched; my $err; my $before; my $after; my $match; my @matchlist; # Set the last loop time to now for time comparisons at end of loop. my $start_loop_time = time(); my $exp_cont = 1; READLOOP: while ($exp_cont) { $exp_cont = 1; $err = ""; my $rmask = ''; my $time_left = undef; if ( defined $timeout ) { $time_left = $timeout - ( time() - $start_loop_time ); $time_left = 0 if $time_left < 0; } $exp_matched = undef; # Test for a match first so we can test the current Accum w/out # worrying about an EOF. foreach my $pat (@params) { my @patterns = @{$pat}[ 1 .. $#{$pat} ]; foreach my $exp ( @{ $pat->[0] } ) { # build mask for select in next section... my $fn = $exp->fileno(); vec( $rmask, $fn, 1 ) = 1 if defined $fn; next unless ${*$exp}{exp_New_Data}; # clear error status ${*$exp}{exp_Error} = undef; ${*$exp}{exp_After} = undef; ${*$exp}{exp_Match_Number} = undef; ${*$exp}{exp_Match} = undef; # This could be huge. We should attempt to do something # about this. Because the output is used for debugging # I'm of the opinion that showing smaller amounts if the # total is huge should be ok. # Thus the 'trim_length' print STDERR ( "\r\n${*$exp}{exp_Pty_Handle}: Does `", $exp->_trim_length( _make_readable( ${*$exp}{exp_Accum} ) ), "'\r\nmatch:\r\n" ) if ${*$exp}{exp_Exp_Internal}; # we don't keep the parameter number anymore # (clashes with before & after), instead the parameter number is # stored inside the pattern; we keep the pattern ref # and look up the number later. foreach my $pattern (@patterns) { print STDERR ( " pattern", defined( $pattern->[0] ) ? ' #' . $pattern->[0] : '', ": ", $pattern->[1], " `", _make_readable( $pattern->[2] ), "'? " ) if ( ${*$exp}{exp_Exp_Internal} ); # Matching exactly if ( $pattern->[1] eq '-ex' ) { my $match_index = index( ${*$exp}{exp_Accum}, $pattern->[2] ); # We matched if $match_index > -1 if ( $match_index > -1 ) { $before = substr( ${*$exp}{exp_Accum}, 0, $match_index ); $match = substr( ${*$exp}{exp_Accum}, $match_index, length( $pattern->[2] ) ); $after = substr( ${*$exp}{exp_Accum}, $match_index + length( $pattern->[2] ) ); ${*$exp}{exp_Before} = $before; ${*$exp}{exp_Match} = $match; ${*$exp}{exp_After} = $after; ${*$exp}{exp_Match_Number} = $pattern->[0]; $exp_matched = $exp; } } elsif ( $pattern->[1] eq '-re' ) { if ($Expect::Multiline_Matching) { @matchlist = ( ${*$exp}{exp_Accum} =~ m/($pattern->[2])/m); } else { @matchlist = ( ${*$exp}{exp_Accum} =~ m/($pattern->[2])/); } if (@matchlist) { # Matching regexp $match = shift @matchlist; my $start = index ${*$exp}{exp_Accum}, $match; die 'The match could not be found' if $start == -1; $before = substr ${*$exp}{exp_Accum}, 0, $start; $after = substr ${*$exp}{exp_Accum}, $start + length($match); ${*$exp}{exp_Before} = $before; ${*$exp}{exp_Match} = $match; ${*$exp}{exp_After} = $after; #pop @matchlist; # remove kludged empty bracket from end @{ ${*$exp}{exp_Matchlist} } = @matchlist; ${*$exp}{exp_Match_Number} = $pattern->[0]; $exp_matched = $exp; } } else { # 'timeout' or 'eof' } if ($exp_matched) { ${*$exp}{exp_Accum} = $after unless ${*$exp}{exp_NoTransfer}; print STDERR "YES!!\r\n" if ${*$exp}{exp_Exp_Internal}; print STDERR ( " Before match string: `", $exp->_trim_length( _make_readable( ($before) ) ), "'\r\n", " Match string: `", _make_readable($match), "'\r\n", " After match string: `", $exp->_trim_length( _make_readable( ($after) ) ), "'\r\n", " Matchlist: (", join( ", ", map { "`" . $exp->_trim_length( _make_readable( ($_) ) ) . "'" } @matchlist, ), ")\r\n", ) if ( ${*$exp}{exp_Exp_Internal} ); # call hook function if defined if ( $pattern->[3] ) { print STDERR ( "Calling hook $pattern->[3]...\r\n", ) if ( ${*$exp}{exp_Exp_Internal} or $Expect::Debug ); if ( $#{$pattern} > 3 ) { # call with parameters if given $exp_cont = &{ $pattern->[3] }( $exp, @{$pattern}[ 4 .. $#{$pattern} ] ); } else { $exp_cont = &{ $pattern->[3] }($exp); } } if ( $exp_cont and $exp_cont eq exp_continue ) { print STDERR ("Continuing expect, restarting timeout...\r\n") if ( ${*$exp}{exp_Exp_Internal} or $Expect::Debug ); $start_loop_time = time(); # restart timeout count next READLOOP; } elsif ( $exp_cont and $exp_cont eq exp_continue_timeout ) { print STDERR ("Continuing expect...\r\n") if ( ${*$exp}{exp_Exp_Internal} or $Expect::Debug ); next READLOOP; } last READLOOP; } print STDERR "No.\r\n" if ${*$exp}{exp_Exp_Internal}; } print STDERR "\r\n" if ${*$exp}{exp_Exp_Internal}; # don't have to match again until we get new data ${*$exp}{exp_New_Data} = 0; } } # End of matching section # No match, let's see what is pending on the filehandles... print STDERR ( "Waiting for new data (", defined($time_left) ? $time_left : 'unlimited', " seconds)...\r\n", ) if ( $Expect::Exp_Internal or $Expect::Debug ); my $nfound; SELECT: { $nfound = select( $rmask, undef, undef, $time_left ); if ( $nfound < 0 ) { if ( $!{EINTR} and $Expect::IgnoreEintr ) { print STDERR ("ignoring EINTR, restarting select()...\r\n") if ( $Expect::Exp_Internal or $Expect::Debug ); next SELECT; } print STDERR ("select() returned error code '$!'\r\n") if ( $Expect::Exp_Internal or $Expect::Debug ); # returned error $err = "4:$!"; last READLOOP; } } # go until we don't find something (== timeout). if ( $nfound == 0 ) { # No pattern, no EOF. Did we time out? $err = "1:TIMEOUT"; foreach my $pat (@params) { foreach my $exp ( @{ $pat->[0] } ) { $before = ${*$exp}{exp_Before} = ${*$exp}{exp_Accum}; next if not defined $exp->fileno(); # skip already closed ${*$exp}{exp_Error} = $err unless ${*$exp}{exp_Error}; } } print STDERR ("TIMEOUT\r\n") if ( $Expect::Debug or $Expect::Exp_Internal ); if ($timeout_hook) { my $ret; print STDERR ("Calling timeout function $timeout_hook...\r\n") if ( $Expect::Debug or $Expect::Exp_Internal ); if ( ref($timeout_hook) eq 'CODE' ) { $ret = &{$timeout_hook}( $params[0]->[0] ); } else { if ( $#{$timeout_hook} > 3 ) { $ret = &{ $timeout_hook->[3] }( $params[0]->[0], @{$timeout_hook}[ 4 .. $#{$timeout_hook} ] ); } else { $ret = &{ $timeout_hook->[3] }( $params[0]->[0] ); } } if ( $ret and $ret eq exp_continue ) { $start_loop_time = time(); # restart timeout count next READLOOP; } } last READLOOP; } my @bits = split( //, unpack( 'b*', $rmask ) ); foreach my $pat (@params) { foreach my $exp ( @{ $pat->[0] } ) { next if not defined $exp->fileno(); # skip already closed if ( $bits[ $exp->fileno() ] ) { print STDERR ("${*$exp}{exp_Pty_Handle}: new data.\r\n") if $Expect::Debug; # read in what we found. my $buffer; my $nread = sysread( $exp, $buffer, 2048 ); # Make errors (nread undef) show up as EOF. $nread = 0 unless defined($nread); if ( $nread == 0 ) { print STDERR ("${*$exp}{exp_Pty_Handle}: EOF\r\n") if ($Expect::Debug); $before = ${*$exp}{exp_Before} = $exp->clear_accum(); $err = "2:EOF"; ${*$exp}{exp_Error} = $err; ${*$exp}{exp_Has_EOF} = 1; $exp_cont = undef; foreach my $eof_pat ( grep { $_->[1] eq '-eof' } @{$pat}[ 1 .. $#{$pat} ] ) { my $ret; print STDERR ( "Calling EOF hook $eof_pat->[3]...\r\n", ) if ($Expect::Debug); if ( $#{$eof_pat} > 3 ) { # call with parameters if given $ret = &{ $eof_pat->[3] }( $exp, @{$eof_pat}[ 4 .. $#{$eof_pat} ] ); } else { $ret = &{ $eof_pat->[3] }($exp); } if ($ret and ( $ret eq exp_continue or $ret eq exp_continue_timeout ) ) { $exp_cont = $ret; } } # is it dead? if ( defined( ${*$exp}{exp_Pid} ) ) { my $ret = waitpid( ${*$exp}{exp_Pid}, POSIX::WNOHANG ); if ( $ret == ${*$exp}{exp_Pid} ) { printf STDERR ( "%s: exit(0x%02X)\r\n", ${*$exp}{exp_Pty_Handle}, $? ) if ($Expect::Debug); $err = "3:Child PID ${*$exp}{exp_Pid} exited with status $?"; ${*$exp}{exp_Error} = $err; ${*$exp}{exp_Exit} = $?; delete $Expect::Spawned_PIDs{ ${*$exp}{exp_Pid} }; ${*$exp}{exp_Pid} = undef; } } print STDERR ("${*$exp}{exp_Pty_Handle}: closing...\r\n") if ($Expect::Debug); $exp->hard_close(); next; } print STDERR ("${*$exp}{exp_Pty_Handle}: read $nread byte(s).\r\n") if ($Expect::Debug); # ugly hack for broken solaris ttys that spew # into our pretty output $buffer =~ s/ \cH//g if not ${*$exp}{exp_Raw_Pty}; # Append it to the accumulator. ${*$exp}{exp_Accum} .= $buffer; if ( exists ${*$exp}{exp_Max_Accum} and ${*$exp}{exp_Max_Accum} ) { ${*$exp}{exp_Accum} = $exp->_trim_length( ${*$exp}{exp_Accum}, ${*$exp}{exp_Max_Accum} ); } ${*$exp}{exp_New_Data} = 1; # next round we try to match again $exp_cont = exp_continue if ( exists ${*$exp}{exp_Continue} and ${*$exp}{exp_Continue} ); # Now propagate what we have read to other listeners... $exp->_print_handles($buffer); # End handle reading section. } } } # end read loop $start_loop_time = time() # restart timeout count if ( $exp_cont and $exp_cont eq exp_continue ); } # End READLOOP # Post loop. Do we have anything? # Tell us status if ( $Expect::Debug or $Expect::Exp_Internal ) { if ($exp_matched) { print STDERR ( "Returning from expect ", ${*$exp_matched}{exp_Error} ? 'un' : '', "successfully.", ${*$exp_matched}{exp_Error} ? "\r\n Error: ${*$exp_matched}{exp_Error}." : '', "\r\n" ); } else { print STDERR ("Returning from expect with TIMEOUT or EOF\r\n"); } if ( $Expect::Debug and $exp_matched ) { print STDERR " ${*$exp_matched}{exp_Pty_Handle}: accumulator: `"; if ( ${*$exp_matched}{exp_Error} ) { print STDERR ( $exp_matched->_trim_length( _make_readable( ${*$exp_matched}{exp_Before} ) ), "'\r\n" ); } else { print STDERR ( $exp_matched->_trim_length( _make_readable( ${*$exp_matched}{exp_Accum} ) ), "'\r\n" ); } } } if ($exp_matched) { return wantarray ? ( ${*$exp_matched}{exp_Match_Number}, ${*$exp_matched}{exp_Error}, ${*$exp_matched}{exp_Match}, ${*$exp_matched}{exp_Before}, ${*$exp_matched}{exp_After}, $exp_matched, ) : ${*$exp_matched}{exp_Match_Number}; } return wantarray ? ( undef, $err, undef, $before, undef, undef ) : undef; } # Patterns are arrays that consist of # [ $pattern_type, $pattern, $sub, @subparms ] # optional $pattern_type is '-re' (RegExp, default) or '-ex' (exact); # $sub is optional CODE ref, which is called as &{$sub}($exp, @subparms) # if pattern matched; # the $parm_nr gets unshifted onto the array for reporting purposes. sub _add_patterns_to_list { my ($listref, $timeoutlistref,$store_parm_nr, @params) = @_; # $timeoutlistref gets timeout patterns my $parm_nr = $store_parm_nr || 1; foreach my $parm (@params) { if ( not ref($parm) eq 'ARRAY' ) { return "Parameter #$parm_nr is not an ARRAY ref."; } $parm = [@$parm]; # make copy if ( $parm->[0] =~ m/\A-/ ) { # it's an option if ( $parm->[0] ne '-re' and $parm->[0] ne '-ex' ) { return "Unknown option $parm->[0] in pattern #$parm_nr"; } } else { if ( $parm->[0] eq 'timeout' ) { if ( defined $timeoutlistref ) { splice @$parm, 0, 1, ( "-$parm->[0]", undef ); unshift @$parm, $store_parm_nr ? $parm_nr : undef; push @$timeoutlistref, $parm; } next; } elsif ( $parm->[0] eq 'eof' ) { splice @$parm, 0, 1, ( "-$parm->[0]", undef ); } else { unshift @$parm, '-re'; # defaults to RegExp } } if ( @$parm > 2 ) { if ( ref( $parm->[2] ) ne 'CODE' ) { croak( "Pattern #$parm_nr doesn't have a CODE reference", "after the pattern." ); } } else { push @$parm, undef; # make sure we have three elements } unshift @$parm, $store_parm_nr ? $parm_nr : undef; push @$listref, $parm; $parm_nr++; } return; } ###################################################################### # $process->interact([$in_handle],[$escape sequence]) # If you don't specify in_handle STDIN will be used. sub interact { my ($self, $infile, $escape_sequence) = @_; my $outfile; my @old_group = $self->set_group(); # If the handle is STDIN we'll # $infile->fileno == 0 should be stdin.. follow stdin rules. no strict 'subs'; # Allow bare word 'STDIN' unless ( defined($infile) ) { # We need a handle object Associated with STDIN. $infile = IO::File->new; $infile->IO::File::fdopen( STDIN, 'r' ); $outfile = IO::File->new; $outfile->IO::File::fdopen( STDOUT, 'w' ); } elsif ( fileno($infile) == fileno(STDIN) ) { # With STDIN we want output to go to stdout. $outfile = IO::File->new; $outfile->IO::File::fdopen( STDOUT, 'w' ); } else { undef($outfile); } # Here we assure ourselves we have an Expect object. my $in_object = Expect->exp_init($infile); if ( defined($outfile) ) { # as above.. we want output to go to stdout if we're given stdin. my $out_object = Expect->exp_init($outfile); $out_object->manual_stty(1); $self->set_group($out_object); } else { $self->set_group($in_object); } $in_object->set_group($self); $in_object->set_seq( $escape_sequence, undef ) if defined($escape_sequence); # interconnect normally sets stty -echo raw. Interact really sort # of implies we don't do that by default. If anyone wanted to they could # set it before calling interact, of use interconnect directly. my $old_manual_stty_val = $self->manual_stty(); $self->manual_stty(1); # I think this is right. Don't send stuff from in_obj to stdout by default. # in theory whatever 'self' is should echo what's going on. my $old_log_stdout_val = $self->log_stdout(); $self->log_stdout(0); $in_object->log_stdout(0); # Allow for the setting of an optional EOF escape function. # $in_object->set_seq('EOF',undef); # $self->set_seq('EOF',undef); Expect::interconnect( $self, $in_object ); $self->log_stdout($old_log_stdout_val); $self->set_group(@old_group); # If old_group was undef, make sure that occurs. This is a slight hack since # it modifies the value directly. # Normally an undef passed to set_group will return the current groups. # It is possible that it may be of worth to make it possible to undef # The current group without doing this. unless (@old_group) { @{ ${*$self}{exp_Listen_Group} } = (); } $self->manual_stty($old_manual_stty_val); return; } sub interconnect { my (@handles) = @_; # my ($handle)=(shift); call as Expect::interconnect($spawn1,$spawn2,...) my ( $nread ); my ( $rout, $emask, $eout ); my ( $escape_character_buffer ); my ( $read_mask, $temp_mask ) = ( '', '' ); # Get read/write handles foreach my $handle (@handles) { $temp_mask = ''; vec( $temp_mask, $handle->fileno(), 1 ) = 1; # Under Linux w/ 5.001 the next line comes up w/ 'Uninit var.'. # It appears to be impossible to make the warning go away. # doing something like $temp_mask='' unless defined ($temp_mask) # has no effect whatsoever. This may be a bug in 5.001. $read_mask = $read_mask | $temp_mask; } if ($Expect::Debug) { print STDERR "Read handles:\r\n"; foreach my $handle (@handles) { print STDERR "\tRead handle: "; print STDERR "'${*$handle}{exp_Pty_Handle}'\r\n"; print STDERR "\t\tListen Handles:"; foreach my $write_handle ( @{ ${*$handle}{exp_Listen_Group} } ) { print STDERR " '${*$write_handle}{exp_Pty_Handle}'"; } print STDERR ".\r\n"; } } # I think if we don't set raw/-echo here we may have trouble. We don't # want a bunch of echoing crap making all the handles jabber at each other. foreach my $handle (@handles) { unless ( ${*$handle}{"exp_Manual_Stty"} ) { # This is probably O/S specific. ${*$handle}{exp_Stored_Stty} = $handle->exp_stty('-g'); print STDERR "Setting tty for ${*$handle}{exp_Pty_Handle} to 'raw -echo'.\r\n" if ${*$handle}{"exp_Debug"}; $handle->exp_stty("raw -echo"); } foreach my $write_handle ( @{ ${*$handle}{exp_Listen_Group} } ) { unless ( ${*$write_handle}{"exp_Manual_Stty"} ) { ${*$write_handle}{exp_Stored_Stty} = $write_handle->exp_stty('-g'); print STDERR "Setting ${*$write_handle}{exp_Pty_Handle} to 'raw -echo'.\r\n" if ${*$handle}{"exp_Debug"}; $write_handle->exp_stty("raw -echo"); } } } print STDERR "Attempting interconnection\r\n" if $Expect::Debug; # Wait until the process dies or we get EOF # In the case of !${*$handle}{exp_Pid} it means # the handle was exp_inited instead of spawned. CONNECT_LOOP: # Go until we have a reason to stop while (1) { # test each handle to see if it's still alive. foreach my $read_handle (@handles) { waitpid( ${*$read_handle}{exp_Pid}, WNOHANG ) if ( exists( ${*$read_handle}{exp_Pid} ) and ${*$read_handle}{exp_Pid} ); if ( exists( ${*$read_handle}{exp_Pid} ) and ( ${*$read_handle}{exp_Pid} ) and ( !kill( 0, ${*$read_handle}{exp_Pid} ) ) ) { print STDERR "Got EOF (${*$read_handle}{exp_Pty_Handle} died) reading ${*$read_handle}{exp_Pty_Handle}\r\n" if ${*$read_handle}{"exp_Debug"}; last CONNECT_LOOP unless defined( ${ ${*$read_handle}{exp_Function} }{"EOF"} ); last CONNECT_LOOP unless &{ ${ ${*$read_handle}{exp_Function} }{"EOF"} } ( @{ ${ ${*$read_handle}{exp_Parameters} }{"EOF"} } ); } } # Every second? No, go until we get something from someone. my $nfound = select( $rout = $read_mask, undef, $eout = $emask, undef ); # Is there anything to share? May be -1 if interrupted by a signal... next CONNECT_LOOP if not defined $nfound or $nfound < 1; # Which handles have stuff? my @bits = split( //, unpack( 'b*', $rout ) ); $eout = 0 unless defined($eout); my @ebits = split( //, unpack( 'b*', $eout ) ); # print "Ebits: $eout\r\n"; foreach my $read_handle (@handles) { if ( $bits[ $read_handle->fileno() ] ) { $nread = sysread( $read_handle, ${*$read_handle}{exp_Pty_Buffer}, 1024 ); # Appease perl -w $nread = 0 unless defined($nread); print STDERR "interconnect: read $nread byte(s) from ${*$read_handle}{exp_Pty_Handle}.\r\n" if ${*$read_handle}{"exp_Debug"} > 1; # Test for escape seq. before printing. # Appease perl -w $escape_character_buffer = '' unless defined($escape_character_buffer); $escape_character_buffer .= ${*$read_handle}{exp_Pty_Buffer}; foreach my $escape_sequence ( keys( %{ ${*$read_handle}{exp_Function} } ) ) { print STDERR "Tested escape sequence $escape_sequence from ${*$read_handle}{exp_Pty_Handle}" if ${*$read_handle}{"exp_Debug"} > 1; # Make sure it doesn't grow out of bounds. $escape_character_buffer = $read_handle->_trim_length( $escape_character_buffer, ${*$read_handle}{"exp_Max_Accum"} ) if ( ${*$read_handle}{"exp_Max_Accum"} ); if ( $escape_character_buffer =~ /($escape_sequence)/ ) { my $match = $1; if ( ${*$read_handle}{"exp_Debug"} ) { print STDERR "\r\ninterconnect got escape sequence from ${*$read_handle}{exp_Pty_Handle}.\r\n"; # I'm going to make the esc. seq. pretty because it will # probably contain unprintable characters. print STDERR "\tEscape Sequence: '" . _trim_length( undef, _make_readable($escape_sequence) ) . "'\r\n"; print STDERR "\tMatched by string: '" . _trim_length( undef, _make_readable($match) ) . "'\r\n"; } # Print out stuff before the escape. # Keep in mind that the sequence may have been split up # over several reads. # Let's get rid of it from this read. If part of it was # in the last read there's not a lot we can do about it now. if ( ${*$read_handle}{exp_Pty_Buffer} =~ /([\w\W]*)($escape_sequence)/ ) { $read_handle->_print_handles($1); } else { $read_handle->_print_handles( ${*$read_handle}{exp_Pty_Buffer} ); } # Clear the buffer so no more matches can be made and it will # only be printed one time. ${*$read_handle}{exp_Pty_Buffer} = ''; $escape_character_buffer = ''; # Do the function here. Must return non-zero to continue. # More cool syntax. Maybe I should turn these in to objects. last CONNECT_LOOP unless &{ ${ ${*$read_handle}{exp_Function} }{$escape_sequence} } ( @{ ${ ${*$read_handle}{exp_Parameters} }{$escape_sequence} } ); } } $nread = 0 unless defined($nread); # Appease perl -w? waitpid( ${*$read_handle}{exp_Pid}, WNOHANG ) if ( defined( ${*$read_handle}{exp_Pid} ) && ${*$read_handle}{exp_Pid} ); if ( $nread == 0 ) { print STDERR "Got EOF reading ${*$read_handle}{exp_Pty_Handle}\r\n" if ${*$read_handle}{"exp_Debug"}; last CONNECT_LOOP unless defined( ${ ${*$read_handle}{exp_Function} }{"EOF"} ); last CONNECT_LOOP unless &{ ${ ${*$read_handle}{exp_Function} }{"EOF"} } ( @{ ${ ${*$read_handle}{exp_Parameters} }{"EOF"} } ); } last CONNECT_LOOP if ( $nread < 0 ); # This would be an error $read_handle->_print_handles( ${*$read_handle}{exp_Pty_Buffer} ); } # I'm removing this because I haven't determined what causes exceptions # consistently. if (0) #$ebits[$read_handle->fileno()]) { print STDERR "Got Exception reading ${*$read_handle}{exp_Pty_Handle}\r\n" if ${*$read_handle}{"exp_Debug"}; last CONNECT_LOOP unless defined( ${ ${*$read_handle}{exp_Function} }{"EOF"} ); last CONNECT_LOOP unless &{ ${ ${*$read_handle}{exp_Function} }{"EOF"} } ( @{ ${ ${*$read_handle}{exp_Parameters} }{"EOF"} } ); } } } foreach my $handle (@handles) { unless ( ${*$handle}{"exp_Manual_Stty"} ) { $handle->exp_stty( ${*$handle}{exp_Stored_Stty} ); } foreach my $write_handle ( @{ ${*$handle}{exp_Listen_Group} } ) { unless ( ${*$write_handle}{"exp_Manual_Stty"} ) { $write_handle->exp_stty( ${*$write_handle}{exp_Stored_Stty} ); } } } return; } # user can decide if log output gets also sent to logfile sub print_log_file { my ($self, @params) = @_; if ( ${*$self}{exp_Log_File} ) { if ( ref( ${*$self}{exp_Log_File} ) eq 'CODE' ) { ${*$self}{exp_Log_File}->(@params); } else { ${*$self}{exp_Log_File}->print(@params); } } return; } # we provide our own print so we can debug what gets sent to the # processes... sub print { my ( $self, @args ) = @_; return if not defined $self->fileno(); # skip if closed if ( ${*$self}{exp_Exp_Internal} ) { my $args = _make_readable( join( '', @args ) ); cluck "Sending '$args' to ${*$self}{exp_Pty_Handle}\r\n"; } foreach my $arg (@args) { while ( length($arg) > 80 ) { $self->SUPER::print( substr( $arg, 0, 80 ) ); $arg = substr( $arg, 80 ); } $self->SUPER::print($arg); } return; } # make an alias for Tcl/Expect users for a DWIM experience... *send = \&print; # This is an Expect standard. It's nice for talking to modems and the like # where from time to time they get unhappy if you send items too quickly. sub send_slow { my ($self, $sleep_time, @chunks) = @_; return if not defined $self->fileno(); # skip if closed # Flushing makes it so each character can be seen separately. my $chunk; while ( $chunk = shift @chunks ) { my @linechars = split( '', $chunk ); foreach my $char (@linechars) { # How slow? select( undef, undef, undef, $sleep_time ); print $self $char; print STDERR "Printed character \'" . _make_readable($char) . "\' to ${*$self}{exp_Pty_Handle}.\r\n" if ${*$self}{"exp_Debug"} > 1; # I think I can get away with this if I save it in accum if ( ${*$self}{"exp_Log_Stdout"} || ${*$self}{exp_Log_Group} ) { my $rmask = ""; vec( $rmask, $self->fileno(), 1 ) = 1; # .01 sec granularity should work. If we miss something it will # probably get flushed later, maybe in an expect call. while ( select( $rmask, undef, undef, .01 ) ) { my $ret = sysread( $self, ${*$self}{exp_Pty_Buffer}, 1024 ); last if not defined $ret or $ret == 0; # Is this necessary to keep? Probably.. # # if you need to expect it later. ${*$self}{exp_Accum} .= ${*$self}{exp_Pty_Buffer}; ${*$self}{exp_Accum} = $self->_trim_length( ${*$self}{exp_Accum}, ${*$self}{"exp_Max_Accum"} ) if ( ${*$self}{"exp_Max_Accum"} ); $self->_print_handles( ${*$self}{exp_Pty_Buffer} ); print STDERR "Received \'" . $self->_trim_length( _make_readable($char) ) . "\' from ${*$self}{exp_Pty_Handle}\r\n" if ${*$self}{"exp_Debug"} > 1; } } } } return; } sub test_handles { my ($timeout, @handle_list) = @_; # This should be called by Expect::test_handles($timeout,@objects); my ( $allmask, $rout ); foreach my $handle (@handle_list) { my $rmask = ''; vec( $rmask, $handle->fileno(), 1 ) = 1; $allmask = '' unless defined($allmask); $allmask = $allmask | $rmask; } my $nfound = select( $rout = $allmask, undef, undef, $timeout ); return () unless $nfound; # Which handles have stuff? my @bits = split( //, unpack( 'b*', $rout ) ); my $handle_num = 0; my @return_list = (); foreach my $handle (@handle_list) { # I go to great lengths to get perl -w to shut the hell up. if ( defined( $bits[ $handle->fileno() ] ) and ( $bits[ $handle->fileno() ] ) ) { push( @return_list, $handle_num ); } } continue { $handle_num++; } return @return_list; } # Be nice close. This should emulate what an interactive shell does after a # command finishes... sort of. We're not as patient as a shell. sub soft_close { my ($self) = @_; my ( $nfound, $nread, $rmask, $end_time, $temp_buffer ); # Give it 15 seconds to cough up an eof. cluck "Closing ${*$self}{exp_Pty_Handle}.\r\n" if ${*$self}{exp_Debug}; return -1 if not defined $self->fileno(); # skip if handle already closed unless ( exists ${*$self}{exp_Has_EOF} and ${*$self}{exp_Has_EOF} ) { $end_time = time() + 15; while ( $end_time > time() ) { my $select_time = $end_time - time(); # Sanity check. $select_time = 0 if $select_time < 0; $rmask = ''; vec( $rmask, $self->fileno(), 1 ) = 1; ($nfound) = select( $rmask, undef, undef, $select_time ); last unless ( defined($nfound) && $nfound ); $nread = sysread( $self, $temp_buffer, 8096 ); # 0 = EOF. unless ( defined($nread) && $nread ) { print STDERR "Got EOF from ${*$self}{exp_Pty_Handle}.\r\n" if ${*$self}{exp_Debug}; last; } $self->_print_handles($temp_buffer); } if ( ( $end_time <= time() ) && ${*$self}{exp_Debug} ) { print STDERR "Timed out waiting for an EOF from ${*$self}{exp_Pty_Handle}.\r\n"; } } my $close_status = $self->close(); if ( $close_status && ${*$self}{exp_Debug} ) { print STDERR "${*$self}{exp_Pty_Handle} closed.\r\n"; } # quit now if it isn't a process. return $close_status unless defined( ${*$self}{exp_Pid} ); # Now give it 15 seconds to die. $end_time = time() + 15; while ( $end_time > time() ) { my $returned_pid = waitpid( ${*$self}{exp_Pid}, &WNOHANG ); # Stop here if the process dies. if ( defined($returned_pid) && $returned_pid ) { delete $Expect::Spawned_PIDs{$returned_pid}; if ( ${*$self}{exp_Debug} ) { printf STDERR ( "Pid %d of %s exited, Status: 0x%02X\r\n", ${*$self}{exp_Pid}, ${*$self}{exp_Pty_Handle}, $? ); } ${*$self}{exp_Pid} = undef; ${*$self}{exp_Exit} = $?; return ${*$self}{exp_Exit}; } sleep 1; # Keep loop nice. } # Send it a term if it isn't dead. if ( ${*$self}{exp_Debug} ) { print STDERR "${*$self}{exp_Pty_Handle} not exiting, sending TERM.\r\n"; } kill TERM => ${*$self}{exp_Pid}; # Now to be anal retentive.. wait 15 more seconds for it to die. $end_time = time() + 15; while ( $end_time > time() ) { my $returned_pid = waitpid( ${*$self}{exp_Pid}, &WNOHANG ); if ( defined($returned_pid) && $returned_pid ) { delete $Expect::Spawned_PIDs{$returned_pid}; if ( ${*$self}{exp_Debug} ) { printf STDERR ( "Pid %d of %s terminated, Status: 0x%02X\r\n", ${*$self}{exp_Pid}, ${*$self}{exp_Pty_Handle}, $? ); } ${*$self}{exp_Pid} = undef; ${*$self}{exp_Exit} = $?; return $?; } sleep 1; } # Since this is a 'soft' close, sending it a -9 would be inappropriate. return; } # 'Make it go away' close. sub hard_close { my ($self) = @_; cluck "Closing ${*$self}{exp_Pty_Handle}.\r\n" if ${*$self}{exp_Debug}; # Don't wait for an EOF. my $close_status = $self->close(); if ( $close_status && ${*$self}{exp_Debug} ) { print STDERR "${*$self}{exp_Pty_Handle} closed.\r\n"; } # Return now if handle. return $close_status unless defined( ${*$self}{exp_Pid} ); # Now give it 5 seconds to die. Less patience here if it won't die. my $end_time = time() + 5; while ( $end_time > time() ) { my $returned_pid = waitpid( ${*$self}{exp_Pid}, &WNOHANG ); # Stop here if the process dies. if ( defined($returned_pid) && $returned_pid ) { delete $Expect::Spawned_PIDs{$returned_pid}; if ( ${*$self}{exp_Debug} ) { printf STDERR ( "Pid %d of %s terminated, Status: 0x%02X\r\n", ${*$self}{exp_Pid}, ${*$self}{exp_Pty_Handle}, $? ); } ${*$self}{exp_Pid} = undef; ${*$self}{exp_Exit} = $?; return ${*$self}{exp_Exit}; } sleep 1; # Keep loop nice. } # Send it a term if it isn't dead. if ( ${*$self}{exp_Debug} ) { print STDERR "${*$self}{exp_Pty_Handle} not exiting, sending TERM.\r\n"; } kill TERM => ${*$self}{exp_Pid}; # wait 15 more seconds for it to die. $end_time = time() + 15; while ( $end_time > time() ) { my $returned_pid = waitpid( ${*$self}{exp_Pid}, &WNOHANG ); if ( defined($returned_pid) && $returned_pid ) { delete $Expect::Spawned_PIDs{$returned_pid}; if ( ${*$self}{exp_Debug} ) { printf STDERR ( "Pid %d of %s terminated, Status: 0x%02X\r\n", ${*$self}{exp_Pid}, ${*$self}{exp_Pty_Handle}, $? ); } ${*$self}{exp_Pid} = undef; ${*$self}{exp_Exit} = $?; return ${*$self}{exp_Exit}; } sleep 1; } kill KILL => ${*$self}{exp_Pid}; # wait 5 more seconds for it to die. $end_time = time() + 5; while ( $end_time > time() ) { my $returned_pid = waitpid( ${*$self}{exp_Pid}, &WNOHANG ); if ( defined($returned_pid) && $returned_pid ) { delete $Expect::Spawned_PIDs{$returned_pid}; if ( ${*$self}{exp_Debug} ) { printf STDERR ( "Pid %d of %s killed, Status: 0x%02X\r\n", ${*$self}{exp_Pid}, ${*$self}{exp_Pty_Handle}, $? ); } ${*$self}{exp_Pid} = undef; ${*$self}{exp_Exit} = $?; return ${*$self}{exp_Exit}; } sleep 1; } warn "Pid ${*$self}{exp_Pid} of ${*$self}{exp_Pty_Handle} is HUNG.\r\n"; ${*$self}{exp_Pid} = undef; return; } # These should not be called externally. sub _init_vars { my ($self) = @_; # for every spawned process or filehandle. ${*$self}{exp_Log_Stdout} = $Expect::Log_Stdout if defined($Expect::Log_Stdout); ${*$self}{exp_Log_Group} = $Expect::Log_Group; ${*$self}{exp_Debug} = $Expect::Debug; ${*$self}{exp_Exp_Internal} = $Expect::Exp_Internal; ${*$self}{exp_Manual_Stty} = $Expect::Manual_Stty; ${*$self}{exp_Stored_Stty} = 'sane'; ${*$self}{exp_Do_Soft_Close} = $Expect::Do_Soft_Close; # sysread doesn't like my or local vars. ${*$self}{exp_Pty_Buffer} = ''; # Initialize accumulator. ${*$self}{exp_Max_Accum} = $Expect::Exp_Max_Accum; ${*$self}{exp_Accum} = ''; ${*$self}{exp_NoTransfer} = 0; # create empty expect_before & after lists ${*$self}{exp_expect_before_list} = []; ${*$self}{exp_expect_after_list} = []; return; } sub _make_readable { my ($s) = @_; $s = '' if not defined($s); study $s; # Speed things up? $s =~ s/\\/\\\\/g; # So we can tell easily(?) what is a backslash $s =~ s/\n/\\n/g; $s =~ s/\r/\\r/g; $s =~ s/\t/\\t/g; $s =~ s/\'/\\\'/g; # So we can tell whassa quote and whassa notta quote. $s =~ s/\"/\\\"/g; # Formfeed (does anyone use formfeed?) $s =~ s/\f/\\f/g; $s =~ s/\010/\\b/g; # escape control chars high/low, but allow ISO 8859-1 chars $s =~ s/([\000-\037\177-\237\377])/sprintf("\\%03lo",ord($1))/ge; return $s; } sub _trim_length { my ($self, $string, $length) = @_; # This is sort of a reverse truncation function # Mostly so we don't have to see the full output when we're using # Also used if Max_Accum gets set to limit the size of the accumulator # for matching functions. # exp_internal croak('No string passed') if not defined $string; # If we're not passed a length (_trim_length is being used for debugging # purposes) AND debug >= 3, don't trim. return ($string) if (defined($self) and ${*$self}{"exp_Debug"} >= 3 and ( !( defined($length) ) ) ); my $indicate_truncation = ($length ? '' : '...'); $length ||= 1021; return $string if $length >= length $string; # We wouldn't want the accumulator to begin with '...' if max_accum is passed # This is because this funct. gets called internally w/ max_accum # and is also used to print information back to the user. return $indicate_truncation . substr( $string, ( length($string) - $length ), $length ); } sub _print_handles { my ($self, $print_this) = @_; # Given crap from 'self' and the handles self wants to print to, print to # them. these are indicated by the handle's 'group' if ( ${*$self}{exp_Log_Group} ) { foreach my $handle ( @{ ${*$self}{exp_Listen_Group} } ) { $print_this = '' unless defined($print_this); # Appease perl -w print STDERR "Printed '" . $self->_trim_length( _make_readable($print_this) ) . "' to ${*$handle}{exp_Pty_Handle} from ${*$self}{exp_Pty_Handle}.\r\n" if ( ${*$handle}{"exp_Debug"} > 1 ); print $handle $print_this; } } # If ${*$self}{exp_Pty_Handle} is STDIN this would make it echo. print STDOUT $print_this if ${*$self}{"exp_Log_Stdout"}; $self->print_log_file($print_this); $| = 1; # This should not be necessary but autoflush() doesn't always work. return; } sub _get_mode { my ($handle) = @_; my ($fcntl_flags) = ''; # What mode are we opening with? use fcntl to find out. $fcntl_flags = fcntl( \*{$handle}, Fcntl::F_GETFL, $fcntl_flags ); die "fcntl returned undef during exp_init of $handle, $!\r\n" unless defined($fcntl_flags); if ( $fcntl_flags | (Fcntl::O_RDWR) ) { return 'rw'; } elsif ( $fcntl_flags | (Fcntl::O_WRONLY) ) { return 'w'; } else { # Under Solaris (among others?) O_RDONLY is implemented as 0. so |O_RDONLY would fail. return 'r'; } } sub _undef { return undef; # Seems a little retarded but &CORE::undef fails in interconnect. # This is used for the default escape sequence function. # w/out the leading & it won't compile. } # clean up child processes sub DESTROY { my ($self) = @_; my $status = $?; # save this as it gets mangled by the terminating spawned children if ( ${*$self}{exp_Do_Soft_Close} ) { $self->soft_close(); } $self->hard_close(); $? = $status; # restore it. otherwise deleting an Expect object may mangle $?, which is unintuitive return; } 1; __END__ =head1 NAME Expect - automate interactions with command line programs that expose a text terminal interface. =head1 SYNOPSIS use Expect; # create an Expect object by spawning another process my $exp = Expect->spawn($command, @params) or die "Cannot spawn $command: $!\n"; # or by using an already opened filehandle (e.g. from Net::Telnet) my $exp = Expect->exp_init(\*FILEHANDLE); # if you prefer the OO mindset: my $exp = Expect->new; $exp->raw_pty(1); $exp->spawn($command, @parameters) or die "Cannot spawn $command: $!\n"; # send some string there: $exp->send("string\n"); # or, for the filehandle mindset: print $exp "string\n"; # then do some pattern matching with either the simple interface $patidx = $exp->expect($timeout, @match_patterns); # or multi-match on several spawned commands with callbacks, # just like the Tcl version $exp->expect($timeout, [ qr/regex1/ => sub { my $exp = shift; $exp->send("response\n"); exp_continue; } ], [ "regexp2" , \&callback, @cbparms ], ); # if no longer needed, do a soft_close to nicely shut down the command $exp->soft_close(); # or be less patient with $exp->hard_close(); Expect.pm is built to either spawn a process or take an existing filehandle and interact with it such that normally interactive tasks can be done without operator assistance. This concept makes more sense if you are already familiar with the versatile Tcl version of Expect. The public functions that make up Expect.pm are: Expect->new() Expect::interconnect(@objects_to_be_read_from) Expect::test_handles($timeout, @objects_to_test) Expect::version($version_requested | undef); $object->spawn(@command) $object->clear_accum() $object->set_accum($value) $object->debug($debug_level) $object->exp_internal(0 | 1) $object->notransfer(0 | 1) $object->raw_pty(0 | 1) $object->stty(@stty_modes) # See the IO::Stty docs $object->slave() $object->before(); $object->match(); $object->after(); $object->matchlist(); $object->match_number(); $object->error(); $object->command(); $object->exitstatus(); $object->pty_handle(); $object->do_soft_close(); $object->restart_timeout_upon_receive(0 | 1); $object->interact($other_object, $escape_sequence) $object->log_group(0 | 1 | undef) $object->log_user(0 | 1 | undef) $object->log_file("filename" | $filehandle | \&coderef | undef) $object->manual_stty(0 | 1 | undef) $object->match_max($max_buffersize or undef) $object->pid(); $object->send_slow($delay, @strings_to_send) $object->set_group(@listen_group_objects | undef) $object->set_seq($sequence,\&function,\@parameters); There are several configurable package variables that affect the behavior of Expect. They are: $Expect::Debug; $Expect::Exp_Internal; $Expect::IgnoreEintr; $Expect::Log_Group; $Expect::Log_Stdout; $Expect::Manual_Stty; $Expect::Multiline_Matching; $Expect::Do_Soft_Close; =head1 DESCRIPTION See an explanation of L The Expect module is a successor of Comm.pl and a descendent of Chat.pl. It more closely resembles the Tcl Expect language than its predecessors. It does not contain any of the networking code found in Comm.pl. I suspect this would be obsolete anyway given the advent of IO::Socket and external tools such as netcat. Expect.pm is an attempt to have more of a switch() & case feeling to make decision processing more fluid. Three separate types of debugging have been implemented to make code production easier. It is possible to interconnect multiple file handles (and processes) much like Tcl's Expect. An attempt was made to enable all the features of Tcl's Expect without forcing Tcl on the victim programmer :-) . Please, before you consider using Expect, read the FAQs about L and L =head1 USAGE =over 4 =item new Creates a new Expect object, i.e. a pty. You can change parameters on it before actually spawning a command. This is important if you want to modify the terminal settings for the slave. See slave() below. The object returned is actually a reblessed IO::Pty filehandle, so see there for additional methods. =item Expect->exp_init(\*FILEHANDLE) I =item Expect->init(\*FILEHANDLE) Initializes $new_handle_object for use with other Expect functions. It must be passed a B<_reference_> to FILEHANDLE if you want it to work properly. IO::File objects are preferable. Returns a reference to the newly created object. You can use only real filehandles, certain tied filehandles (e.g. Net::SSH2) that lack a fileno() will not work. Net::Telnet objects can be used but have been reported to work only for certain hosts. YMMV. =item Expect->spawn($command, @parameters) I =item $object->spawn($command, @parameters) I =item Expect->new($command, @parameters) Forks and execs $command. Returns an Expect object upon success or C if the fork was unsuccessful or the command could not be found. spawn() passes its parameters unchanged to Perls exec(), so look there for detailed semantics. Note that if spawn cannot exec() the given command, the Expect object is still valid and the next expect() will see "Cannot exec", so you can use that for error handling. Also note that you cannot reuse an object with an already spawned command, even if that command has exited. Sorry, but you have to allocate a new object... =item $object->debug(0 | 1 | 2 | 3 | undef) Sets debug level for $object. 1 refers to general debugging information, 2 refers to verbose debugging and 0 refers to no debugging. If you call debug() with no parameters it will return the current debugging level. When the object is created the debugging level will match that $Expect::Debug, normally 0. The '3' setting is new with 1.05, and adds the additional functionality of having the _full_ accumulated buffer printed every time data is read from an Expect object. This was implemented by request. I recommend against using this unless you think you need it as it can create quite a quantity of output under some circumstances.. =item $object->exp_internal(1 | 0) Sets/unsets 'exp_internal' debugging. This is similar in nature to its Tcl counterpart. It is extremely valuable when debugging expect() sequences. When the object is created the exp_internal setting will match the value of $Expect::Exp_Internal, normally 0. Returns the current setting if called without parameters. It is highly recommended that you make use of the debugging features lest you have angry code. =item $object->raw_pty(1 | 0) Set pty to raw mode before spawning. This disables echoing, CR->LF translation and an ugly hack for broken Solaris TTYs (which send to slow things down) and thus gives a more pipe-like behaviour (which is important if you want to transfer binary content). Note that this must be set I spawning the program. =item $object->stty(qw(mode1 mode2...)) Sets the tty mode for $object's associated terminal to the given modes. Note that on many systems the master side of the pty is not a tty, so you have to modify the slave pty instead, see next item. This needs IO::Stty installed, which is no longer required. =item $object->slave() Returns a filehandle to the slave part of the pty. Very useful in modifying the terminal settings: $object->slave->stty(qw(raw -echo)); Typical values are 'sane', 'raw', and 'raw -echo'. Note that I recommend setting the terminal to 'raw' or 'raw -echo', as this avoids a lot of hassle and gives pipe-like (i.e. transparent) behaviour (without the buffering issue). =item $object->print(@strings) I =item $object->send(@strings) Sends the given strings to the spawned command. Note that the strings are not logged in the logfile (see print_log_file) but will probably be echoed back by the pty, depending on pty settings (default is echo) and thus end up there anyway. This must also be taken into account when expect()ing for an answer: the next string will be the command just sent. I suggest setting the pty to raw, which disables echo and makes the pty transparently act like a bidirectional pipe. =item $object->expect($timeout, @match_patterns) =over 4 =item Simple interface Given $timeout in seconds Expect will wait for $object's handle to produce one of the match_patterns, which are matched exactly by default. If you want a regexp match, prefix the pattern with '-re'. $object->expect(15, 'match me exactly','-re','match\s+me\s+exactly'); Due to o/s limitations $timeout should be a round number. If $timeout is 0 Expect will check one time to see if $object's handle contains any of the match_patterns. If $timeout is undef Expect will wait forever for a pattern to match. If called in a scalar context, expect() will return the position of the matched pattern within @matched_patterns, or undef if no pattern was matched. This is a position starting from 1, so if you want to know which of an array of @matched_patterns matched you should subtract one from the return value. If called in an array context expect() will return ($matched_pattern_position, $error, $successfully_matching_string, $before_match, and $after_match). C<$matched_pattern_position> will contain the value that would have been returned if expect() had been called in a scalar context. C<$error> is the error that occurred that caused expect() to return. $error will contain a number followed by a string equivalent expressing the nature of the error. Possible values are undef, indicating no error, '1:TIMEOUT' indicating that $timeout seconds had elapsed without a match, '2:EOF' indicating an eof was read from $object, '3: spawn id($fileno) died' indicating that the process exited before matching and '4:$!' indicating whatever error was set in $ERRNO during the last read on $object's handle or during select(). All handles indicated by set_group plus STDOUT will have all data to come out of $object printed to them during expect() if log_group and log_stdout are set. C<$successfully_matching_string> C<$before_match> C<$after_match> Changed from older versions is the regular expression handling. By default now all strings passed to expect() are treated as literals. To match a regular expression pass '-re' as a parameter in front of the pattern you want to match as a regexp. This change makes it possible to match literals and regular expressions in the same expect() call. Also new is multiline matching. ^ will now match the beginning of lines. Unfortunately, because perl doesn't use $/ in determining where lines break using $ to find the end of a line frequently doesn't work. This is because your terminal is returning "\r\n" at the end of every line. One way to check for a pattern at the end of a line would be to use \r?$ instead of $. Example: Spawning telnet to a host, you might look for the escape character. telnet would return to you "\r\nEscape character is '^]'.\r\n". To find this you might use $match='^Escape char.*\.\r?$'; $telnet->expect(10,'-re',$match); =item New more Tcl/Expect-like interface expect($timeout, '-i', [ $obj1, $obj2, ... ], [ $re_pattern, sub { ...; exp_continue; }, @subparms, ], [ 'eof', sub { ... } ], [ 'timeout', sub { ... }, \$subparm1 ], '-i', [ $objn, ...], '-ex', $exact_pattern, sub { ... }, $exact_pattern, sub { ...; exp_continue_timeout; }, '-re', $re_pattern, sub { ... }, '-i', \@object_list, @pattern_list, ...); It's now possible to expect on more than one connection at a time by specifying 'C<-i>' and a single Expect object or a ref to an array containing Expect objects, e.g. expect($timeout, '-i', $exp1, @patterns_1, '-i', [ $exp2, $exp3 ], @patterns_2_3, ) Furthermore, patterns can now be specified as array refs containing [$regexp, sub { ...}, @optional_subprams] . When the pattern matches, the subroutine is called with parameters ($matched_expect_obj, @optional_subparms). The subroutine can return the symbol `exp_continue' to continue the expect matching with timeout starting anew or return the symbol `exp_continue_timeout' for continuing expect without resetting the timeout count. $exp->expect($timeout, [ qr/username: /i, sub { my $self = shift; $self->send("$username\n"); exp_continue; }], [ qr/password: /i, sub { my $self = shift; $self->send("$password\n"); exp_continue; }], $shell_prompt); `expect' is now exported by default. =back =item $object->exp_before() I =item $object->before() before() returns the 'before' part of the last expect() call. If the last expect() call didn't match anything, exp_before() will return the entire output of the object accumulated before the expect() call finished. Note that this is something different than Tcl Expects before()!! =item $object->exp_after() I =item $object->after() returns the 'after' part of the last expect() call. If the last expect() call didn't match anything, exp_after() will return undef(). =item $object->exp_match() I =item $object->match() returns the string matched by the last expect() call, undef if no string was matched. =item $object->exp_match_number() I =item $object->match_number() exp_match_number() returns the number of the pattern matched by the last expect() call. Keep in mind that the first pattern in a list of patterns is 1, not 0. Returns undef if no pattern was matched. =item $object->exp_matchlist() I =item $object->matchlist() exp_matchlist() returns a list of matched substrings from the brackets () inside the regexp that last matched. ($object->matchlist)[0] thus corresponds to $1, ($object->matchlist)[1] to $2, etc. =item $object->exp_error() I =item $object->error() exp_error() returns the error generated by the last expect() call if no pattern was matched. It is typically useful to examine the value returned by before() to find out what the output of the object was in determining why it didn't match any of the patterns. =item $object->clear_accum() Clear the contents of the accumulator for $object. This gets rid of any residual contents of a handle after expect() or send_slow() such that the next expect() call will only see new data from $object. The contents of the accumulator are returned. =item $object->set_accum($value) Sets the content of the accumulator for $object to $value. The previous content of the accumulator is returned. =item $object->exp_command() I =item $object->command() exp_command() returns the string that was used to spawn the command. Helpful for debugging and for reused patternmatch subroutines. =item $object->exp_exitstatus() I =item $object->exitstatus() Returns the exit status of $object (if it already exited). =item $object->exp_pty_handle() I =item $object->pty_handle() Returns a string representation of the attached pty, for example: `spawn id(5)' (pty has fileno 5), `handle id(7)' (pty was initialized from fileno 7) or `STDIN'. Useful for debugging. =item $object->restart_timeout_upon_receive(0 | 1) If this is set to 1, the expect timeout is retriggered whenever something is received from the spawned command. This allows to perform some aliveness testing and still expect for patterns. $exp->restart_timeout_upon_receive(1); $exp->expect($timeout, [ timeout => \&report_timeout ], [ qr/pattern/ => \&handle_pattern], ); Now the timeout isn't triggered if the command produces any kind of output, i.e. is still alive, but you can act upon patterns in the output. =item $object->notransfer(1 | 0) Do not truncate the content of the accumulator after a match. Normally, the accumulator is set to the remains that come after the matched string. Note that this setting is per object and not per pattern, so if you want to have normal acting patterns that truncate the accumulator, you have to add a $exp->set_accum($exp->after); to their callback, e.g. $exp->notransfer(1); $exp->expect($timeout, # accumulator not truncated, pattern1 will match again [ "pattern1" => sub { my $self = shift; ... } ], # accumulator truncated, pattern2 will not match again [ "pattern2" => sub { my $self = shift; ... $self->set_accum($self->after()); } ], ); This is only a temporary fix until I can rewrite the pattern matching part so it can take that additional -notransfer argument. =item Expect::interconnect(@objects); Read from @objects and print to their @listen_groups until an escape sequence is matched from one of @objects and the associated function returns 0 or undef. The special escape sequence 'EOF' is matched when an object's handle returns an end of file. Note that it is not necessary to include objects that only accept data in @objects since the escape sequence is _read_ from an object. Further note that the listen_group for a write-only object is always empty. Why would you want to have objects listening to STDOUT (for example)? By default every member of @objects _as well as every member of its listen group_ will be set to 'raw -echo' for the duration of interconnection. Setting $object->manual_stty() will stop this behavior per object. The original tty settings will be restored as interconnect exits. For a generic way to interconnect processes, take a look at L. =item Expect::test_handles(@objects) Given a set of objects determines which objects' handles have data ready to be read. B who's members are positions in @objects that have ready handles. Returns undef if there are no such handles ready. =item Expect::version($version_requested or undef); Returns current version of Expect. As of .99 earlier versions are not supported. Too many things were changed to make versioning possible. =item $object->interact( C<\*FILEHANDLE, $escape_sequence>) interact() is essentially a macro for calling interconnect() for connecting 2 processes together. \*FILEHANDLE defaults to \*STDIN and $escape_sequence defaults to undef. Interaction ceases when $escape_sequence is read from B, not $object. $object's listen group will consist solely of \*FILEHANDLE for the duration of the interaction. \*FILEHANDLE will not be echoed on STDOUT. =item $object->log_group(0 | 1 | undef) Set/unset logging of $object to its 'listen group'. If set all objects in the listen group will have output from $object printed to them during $object->expect(), $object->send_slow(), and C. Default value is on. During creation of $object the setting will match the value of $Expect::Log_Group, normally 1. =item $object->log_user(0 | 1 | undef) I =item $object->log_stdout(0 | 1 | undef) Set/unset logging of object's handle to STDOUT. This corresponds to Tcl's log_user variable. Returns current setting if called without parameters. Default setting is off for initialized handles. When a process object is created (not a filehandle initialized with exp_init) the log_stdout setting will match the value of $Expect::Log_Stdout variable, normally 1. If/when you initialize STDIN it is usually associated with a tty which will by default echo to STDOUT anyway, so be careful or you will have multiple echoes. =item $object->log_file("filename" | $filehandle | \&coderef | undef) Log session to a file. All characters send to or received from the spawned process are written to the file. Normally appends to the logfile, but you can pass an additional mode of "w" to truncate the file upon open(): $object->log_file("filename", "w"); Returns the logfilehandle. If called with an undef value, stops logging and closes logfile: $object->log_file(undef); If called without argument, returns the logfilehandle: $fh = $object->log_file(); Can be set to a code ref, which will be called instead of printing to the logfile: $object->log_file(\&myloggerfunc); =item $object->print_log_file(@strings) Prints to logfile (if opened) or calls the logfile hook function. This allows the user to add arbitrary text to the logfile. Note that this could also be done as $object->log_file->print() but would only work for log files, not code hooks. =item $object->set_seq($sequence, \&function, \@function_parameters) During Expect->interconnect() if $sequence is read from $object &function will be executed with parameters @function_parameters. It is B<_highly recommended_> that the escape sequence be a single character since the likelihood is great that the sequence will be broken into to separate reads from the $object's handle, making it impossible to strip $sequence from getting printed to $object's listen group. \&function should be something like 'main::control_w_function' and @function_parameters should be an array defined by the caller, passed by reference to set_seq(). Your function should return a non-zero value if execution of interconnect() is to resume after the function returns, zero or undefined if interconnect() should return after your function returns. The special sequence 'EOF' matches the end of file being reached by $object. See interconnect() for details. =item $object->set_group(@listener_objects) @listener_objects is the list of objects that should have their handles printed to by $object when Expect::interconnect, $object->expect() or $object->send_slow() are called. Calling w/out parameters will return the current list of the listener objects. =item $object->manual_stty(0 | 1 | undef) Sets/unsets whether or not Expect should make reasonable guesses as to when and how to set tty parameters for $object. Will match $Expect::Manual_Stty value (normally 0) when $object is created. If called without parameters manual_stty() will return the current manual_stty setting. =item $object->match_max($maximum_buffer_length | undef) I =item $object->max_accum($maximum_buffer_length | undef) Set the maximum accumulator size for object. This is useful if you think that the accumulator will grow out of hand during expect() calls. Since the buffer will be matched by every match_pattern it may get slow if the buffer gets too large. Returns current value if called without parameters. Not defined by default. =item $object->notransfer(0 | 1) If set, matched strings will not be deleted from the accumulator. Returns current value if called without parameters. False by default. =item $object->exp_pid() I =item $object->pid() Return pid of $object, if one exists. Initialized filehandles will not have pids (of course). =item $object->send_slow($delay, @strings); print each character from each string of @strings one at a time with $delay seconds before each character. This is handy for devices such as modems that can be annoying if you send them data too fast. After each character $object will be checked to determine whether or not it has any new data ready and if so update the accumulator for future expect() calls and print the output to STDOUT and @listen_group if log_stdout and log_group are appropriately set. =back =head2 Configurable Package Variables: =over 4 =item $Expect::Debug Defaults to 0. Newly created objects have a $object->debug() value of $Expect::Debug. See $object->debug(); =item $Expect::Do_Soft_Close Defaults to 0. When destroying objects, soft_close may take up to half a minute to shut everything down. From now on, only hard_close will be called, which is less polite but still gives the process a chance to terminate properly. Set this to '1' for old behaviour. =item $Expect::Exp_Internal Defaults to 0. Newly created objects have a $object->exp_internal() value of $Expect::Exp_Internal. See $object->exp_internal(). =item $Expect::IgnoreEintr Defaults to 0. If set to 1, when waiting for new data, Expect will ignore EINTR errors and restart the select() call instead. =item $Expect::Log_Group Defaults to 1. Newly created objects have a $object->log_group() value of $Expect::Log_Group. See $object->log_group(). =item $Expect::Log_Stdout Defaults to 1 for spawned commands, 0 for file handles attached with exp_init(). Newly created objects have a $object->log_stdout() value of $Expect::Log_Stdout. See $object->log_stdout(). =item $Expect::Manual_Stty Defaults to 0. Newly created objects have a $object->manual_stty() value of $Expect::Manual_Stty. See $object->manual_stty(). =item $Expect::Multiline_Matching Defaults to 1. Affects whether or not expect() uses the /m flag for doing regular expression matching. If set to 1 /m is used. This makes a difference when you are trying to match ^ and $. If you have this on you can match lines in the middle of a page of output using ^ and $ instead of it matching the beginning and end of the entire expression. I think this is handy. The $Expect::Multiline_Matching turns on and off Expect's multi-line matching mode. But this only has an effect if you pass in a string, and then use '-re' mode. If you pass in a regular expression value (via qr//), then the qr//'s own flags are preserved irrespective of what it gets interpolated into. There was a bug in Perl 5.8.x where interpolating a regex without /m into a match with /m would incorrectly apply the /m to the inner regex too, but this was fixed in Perl 5.10. The correct behavior, as seen in Perl 5.10, is that if you pass in a regex (via qr//), then $Expect::Multiline_Matching has no effect. So if you pass in a regex, then you must use the qr's flags to control whether it is multiline (which by default it is not, opposite of the default behavior of Expect). =back =head1 CONTRIBUTIONS Lee Eakin has ported the kibitz script from Tcl/Expect to Perl/Expect. Jeff Carr provided a simple example of how handle terminal window resize events (transmitted via the WINCH signal) in a ssh session. You can find both scripts in the examples/ subdir. Thanks to both! Historical notes: There are still a few lines of code dating back to the inspirational Comm.pl and Chat.pl modules without which this would not have been possible. Kudos to Eric Arnold and Randal 'Nuke your NT box with one line of perl code' Schwartz for making these available to the perl public. As of .98 I think all the old code is toast. No way could this have been done without it though. Special thanks to Graham Barr for helping make sense of the IO::Handle stuff as well as providing the highly recommended IO::Tty module. =head1 REFERENCES Mark Rogaski wrote: "I figured that you'd like to know that Expect.pm has been very useful to AT&T Labs over the past couple of years (since I first talked to Austin about design decisions). We use Expect.pm for managing the switches in our network via the telnet interface, and such automation has significantly increased our reliability. So, you can honestly say that one of the largest digital networks in existence (AT&T Frame Relay) uses Expect.pm quite extensively." =head1 FAQ - Frequently Asked Questions This is a growing collection of things that might help. Please send you questions that are not answered here to RGiersig@cpan.org =head2 What systems does Expect run on? Expect itself doesn't have real system dependencies, but the underlying IO::Tty needs pseudoterminals. IO::Stty uses POSIX.pm and Fcntl.pm. I have used it on Solaris, Linux and AIX, others report *BSD and OSF as working. Generally, any modern POSIX Unix should do, but there are exceptions to every rule. Feedback is appreciated. See L for a list of verified systems. =head2 Can I use this module with ActivePerl on Windows? Up to now, the answer was 'No', but this has changed. You still cannot use ActivePerl, but if you use the Cygwin environment (http://sources.redhat.com), which brings its own perl, and have the latest IO::Tty (v0.05 or later) installed, it should work (feedback appreciated). =head2 The examples in the tutorial don't work! The tutorial is hopelessly out of date and needs a serious overhaul. I apologize for this, I have concentrated my efforts mainly on the functionality. Volunteers welcomed. =head2 How can I find out what Expect is doing? If you set $Expect::Exp_Internal = 1; Expect will tell you very verbosely what it is receiving and sending, what matching it is trying and what it found. You can do this on a per-command base with $exp->exp_internal(1); You can also set $Expect::Debug = 1; # or 2, 3 for more verbose output or $exp->debug(1); which gives you even more output. =head2 I am seeing the output of the command I spawned. Can I turn that off? Yes, just set $Expect::Log_Stdout = 0; to globally disable it or $exp->log_stdout(0); for just that command. 'log_user' is provided as an alias so Tcl/Expect user get a DWIM experience... :-) =head2 No, I mean that when I send some text to the spawned process, it gets echoed back and I have to deal with it in the next expect. This is caused by the pty, which has probably 'echo' enabled. A solution would be to set the pty to raw mode, which in general is cleaner for communication between two programs (no more unexpected character translations). Unfortunately this would break a lot of old code that sends "\r" to the program instead of "\n" (translating this is also handled by the pty), so I won't add this to Expect just like that. But feel free to experiment with C<$exp-Eraw_pty(1)>. =head2 How do I send control characters to a process? A: You can send any characters to a process with the print command. To represent a control character in Perl, use \c followed by the letter. For example, control-G can be represented with "\cG" . Note that this will not work if you single-quote your string. So, to send control-C to a process in $exp, do: print $exp "\cC"; Or, if you prefer: $exp->send("\cC"); The ability to include control characters in a string like this is provided by Perl, not by Expect.pm . Trying to learn Expect.pm without a thorough grounding in Perl can be very daunting. We suggest you look into some of the excellent Perl learning material, such as the books _Programming Perl_ and _Learning Perl_ by O'Reilly, as well as the extensive online Perl documentation available through the perldoc command. =head2 My script fails from time to time without any obvious reason. It seems that I am sometimes loosing output from the spawned program. You could be exiting too fast without giving the spawned program enough time to finish. Try adding $exp->soft_close() to terminate the program gracefully or do an expect() for 'eof'. Alternatively, try adding a 'sleep 1' after you spawn() the program. It could be that pty creation on your system is just slow (but this is rather improbable if you are using the latest IO-Tty). =head2 I want to automate password entry for su/ssh/scp/rsh/... You shouldn't use Expect for this. Putting passwords, especially root passwords, into scripts in clear text can mean severe security problems. I strongly recommend using other means. For 'su', consider switching to 'sudo', which gives you root access on a per-command and per-user basis without the need to enter passwords. 'ssh'/'scp' can be set up with RSA authentication without passwords. 'rsh' can use the .rhost mechanism, but I'd strongly suggest to switch to 'ssh'; to mention 'rsh' and 'security' in the same sentence makes an oxymoron. It will work for 'telnet', though, and there are valid uses for it, but you still might want to consider using 'ssh', as keeping cleartext passwords around is very insecure. =head2 I want to use Expect to automate [anything with a buzzword]... Are you sure there is no other, easier way? As a rule of thumb, Expect is useful for automating things that expect to talk to a human, where no formal standard applies. For other tasks that do follow a well-defined protocol, there are often better-suited modules that already can handle those protocols. Don't try to do HTTP requests by spawning telnet to port 80, use LWP instead. To automate FTP, take a look at L or C (http://www.ncftp.org). You don't use a screwdriver to hammer in your nails either, or do you? =head2 Is it possible to use threads with Expect? Basically yes, with one restriction: you must spawn() your programs in the main thread and then pass the Expect objects to the handling threads. The reason is that spawn() uses fork(), and L: "Thinking of mixing fork() and threads? Please lie down and wait until the feeling passes." =head2 I want to log the whole session to a file. Use $exp->log_file("filename"); or $exp->log_file($filehandle); or even $exp->log_file(\&log_procedure); for maximum flexibility. Note that the logfile is appended to by default, but you can specify an optional mode "w" to truncate the logfile: $exp->log_file("filename", "w"); To stop logging, just call it with a false argument: $exp->log_file(undef); =head2 How can I turn off multi-line matching for my regexps? To globally unset multi-line matching for all regexps: $Expect::Multiline_Matching = 0; You can do that on a per-regexp basis by stating C<(?-m)> inside the regexp (you need perl5.00503 or later for that). =head2 How can I expect on multiple spawned commands? You can use the B<-i> parameter to specify a single object or a list of Expect objects. All following patterns will be evaluated against that list. You can specify B<-i> multiple times to create groups of objects and patterns to match against within the same expect statement. This works just like in Tcl/Expect. See the source example below. =head2 I seem to have problems with ptys! Well, pty handling is really a black magic, as it is extremely system dependent. I have extensively revised IO-Tty, so these problems should be gone. If your system is listed in the "verified" list of IO::Tty, you probably have some non-standard setup, e.g. you compiled your Linux-kernel yourself and disabled ptys. Please ask your friendly sysadmin for help. If your system is not listed, unpack the latest version of IO::Tty, do a 'perl Makefile.PL; make; make test; uname C<-a>' and send me the results and I'll see what I can deduce from that. =head2 I just want to read the output of a process without expect()ing anything. How can I do this? [ Are you sure you need Expect for this? How about qx() or open("prog|")? ] By using expect without any patterns to match. $process->expect(undef); # Forever until EOF $process->expect($timeout); # For a few seconds $process->expect(0); # Is there anything ready on the handle now? =head2 Ok, so now how do I get what was read on the handle? $read = $process->before(); =head2 Where's IO::Pty? Find it on CPAN as IO-Tty, which provides both. =head2 How come when I automate the passwd program to change passwords for me passwd dies before changing the password sometimes/every time? What's happening is you are closing the handle before passwd exits. When you close the handle to a process, it is sent a signal (SIGPIPE?) telling it that STDOUT has gone away. The default behavior for processes is to die in this circumstance. Two ways you can make this not happen are: $process->soft_close(); This will wait 15 seconds for a process to come up with an EOF by itself before killing it. $process->expect(undef); This will wait forever for the process to match an empty set of patterns. It will return when the process hits an EOF. As a rule, you should always expect() the result of your transaction before you continue with processing. =head2 How come when I try to make a logfile with log_file() or set_group() it doesn't print anything after the last time I run expect()? Output is only printed to the logfile/group when Expect reads from the process, during expect(), send_slow() and interconnect(). One way you can force this is to make use of $process->expect(undef); and $process->expect(0); which will make expect() run with an empty pattern set forever or just for an instant to capture the output of $process. The output is available in the accumulator, so you can grab it using $process->before(). =head2 I seem to have problems with terminal settings, double echoing, etc. Tty settings are a major pain to keep track of. If you find unexpected behavior such as double-echoing or a frozen session, doublecheck the documentation for default settings. When in doubt, handle them yourself using $exp->stty() and manual_stty() functions. As of .98 you shouldn't have to worry about stty settings getting fouled unless you use interconnect or intentionally change them (like doing -echo to get a password). If you foul up your terminal's tty settings, kill any hung processes and enter 'stty sane' at a shell prompt. This should make your terminal manageable again. Note that IO::Tty returns ptys with your systems default setting regarding echoing, CRLF translation etc. and Expect does not change them. I have considered setting the ptys to 'raw' without any translation whatsoever, but this would break a lot of existing things, as '\r' translation would not work anymore. On the other hand, a raw pty works much like a pipe and is more WYGIWYE (what you get is what you expect), so I suggest you set it to 'raw' by yourself: $exp = Expect->new; $exp->raw_pty(1); $exp->spawn(...); To disable echo: $exp->slave->stty(qw(-echo)); =head2 I'm spawning a telnet/ssh session and then let the user interact with it. But screen-oriented applications on the other side don't work properly. You have to set the terminal screen size for that. Luckily, IO::Pty already has a method for that, so modify your code to look like this: my $exp = Expect->new; $exp->slave->clone_winsize_from(\*STDIN); $exp->spawn("telnet somehost); Also, some applications need the TERM shell variable set so they know how to move the cursor across the screen. When logging in, the remote shell sends a query (Ctrl-Z I think) and expects the terminal to answer with a string, e.g. 'xterm'. If you really want to go that way (be aware, madness lies at its end), you can handle that and send back the value in $ENV{TERM}. This is only a hand-waving explanation, please figure out the details by yourself. =head2 I set the terminal size as explained above, but if I resize the window, the application does not notice this. You have to catch the signal WINCH ("window size changed"), change the terminal size and propagate the signal to the spawned application: my $exp = Expect->new; $exp->slave->clone_winsize_from(\*STDIN); $exp->spawn("ssh somehost); $SIG{WINCH} = \&winch; sub winch { $exp->slave->clone_winsize_from(\*STDIN); kill WINCH => $exp->pid if $exp->pid; $SIG{WINCH} = \&winch; } $exp->interact(); There is an example file ssh.pl in the examples/ subdir that shows how this works with ssh. Please note that I do strongly object against using Expect to automate ssh login, as there are better way to do that (see L). =head2 I noticed that the test uses a string that resembles, but not exactly matches, a well-known sentence that contains every character. What does that mean? That means you are anal-retentive. :-) [Gotcha there!] =head2 I get a "Could not assign a pty" error when running as a non-root user on an IRIX box? The OS may not be configured to grant additional pty's (pseudo terminals) to non-root users. /usr/sbin/mkpts should be 4755, not 700 for this to work. I don't know about security implications if you do this. =head2 How come I don't notice when the spawned process closes its stdin/out/err?? You are probably on one of the systems where the master doesn't get an EOF when the slave closes stdin/out/err. One possible solution is when you spawn a process, follow it with a unique string that would indicate the process is finished. $process = Expect->spawn('telnet somehost; echo ____END____'); And then $process->expect($timeout,'____END____','other','patterns'); =head1 Source Examples =head2 How to automate login my $telnet = Net::Telnet->new("remotehost") # see Net::Telnet or die "Cannot telnet to remotehost: $!\n";; my $exp = Expect->exp_init($telnet); # deprecated use of spawned telnet command # my $exp = Expect->spawn("telnet localhost") # or die "Cannot spawn telnet: $!\n";; my $spawn_ok; $exp->expect($timeout, [ qr'login: $', sub { $spawn_ok = 1; my $fh = shift; $fh->send("$username\n"); exp_continue; } ], [ 'Password: $', sub { my $fh = shift; print $fh "$password\n"; exp_continue; } ], [ eof => sub { if ($spawn_ok) { die "ERROR: premature EOF in login.\n"; } else { die "ERROR: could not spawn telnet.\n"; } } ], [ timeout => sub { die "No login.\n"; } ], '-re', qr'[#>:] $', #' wait for shell prompt, then exit expect ); =head2 How to expect on multiple spawned commands foreach my $cmd (@list_of_commands) { push @commands, Expect->spawn($cmd); } expect($timeout, '-i', \@commands, [ qr"pattern", # find this pattern in output of all commands sub { my $obj = shift; # object that matched print $obj "something\n"; exp_continue; # we don't want to terminate the expect call } ], '-i', $some_other_command, [ "some other pattern", sub { my ($obj, $parmref) = @_; # ... # now we exit the expect command }, \$parm ], ); =head2 How to propagate terminal sizes my $exp = Expect->new; $exp->slave->clone_winsize_from(\*STDIN); $exp->spawn("ssh somehost); $SIG{WINCH} = \&winch; sub winch { $exp->slave->clone_winsize_from(\*STDIN); kill WINCH => $exp->pid if $exp->pid; $SIG{WINCH} = \&winch; } $exp->interact(); =head1 HOMEPAGE L though the source code is now in GitHub: L =head1 MAILING LISTS There are two mailing lists available, expectperl-announce and expectperl-discuss, at http://lists.sourceforge.net/lists/listinfo/expectperl-announce and http://lists.sourceforge.net/lists/listinfo/expectperl-discuss =head1 BUG TRACKING You can use the CPAN Request Tracker http://rt.cpan.org/ and submit new bugs under http://rt.cpan.org/Ticket/Create.html?Queue=Expect =head1 AUTHORS (c) 1997 Austin Schutz EFE (retired) expect() interface & functionality enhancements (c) 1999-2006 Roland Giersig. This module is now maintained by Dave Jacoby EFE =head1 LICENSE This module can be used under the same terms as Perl. =head1 DISCLAIMER THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. In other words: Use at your own risk. Provided as is. Your mileage may vary. Read the source, Luke! And finally, just to be sure: Any Use of This Product, in Any Manner Whatsoever, Will Increase the Amount of Disorder in the Universe. Although No Liability Is Implied Herein, the Consumer Is Warned That This Process Will Ultimately Lead to the Heat Death of the Universe. =cut applications/mimeinfo.cache000064400000000015152462503210012016 0ustar00[MIME Cache] man/man3/LWP::Protocol::https.3pm000044400000007771152462503210012427 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::Protocol::https 3" .TH LWP::Protocol::https 3 "2020-12-17" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::Protocol::https \- Provide https support for LWP::UserAgent .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use LWP::UserAgent; \& \& $ua = LWP::UserAgent\->new(ssl_opts => { verify_hostname => 1 }); \& $res = $ua\->get("https://www.example.com"); \& \& # specify a CA path \& $ua = LWP::UserAgent\->new( \& ssl_opts => { \& SSL_ca_path => \*(Aq/etc/ssl/certs\*(Aq, \& verify_hostname => 1, \& } \& ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The LWP::Protocol::https module provides support for using https schemed URLs with \s-1LWP.\s0 This module is a plug-in to the \s-1LWP\s0 protocol handling, so you don't use it directly. Once the module is installed \s-1LWP\s0 is able to access sites using \s-1HTTP\s0 over \s-1SSL/TLS.\s0 .PP If hostname verification is requested by LWP::UserAgent's \f(CW\*(C`ssl_opts\*(C'\fR, and neither \f(CW\*(C`SSL_ca_file\*(C'\fR nor \f(CW\*(C`SSL_ca_path\*(C'\fR is set, then \f(CW\*(C`SSL_ca_file\*(C'\fR is implied to be the one provided by Mozilla::CA. If the Mozilla::CA module isn't available \s-1SSL\s0 requests will fail. Either install this module, set up an alternative \f(CW\*(C`SSL_ca_file\*(C'\fR or disable hostname verification. .PP This module used to be bundled with the libwww-perl, but it was unbundled in v6.02 in order to be able to declare its dependencies properly for the \s-1CPAN\s0 tool-chain. Applications that need https support can just declare their dependency on LWP::Protocol::https and will no longer need to know what underlying modules to install. .SH "SEE ALSO" .IX Header "SEE ALSO" IO::Socket::SSL, Crypt::SSLeay, Mozilla::CA .SH "COPYRIGHT & LICENSE" .IX Header "COPYRIGHT & LICENSE" Copyright (c) 1997\-2011 Gisle Aas. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/IO::Tty::Constant.3pm000044400000022756152462503210011702 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Tty::Constant 3" .TH Tty::Constant 3 "2021-10-07" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" IO::Tty::Constant \- Terminal Constants (autogenerated) .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use IO::Tty::Constant qw(TIOCNOTTY); \& ... .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This package defines constants usually found in or (and their #include hierarchy). Find below an autogenerated alphabetic list of all known constants and whether they are defined on your system (prefixed with '+') and have compilation problems ('o'). Undefined or problematic constants are set to 'undef'. .SH "DEFINED CONSTANTS" .IX Header "DEFINED CONSTANTS" .IP "+" 4 B0 .IP "+" 4 B110 .IP "+" 4 B115200 .IP "+" 4 B1200 .IP "+" 4 B134 .IP "+" 4 B150 .IP "\-" 4 B153600 .IP "+" 4 B1800 .IP "+" 4 B19200 .IP "+" 4 B200 .IP "+" 4 B230400 .IP "+" 4 B2400 .IP "+" 4 B300 .IP "\-" 4 B307200 .IP "+" 4 B38400 .IP "+" 4 B460800 .IP "+" 4 B4800 .IP "+" 4 B50 .IP "+" 4 B57600 .IP "+" 4 B600 .IP "+" 4 B75 .IP "\-" 4 B76800 .IP "+" 4 B9600 .IP "+" 4 \&\s-1BRKINT\s0 .IP "+" 4 \&\s-1BS0\s0 .IP "+" 4 \&\s-1BS1\s0 .IP "+" 4 \&\s-1BSDLY\s0 .IP "+" 4 \&\s-1CBAUD\s0 .IP "\-" 4 \&\s-1CBAUDEXT\s0 .IP "+" 4 \&\s-1CBRK\s0 .IP "\-" 4 \&\s-1CCTS_OFLOW\s0 .IP "\-" 4 \&\s-1CDEL\s0 .IP "+" 4 \&\s-1CDSUSP\s0 .IP "+" 4 \&\s-1CEOF\s0 .IP "+" 4 \&\s-1CEOL\s0 .IP "\-" 4 \&\s-1CEOL2\s0 .IP "+" 4 \&\s-1CEOT\s0 .IP "+" 4 \&\s-1CERASE\s0 .IP "\-" 4 \&\s-1CESC\s0 .IP "+" 4 \&\s-1CFLUSH\s0 .IP "+" 4 \&\s-1CIBAUD\s0 .IP "\-" 4 \&\s-1CIBAUDEXT\s0 .IP "+" 4 \&\s-1CINTR\s0 .IP "+" 4 \&\s-1CKILL\s0 .IP "+" 4 \&\s-1CLNEXT\s0 .IP "+" 4 \&\s-1CLOCAL\s0 .IP "\-" 4 \&\s-1CNSWTCH\s0 .IP "\-" 4 \&\s-1CNUL\s0 .IP "+" 4 \&\s-1CQUIT\s0 .IP "+" 4 \&\s-1CR0\s0 .IP "+" 4 \&\s-1CR1\s0 .IP "+" 4 \&\s-1CR2\s0 .IP "+" 4 \&\s-1CR3\s0 .IP "+" 4 \&\s-1CRDLY\s0 .IP "+" 4 \&\s-1CREAD\s0 .IP "+" 4 \&\s-1CRPRNT\s0 .IP "+" 4 \&\s-1CRTSCTS\s0 .IP "\-" 4 \&\s-1CRTSXOFF\s0 .IP "\-" 4 \&\s-1CRTS_IFLOW\s0 .IP "+" 4 \&\s-1CS5\s0 .IP "+" 4 \&\s-1CS6\s0 .IP "+" 4 \&\s-1CS7\s0 .IP "+" 4 \&\s-1CS8\s0 .IP "+" 4 \&\s-1CSIZE\s0 .IP "+" 4 \&\s-1CSTART\s0 .IP "+" 4 \&\s-1CSTOP\s0 .IP "+" 4 \&\s-1CSTOPB\s0 .IP "+" 4 \&\s-1CSUSP\s0 .IP "\-" 4 \&\s-1CSWTCH\s0 .IP "+" 4 \&\s-1CWERASE\s0 .IP "\-" 4 \&\s-1DEFECHO\s0 .IP "\-" 4 \&\s-1DIOC\s0 .IP "\-" 4 \&\s-1DIOCGETP\s0 .IP "\-" 4 \&\s-1DIOCSETP\s0 .IP "\-" 4 \&\s-1DOSMODE\s0 .IP "+" 4 \&\s-1ECHO\s0 .IP "+" 4 \&\s-1ECHOCTL\s0 .IP "+" 4 \&\s-1ECHOE\s0 .IP "+" 4 \&\s-1ECHOK\s0 .IP "+" 4 \&\s-1ECHOKE\s0 .IP "+" 4 \&\s-1ECHONL\s0 .IP "+" 4 \&\s-1ECHOPRT\s0 .IP "+" 4 \&\s-1EXTA\s0 .IP "+" 4 \&\s-1EXTB\s0 .IP "+" 4 \&\s-1FF0\s0 .IP "+" 4 \&\s-1FF1\s0 .IP "+" 4 \&\s-1FFDLY\s0 .IP "\-" 4 \&\s-1FIORDCHK\s0 .IP "+" 4 \&\s-1FLUSHO\s0 .IP "+" 4 \&\s-1HUPCL\s0 .IP "+" 4 \&\s-1ICANON\s0 .IP "+" 4 \&\s-1ICRNL\s0 .IP "+" 4 \&\s-1IEXTEN\s0 .IP "+" 4 \&\s-1IGNBRK\s0 .IP "+" 4 \&\s-1IGNCR\s0 .IP "+" 4 \&\s-1IGNPAR\s0 .IP "+" 4 \&\s-1IMAXBEL\s0 .IP "+" 4 \&\s-1INLCR\s0 .IP "+" 4 \&\s-1INPCK\s0 .IP "+" 4 \&\s-1ISIG\s0 .IP "+" 4 \&\s-1ISTRIP\s0 .IP "+" 4 \&\s-1IUCLC\s0 .IP "+" 4 \&\s-1IXANY\s0 .IP "+" 4 \&\s-1IXOFF\s0 .IP "+" 4 \&\s-1IXON\s0 .IP "\-" 4 \&\s-1KBENABLED\s0 .IP "\-" 4 \&\s-1LDCHG\s0 .IP "\-" 4 \&\s-1LDCLOSE\s0 .IP "\-" 4 \&\s-1LDDMAP\s0 .IP "\-" 4 \&\s-1LDEMAP\s0 .IP "\-" 4 \&\s-1LDGETT\s0 .IP "\-" 4 \&\s-1LDGMAP\s0 .IP "\-" 4 \&\s-1LDIOC\s0 .IP "\-" 4 \&\s-1LDNMAP\s0 .IP "\-" 4 \&\s-1LDOPEN\s0 .IP "\-" 4 \&\s-1LDSETT\s0 .IP "\-" 4 \&\s-1LDSMAP\s0 .IP "\-" 4 \&\s-1LOBLK\s0 .IP "+" 4 \&\s-1NCCS\s0 .IP "+" 4 \&\s-1NL0\s0 .IP "+" 4 \&\s-1NL1\s0 .IP "+" 4 \&\s-1NLDLY\s0 .IP "+" 4 \&\s-1NOFLSH\s0 .IP "+" 4 \&\s-1OCRNL\s0 .IP "+" 4 \&\s-1OFDEL\s0 .IP "+" 4 \&\s-1OFILL\s0 .IP "+" 4 \&\s-1OLCUC\s0 .IP "+" 4 \&\s-1ONLCR\s0 .IP "+" 4 \&\s-1ONLRET\s0 .IP "+" 4 \&\s-1ONOCR\s0 .IP "+" 4 \&\s-1OPOST\s0 .IP "\-" 4 \&\s-1PAGEOUT\s0 .IP "+" 4 \&\s-1PARENB\s0 .IP "\-" 4 \&\s-1PAREXT\s0 .IP "+" 4 \&\s-1PARMRK\s0 .IP "+" 4 \&\s-1PARODD\s0 .IP "+" 4 \&\s-1PENDIN\s0 .IP "\-" 4 \&\s-1RCV1EN\s0 .IP "\-" 4 \&\s-1RTS_TOG\s0 .IP "+" 4 \&\s-1TAB0\s0 .IP "+" 4 \&\s-1TAB1\s0 .IP "+" 4 \&\s-1TAB2\s0 .IP "+" 4 \&\s-1TAB3\s0 .IP "+" 4 \&\s-1TABDLY\s0 .IP "\-" 4 \&\s-1TCDSET\s0 .IP "+" 4 \&\s-1TCFLSH\s0 .IP "+" 4 \&\s-1TCGETA\s0 .IP "+" 4 \&\s-1TCGETS\s0 .IP "+" 4 \&\s-1TCIFLUSH\s0 .IP "+" 4 \&\s-1TCIOFF\s0 .IP "+" 4 \&\s-1TCIOFLUSH\s0 .IP "+" 4 \&\s-1TCION\s0 .IP "+" 4 \&\s-1TCOFLUSH\s0 .IP "+" 4 \&\s-1TCOOFF\s0 .IP "+" 4 \&\s-1TCOON\s0 .IP "+" 4 \&\s-1TCSADRAIN\s0 .IP "+" 4 \&\s-1TCSAFLUSH\s0 .IP "+" 4 \&\s-1TCSANOW\s0 .IP "+" 4 \&\s-1TCSBRK\s0 .IP "+" 4 \&\s-1TCSETA\s0 .IP "+" 4 \&\s-1TCSETAF\s0 .IP "+" 4 \&\s-1TCSETAW\s0 .IP "\-" 4 \&\s-1TCSETCTTY\s0 .IP "+" 4 \&\s-1TCSETS\s0 .IP "+" 4 \&\s-1TCSETSF\s0 .IP "+" 4 \&\s-1TCSETSW\s0 .IP "+" 4 \&\s-1TCXONC\s0 .IP "\-" 4 \&\s-1TERM_D40\s0 .IP "\-" 4 \&\s-1TERM_D42\s0 .IP "\-" 4 \&\s-1TERM_H45\s0 .IP "\-" 4 \&\s-1TERM_NONE\s0 .IP "\-" 4 \&\s-1TERM_TEC\s0 .IP "\-" 4 \&\s-1TERM_TEX\s0 .IP "\-" 4 \&\s-1TERM_V10\s0 .IP "\-" 4 \&\s-1TERM_V61\s0 .IP "+" 4 \&\s-1TIOCCBRK\s0 .IP "\-" 4 \&\s-1TIOCCDTR\s0 .IP "+" 4 \&\s-1TIOCCONS\s0 .IP "+" 4 \&\s-1TIOCEXCL\s0 .IP "\-" 4 \&\s-1TIOCFLUSH\s0 .IP "+" 4 \&\s-1TIOCGETD\s0 .IP "\-" 4 \&\s-1TIOCGETC\s0 .IP "\-" 4 \&\s-1TIOCGETP\s0 .IP "\-" 4 \&\s-1TIOCGLTC\s0 .IP "\-" 4 \&\s-1TIOCSETC\s0 .IP "\-" 4 \&\s-1TIOCSETN\s0 .IP "\-" 4 \&\s-1TIOCSETP\s0 .IP "\-" 4 \&\s-1TIOCSLTC\s0 .IP "+" 4 \&\s-1TIOCGPGRP\s0 .IP "+" 4 \&\s-1TIOCGSID\s0 .IP "+" 4 \&\s-1TIOCGSOFTCAR\s0 .IP "+" 4 \&\s-1TIOCGWINSZ\s0 .IP "\-" 4 \&\s-1TIOCHPCL\s0 .IP "\-" 4 \&\s-1TIOCKBOF\s0 .IP "\-" 4 \&\s-1TIOCKBON\s0 .IP "\-" 4 \&\s-1TIOCLBIC\s0 .IP "\-" 4 \&\s-1TIOCLBIS\s0 .IP "\-" 4 \&\s-1TIOCLGET\s0 .IP "\-" 4 \&\s-1TIOCLSET\s0 .IP "+" 4 \&\s-1TIOCMBIC\s0 .IP "+" 4 \&\s-1TIOCMBIS\s0 .IP "+" 4 \&\s-1TIOCMGET\s0 .IP "+" 4 \&\s-1TIOCMSET\s0 .IP "+" 4 \&\s-1TIOCM_CAR\s0 .IP "+" 4 \&\s-1TIOCM_CD\s0 .IP "+" 4 \&\s-1TIOCM_CTS\s0 .IP "+" 4 \&\s-1TIOCM_DSR\s0 .IP "+" 4 \&\s-1TIOCM_DTR\s0 .IP "+" 4 \&\s-1TIOCM_LE\s0 .IP "+" 4 \&\s-1TIOCM_RI\s0 .IP "+" 4 \&\s-1TIOCM_RNG\s0 .IP "+" 4 \&\s-1TIOCM_RTS\s0 .IP "+" 4 \&\s-1TIOCM_SR\s0 .IP "+" 4 \&\s-1TIOCM_ST\s0 .IP "+" 4 \&\s-1TIOCNOTTY\s0 .IP "+" 4 \&\s-1TIOCNXCL\s0 .IP "+" 4 \&\s-1TIOCOUTQ\s0 .IP "\-" 4 \&\s-1TIOCREMOTE\s0 .IP "+" 4 \&\s-1TIOCSBRK\s0 .IP "+" 4 \&\s-1TIOCSCTTY\s0 .IP "\-" 4 \&\s-1TIOCSDTR\s0 .IP "+" 4 \&\s-1TIOCSETD\s0 .IP "\-" 4 \&\s-1TIOCSIGNAL\s0 .IP "+" 4 \&\s-1TIOCSPGRP\s0 .IP "\-" 4 \&\s-1TIOCSSID\s0 .IP "+" 4 \&\s-1TIOCSSOFTCAR\s0 .IP "\-" 4 \&\s-1TIOCSTART\s0 .IP "+" 4 \&\s-1TIOCSTI\s0 .IP "\-" 4 \&\s-1TIOCSTOP\s0 .IP "+" 4 \&\s-1TIOCSWINSZ\s0 .IP "\-" 4 \&\s-1TM_ANL\s0 .IP "\-" 4 \&\s-1TM_CECHO\s0 .IP "\-" 4 \&\s-1TM_CINVIS\s0 .IP "\-" 4 \&\s-1TM_LCF\s0 .IP "\-" 4 \&\s-1TM_NONE\s0 .IP "\-" 4 \&\s-1TM_SET\s0 .IP "\-" 4 \&\s-1TM_SNL\s0 .IP "+" 4 \&\s-1TOSTOP\s0 .IP "\-" 4 \&\s-1VCEOF\s0 .IP "\-" 4 \&\s-1VCEOL\s0 .IP "+" 4 \&\s-1VDISCARD\s0 .IP "\-" 4 \&\s-1VDSUSP\s0 .IP "+" 4 \&\s-1VEOF\s0 .IP "+" 4 \&\s-1VEOL\s0 .IP "+" 4 \&\s-1VEOL2\s0 .IP "+" 4 \&\s-1VERASE\s0 .IP "+" 4 \&\s-1VINTR\s0 .IP "+" 4 \&\s-1VKILL\s0 .IP "+" 4 \&\s-1VLNEXT\s0 .IP "+" 4 \&\s-1VMIN\s0 .IP "+" 4 \&\s-1VQUIT\s0 .IP "+" 4 \&\s-1VREPRINT\s0 .IP "+" 4 \&\s-1VSTART\s0 .IP "+" 4 \&\s-1VSTOP\s0 .IP "+" 4 \&\s-1VSUSP\s0 .IP "\-" 4 \&\s-1VSWTCH\s0 .IP "+" 4 \&\s-1VT0\s0 .IP "+" 4 \&\s-1VT1\s0 .IP "+" 4 \&\s-1VTDLY\s0 .IP "+" 4 \&\s-1VTIME\s0 .IP "+" 4 \&\s-1VWERASE\s0 .IP "\-" 4 \&\s-1WRAP\s0 .IP "+" 4 \&\s-1XCASE\s0 .IP "\-" 4 \&\s-1XCLUDE\s0 .IP "\-" 4 \&\s-1XMT1EN\s0 .IP "+" 4 \&\s-1XTABS\s0 .SH "FOR MORE INFO SEE" .IX Header "FOR MORE INFO SEE" IO::Tty man/man3/JSON::PP.3pm000044400000176532152462503210010007 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::PP 3" .TH JSON::PP 3 "2021-01-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::PP \- JSON::XS compatible pure\-Perl module. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use JSON::PP; \& \& # exported functions, they croak on error \& # and expect/generate UTF\-8 \& \& $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; \& $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; \& \& # OO\-interface \& \& $json = JSON::PP\->new\->ascii\->pretty\->allow_nonref; \& \& $pretty_printed_json_text = $json\->encode( $perl_scalar ); \& $perl_scalar = $json\->decode( $json_text ); \& \& # Note that JSON version 2.0 and above will automatically use \& # JSON::XS or JSON::PP, so you should be able to just: \& \& use JSON; .Ve .SH "VERSION" .IX Header "VERSION" .Vb 1 \& 4.05 .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1JSON::PP\s0 is a pure perl \s-1JSON\s0 decoder/encoder, and (almost) compatible to much faster \s-1JSON::XS\s0 written by Marc Lehmann in C. \s-1JSON::PP\s0 works as a fallback module when you use \s-1JSON\s0 module without having installed \s-1JSON::XS.\s0 .PP Because of this fallback feature of \s-1JSON\s0.pm, \s-1JSON::PP\s0 tries not to be more JavaScript-friendly than \s-1JSON::XS\s0 (i.e. not to escape extra characters such as U+2028 and U+2029, etc), in order for you not to lose such JavaScript-friendliness silently when you use \s-1JSON\s0.pm and install \s-1JSON::XS\s0 for speed or by accident. If you need JavaScript-friendly RFC7159\-compliant pure perl module, try JSON::Tiny, which is derived from Mojolicious web framework and is also smaller and faster than \s-1JSON::PP.\s0 .PP \&\s-1JSON::PP\s0 has been in the Perl core since Perl 5.14, mainly for \&\s-1CPAN\s0 toolchain modules to parse \s-1META\s0.json. .SH "FUNCTIONAL INTERFACE" .IX Header "FUNCTIONAL INTERFACE" This section is taken from \s-1JSON::XS\s0 almost verbatim. \f(CW\*(C`encode_json\*(C'\fR and \f(CW\*(C`decode_json\*(C'\fR are exported by default. .SS "encode_json" .IX Subsection "encode_json" .Vb 1 \& $json_text = encode_json $perl_scalar .Ve .PP Converts the given Perl data structure to a \s-1UTF\-8\s0 encoded, binary string (that is, the string contains octets only). Croaks on error. .PP This function call is functionally identical to: .PP .Vb 1 \& $json_text = JSON::PP\->new\->utf8\->encode($perl_scalar) .Ve .PP Except being faster. .SS "decode_json" .IX Subsection "decode_json" .Vb 1 \& $perl_scalar = decode_json $json_text .Ve .PP The opposite of \f(CW\*(C`encode_json\*(C'\fR: expects an \s-1UTF\-8\s0 (binary) string and tries to parse that as an \s-1UTF\-8\s0 encoded \s-1JSON\s0 text, returning the resulting reference. Croaks on error. .PP This function call is functionally identical to: .PP .Vb 1 \& $perl_scalar = JSON::PP\->new\->utf8\->decode($json_text) .Ve .PP Except being faster. .SS "JSON::PP::is_bool" .IX Subsection "JSON::PP::is_bool" .Vb 1 \& $is_boolean = JSON::PP::is_bool($scalar) .Ve .PP Returns true if the passed scalar represents either JSON::PP::true or JSON::PP::false, two constants that act like \f(CW1\fR and \f(CW0\fR respectively and are also used to represent \s-1JSON\s0 \f(CW\*(C`true\*(C'\fR and \f(CW\*(C`false\*(C'\fR in Perl strings. .PP See \s-1MAPPING\s0, below, for more information on how \s-1JSON\s0 values are mapped to Perl. .SH "OBJECT-ORIENTED INTERFACE" .IX Header "OBJECT-ORIENTED INTERFACE" This section is also taken from \s-1JSON::XS.\s0 .PP The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. .SS "new" .IX Subsection "new" .Vb 1 \& $json = JSON::PP\->new .Ve .PP Creates a new \s-1JSON::PP\s0 object that can be used to de/encode \s-1JSON\s0 strings. All boolean flags described below are by default \fIdisabled\fR (with the exception of \f(CW\*(C`allow_nonref\*(C'\fR, which defaults to \fIenabled\fR since version \f(CW4.0\fR). .PP The mutators for flags all return the \s-1JSON::PP\s0 object again and thus calls can be chained: .PP .Vb 2 \& my $json = JSON::PP\->new\->utf8\->space_after\->encode({a => [1,2]}) \& => {"a": [1, 2]} .Ve .SS "ascii" .IX Subsection "ascii" .Vb 1 \& $json = $json\->ascii([$enable]) \& \& $enabled = $json\->get_ascii .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not generate characters outside the code range \f(CW0..127\fR (which is \s-1ASCII\s0). Any Unicode characters outside that range will be escaped using either a single \euXXXX (\s-1BMP\s0 characters) or a double \euHHHH\euLLLLL escape sequence, as per \s-1RFC4627.\s0 The resulting encoded \s-1JSON\s0 text can be treated as a native Unicode string, an ascii-encoded, latin1\-encoded or \s-1UTF\-8\s0 encoded string, or any other superset of \s-1ASCII.\s0 .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. This results in a faster and more compact format. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP The main use for this flag is to produce \s-1JSON\s0 texts that can be transmitted over a 7\-bit channel, as the encoded \s-1JSON\s0 texts will not contain any 8 bit characters. .PP .Vb 2 \& JSON::PP\->new\->ascii(1)\->encode([chr 0x10401]) \& => ["\eud801\eudc01"] .Ve .SS "latin1" .IX Subsection "latin1" .Vb 1 \& $json = $json\->latin1([$enable]) \& \& $enabled = $json\->get_latin1 .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the resulting \s-1JSON\s0 text as latin1 (or iso\-8859\-1), escaping any characters outside the code range \f(CW0..255\fR. The resulting string can be treated as a latin1\-encoded \s-1JSON\s0 text or a native Unicode string. The \f(CW\*(C`decode\*(C'\fR method will not be affected in any way by this flag, as \f(CW\*(C`decode\*(C'\fR by default expects Unicode, which is a strict superset of latin1. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP The main use for this flag is efficiently encoding binary data as \s-1JSON\s0 text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting \s-1JSON\s0 text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for \s-1JSON.\s0 It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other \s-1JSON\s0 encoders/decoders. .PP .Vb 2 \& JSON::PP\->new\->latin1\->encode (["\ex{89}\ex{abc}"] \& => ["\ex{89}\e\eu0abc"] # (perl syntax, U+abc escaped, U+89 not) .Ve .SS "utf8" .IX Subsection "utf8" .Vb 1 \& $json = $json\->utf8([$enable]) \& \& $enabled = $json\->get_utf8 .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the \s-1JSON\s0 result into \s-1UTF\-8,\s0 as required by many protocols, while the \&\f(CW\*(C`decode\*(C'\fR method expects to be handled an UTF\-8\-encoded string. Please note that UTF\-8\-encoded strings do not contain any characters outside the range \f(CW0..255\fR, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the \s-1UTF\-16\s0 and \s-1UTF\-32\s0 encoding families, as described in \s-1RFC4627.\s0 .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will return the \s-1JSON\s0 string as a (non-encoded) Unicode string, while \f(CW\*(C`decode\*(C'\fR expects thus a Unicode string. Any decoding or encoding (e.g. to \s-1UTF\-8\s0 or \s-1UTF\-16\s0) needs to be done yourself, e.g. using the Encode module. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP Example, output UTF\-16BE\-encoded \s-1JSON:\s0 .PP .Vb 2 \& use Encode; \& $jsontext = encode "UTF\-16BE", JSON::PP\->new\->encode ($object); .Ve .PP Example, decode UTF\-32LE\-encoded \s-1JSON:\s0 .PP .Vb 2 \& use Encode; \& $object = JSON::PP\->new\->decode (decode "UTF\-32LE", $jsontext); .Ve .SS "pretty" .IX Subsection "pretty" .Vb 1 \& $json = $json\->pretty([$enable]) .Ve .PP This enables (or disables) all of the \f(CW\*(C`indent\*(C'\fR, \f(CW\*(C`space_before\*(C'\fR and \&\f(CW\*(C`space_after\*(C'\fR (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. .SS "indent" .IX Subsection "indent" .Vb 1 \& $json = $json\->indent([$enable]) \& \& $enabled = $json\->get_indent .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. .PP If \f(CW$enable\fR is false, no newlines or indenting will be produced, and the resulting \s-1JSON\s0 text is guaranteed not to contain any \f(CW\*(C`newlines\*(C'\fR. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP The default indent space length is three. You can use \f(CW\*(C`indent_length\*(C'\fR to change the length. .SS "space_before" .IX Subsection "space_before" .Vb 1 \& $json = $json\->space_before([$enable]) \& \& $enabled = $json\->get_space_before .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space before the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .PP This setting has no effect when decoding \s-1JSON\s0 texts. You will also most likely combine this setting with \f(CW\*(C`space_after\*(C'\fR. .PP Example, space_before enabled, space_after and indent disabled: .PP .Vb 1 \& {"key" :"value"} .Ve .SS "space_after" .IX Subsection "space_after" .Vb 1 \& $json = $json\->space_after([$enable]) \& \& $enabled = $json\->get_space_after .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space after the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects and extra whitespace after the \f(CW\*(C`,\*(C'\fR separating key-value pairs and array members. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP Example, space_before and indent disabled, space_after enabled: .PP .Vb 1 \& {"key": "value"} .Ve .SS "relaxed" .IX Subsection "relaxed" .Vb 1 \& $json = $json\->relaxed([$enable]) \& \& $enabled = $json\->get_relaxed .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept some extensions to normal \s-1JSON\s0 syntax (see below). \f(CW\*(C`encode\*(C'\fR will not be affected in anyway. \fIBe aware that this option makes you accept invalid \&\s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP Currently accepted extensions are: .IP "\(bu" 4 list items can have an end-comma .Sp \&\s-1JSON\s0 \fIseparates\fR array elements and key-value pairs with commas. This can be annoying if you write \s-1JSON\s0 texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: .Sp .Vb 8 \& [ \& 1, \& 2, <\- this comma not normally allowed \& ] \& { \& "k1": "v1", \& "k2": "v2", <\- this comma not normally allowed \& } .Ve .IP "\(bu" 4 shell-style '#'\-comments .Sp Whenever \s-1JSON\s0 allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, # this comment not allowed in JSON \& # neither this one... \& ] .Ve .IP "\(bu" 4 C\-style multiple-line '/* */'\-comments (\s-1JSON::PP\s0 only) .Sp Whenever \s-1JSON\s0 allows whitespace, C\-style multiple-line comments are additionally allowed. Everything between \f(CW\*(C`/*\*(C'\fR and \f(CW\*(C`*/\*(C'\fR is a comment, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, /* this comment not allowed in JSON */ \& /* neither this one... */ \& ] .Ve .IP "\(bu" 4 \&\*(C+\-style one-line '//'\-comments (\s-1JSON::PP\s0 only) .Sp Whenever \s-1JSON\s0 allows whitespace, \*(C+\-style one-line comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, // this comment not allowed in JSON \& // neither this one... \& ] .Ve .IP "\(bu" 4 literal \s-1ASCII TAB\s0 characters in strings .Sp Literal \s-1ASCII TAB\s0 characters are now allowed in strings (and treated as \&\f(CW\*(C`\et\*(C'\fR). .Sp .Vb 4 \& [ \& "Hello\etWorld", \& "HelloWorld", # literal would not normally be allowed \& ] .Ve .SS "canonical" .IX Subsection "canonical" .Vb 1 \& $json = $json\->canonical([$enable]) \& \& $enabled = $json\->get_canonical .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will output \s-1JSON\s0 objects by sorting their keys. This is adding a comparatively high overhead. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). .PP This option is useful if you want the same data structure to be encoded as the same \s-1JSON\s0 text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP This setting has currently no effect on tied hashes. .SS "allow_nonref" .IX Subsection "allow_nonref" .Vb 1 \& $json = $json\->allow_nonref([$enable]) \& \& $enabled = $json\->get_allow_nonref .Ve .PP Unlike other boolean options, this opotion is enabled by default beginning with version \f(CW4.0\fR. .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method can convert a non-reference into its corresponding string, number or null \s-1JSON\s0 value, which is an extension to \s-1RFC4627.\s0 Likewise, \f(CW\*(C`decode\*(C'\fR will accept those \s-1JSON\s0 values instead of croaking. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will croak if it isn't passed an arrayref or hashref, as \s-1JSON\s0 texts must either be an object or array. Likewise, \f(CW\*(C`decode\*(C'\fR will croak if given something that is not a \&\s-1JSON\s0 object or array. .PP Example, encode a Perl scalar as \s-1JSON\s0 value without enabled \f(CW\*(C`allow_nonref\*(C'\fR, resulting in an error: .PP .Vb 2 \& JSON::PP\->new\->allow_nonref(0)\->encode ("Hello, World!") \& => hash\- or arrayref expected... .Ve .SS "allow_unknown" .IX Subsection "allow_unknown" .Vb 1 \& $json = $json\->allow_unknown([$enable]) \& \& $enabled = $json\->get_allow_unknown .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR will \fInot\fR throw an exception when it encounters values it cannot represent in \s-1JSON\s0 (for example, filehandles) but instead will encode a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value. Note that blessed objects are not included here and are handled separately by c. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters anything it cannot encode as \s-1JSON.\s0 .PP This option does not affect \f(CW\*(C`decode\*(C'\fR in any way, and it is recommended to leave it off unless you know your communications partner. .SS "allow_blessed" .IX Subsection "allow_blessed" .Vb 1 \& $json = $json\->allow_blessed([$enable]) \& \& $enabled = $json\->get_allow_blessed .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value is encoded instead of the object. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters a blessed object that it cannot convert otherwise. .PP This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .SS "convert_blessed" .IX Subsection "convert_blessed" .Vb 1 \& $json = $json\->convert_blessed([$enable]) \& \& $enabled = $json\->get_convert_blessed .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`TO_JSON\*(C'\fR method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. .PP The \f(CW\*(C`TO_JSON\*(C'\fR method may safely call die if it wants. If \f(CW\*(C`TO_JSON\*(C'\fR returns other blessed objects, those will be handled in the same way. \f(CW\*(C`TO_JSON\*(C'\fR must take care of not causing an endless recursion cycle (== crash) in this case. The name of \f(CW\*(C`TO_JSON\*(C'\fR was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any \f(CW\*(C`to_json\*(C'\fR function or method. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion. .PP This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .SS "allow_tags" .IX Subsection "allow_tags" .Vb 1 \& $json = $json\->allow_tags([$enable]) \& \& $enabled = $json\->get_allow_tags .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`FREEZE\*(C'\fR method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged \s-1JSON\s0 value (that \s-1JSON\s0 decoders cannot decode). .PP It also causes \f(CW\*(C`decode\*(C'\fR to parse such tagged \s-1JSON\s0 values and deserialise them via a call to the \f(CW\*(C`THAW\*(C'\fR method. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion, and tagged \s-1JSON\s0 values will cause a parse error in \f(CW\*(C`decode\*(C'\fR, as if tags were not part of the grammar. .SS "boolean_values" .IX Subsection "boolean_values" .Vb 1 \& $json\->boolean_values([$false, $true]) \& \& ($false, $true) = $json\->get_boolean_values .Ve .PP By default, \s-1JSON\s0 booleans will be decoded as overloaded \&\f(CW$JSON::PP::false\fR and \f(CW$JSON::PP::true\fR objects. .PP With this method you can specify your own boolean values for decoding \- on decode, \s-1JSON\s0 \f(CW\*(C`false\*(C'\fR will be decoded as a copy of \f(CW$false\fR, and \s-1JSON\s0 \&\f(CW\*(C`true\*(C'\fR will be decoded as \f(CW$true\fR (\*(L"copy\*(R" here is the same thing as assigning a value to another variable, i.e. \f(CW\*(C`$copy = $false\*(C'\fR). .PP This is useful when you want to pass a decoded data structure directly to other serialisers like \s-1YAML,\s0 Data::MessagePack and so on. .PP Note that this works only when you \f(CW\*(C`decode\*(C'\fR. You can set incompatible boolean objects (like boolean), but when you \f(CW\*(C`encode\*(C'\fR a data structure with such boolean objects, you still need to enable \f(CW\*(C`convert_blessed\*(C'\fR (and add a \f(CW\*(C`TO_JSON\*(C'\fR method if necessary). .PP Calling this method without any arguments will reset the booleans to their default values. .PP \&\f(CW\*(C`get_boolean_values\*(C'\fR will return both \f(CW$false\fR and \f(CW$true\fR values, or the empty list when they are set to the default. .SS "filter_json_object" .IX Subsection "filter_json_object" .Vb 1 \& $json = $json\->filter_json_object([$coderef]) .Ve .PP When \f(CW$coderef\fR is specified, it will be called from \f(CW\*(C`decode\*(C'\fR each time it decodes a \s-1JSON\s0 object. The only argument is a reference to the newly-created hash. If the code references returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (\s-1NOTE:\s0 \fInot\fR \f(CW\*(C`undef\*(C'\fR, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. .PP When \f(CW$coderef\fR is omitted or undefined, any existing callback will be removed and \f(CW\*(C`decode\*(C'\fR will not change the deserialised hash in any way. .PP Example, convert all \s-1JSON\s0 objects into the integer 5: .PP .Vb 5 \& my $js = JSON::PP\->new\->filter_json_object(sub { 5 }); \& # returns [5] \& $js\->decode(\*(Aq[{}]\*(Aq); \& # returns 5 \& $js\->decode(\*(Aq{"a":1, "b":2}\*(Aq); .Ve .SS "filter_json_single_key_object" .IX Subsection "filter_json_single_key_object" .Vb 1 \& $json = $json\->filter_json_single_key_object($key [=> $coderef]) .Ve .PP Works remotely similar to \f(CW\*(C`filter_json_object\*(C'\fR, but is only called for \&\s-1JSON\s0 objects having a single key named \f(CW$key\fR. .PP This \f(CW$coderef\fR is called before the one specified via \&\f(CW\*(C`filter_json_object\*(C'\fR, if any. It gets passed the single value in the \s-1JSON\s0 object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even \f(CW\*(C`undef\*(C'\fR but the empty list), the callback from \f(CW\*(C`filter_json_object\*(C'\fR will be called next, as if no single-key callback were specified. .PP If \f(CW$coderef\fR is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. .PP As this callback gets called less often then the \f(CW\*(C`filter_json_object\*(C'\fR one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key \s-1JSON\s0 objects are as close to the type-tagged value concept as \s-1JSON\s0 gets (it's basically an \s-1ID/VALUE\s0 tuple). Of course, \s-1JSON\s0 does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. .PP Typical names for the single object key are \f(CW\*(C`_\|_class_whatever_\|_\*(C'\fR, or \&\f(CW\*(C`$_\|_dollars_are_rarely_used_\|_$\*(C'\fR or \f(CW\*(C`}ugly_brace_placement\*(C'\fR, or even things like \f(CW\*(C`_\|_class_md5sum(classname)_\|_\*(C'\fR, to reduce the risk of clashing with real hashes. .PP Example, decode \s-1JSON\s0 objects of the form \f(CW\*(C`{ "_\|_widget_\|_" => }\*(C'\fR into the corresponding \f(CW$WIDGET{}\fR object: .PP .Vb 7 \& # return whatever is in $WIDGET{5}: \& JSON::PP \& \->new \& \->filter_json_single_key_object (_\|_widget_\|_ => sub { \& $WIDGET{ $_[0] } \& }) \& \->decode (\*(Aq{"_\|_widget_\|_": 5\*(Aq) \& \& # this can be used with a TO_JSON method in some "widget" class \& # for serialisation to json: \& sub WidgetBase::TO_JSON { \& my ($self) = @_; \& \& unless ($self\->{id}) { \& $self\->{id} = ..get..some..id..; \& $WIDGET{$self\->{id}} = $self; \& } \& \& { _\|_widget_\|_ => $self\->{id} } \& } .Ve .SS "shrink" .IX Subsection "shrink" .Vb 1 \& $json = $json\->shrink([$enable]) \& \& $enabled = $json\->get_shrink .Ve .PP If \f(CW$enable\fR is true (or missing), the string returned by \f(CW\*(C`encode\*(C'\fR will be shrunk (i.e. downgraded if possible). .PP The actual definition of what shrink does might change in future versions, but it will always try to save space at the expense of time. .PP If \f(CW$enable\fR is false, then \s-1JSON::PP\s0 does nothing. .SS "max_depth" .IX Subsection "max_depth" .Vb 1 \& $json = $json\->max_depth([$maximum_nesting_depth]) \& \& $max_depth = $json\->get_max_depth .Ve .PP Sets the maximum nesting level (default \f(CW512\fR) accepted while encoding or decoding. If a higher nesting level is detected in \s-1JSON\s0 text or a Perl data structure, then the encoder and decoder will stop and croak at that point. .PP Nesting level is defined by number of hash\- or arrayrefs that the encoder needs to traverse to reach a given point or the number of \f(CW\*(C`{\*(C'\fR or \f(CW\*(C`[\*(C'\fR characters without their matching closing parenthesis crossed to reach a given character in a string. .PP Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. .PP If no argument is given, the highest possible setting will be used, which is rarely useful. .PP See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 in \s-1JSON::XS\s0 for more info on why this is useful. .SS "max_size" .IX Subsection "max_size" .Vb 1 \& $json = $json\->max_size([$maximum_string_size]) \& \& $max_size = $json\->get_max_size .Ve .PP Set the maximum length a \s-1JSON\s0 text may have (in bytes) where decoding is being attempted. The default is \f(CW0\fR, meaning no limit. When \f(CW\*(C`decode\*(C'\fR is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on \f(CW\*(C`encode\*(C'\fR (yet). .PP If no argument is given, the limit check will be deactivated (same as when \&\f(CW0\fR is specified). .PP See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 in \s-1JSON::XS\s0 for more info on why this is useful. .SS "encode" .IX Subsection "encode" .Vb 1 \& $json_text = $json\->encode($perl_scalar) .Ve .PP Converts the given Perl value or data structure to its \s-1JSON\s0 representation. Croaks on error. .SS "decode" .IX Subsection "decode" .Vb 1 \& $perl_scalar = $json\->decode($json_text) .Ve .PP The opposite of \f(CW\*(C`encode\*(C'\fR: expects a \s-1JSON\s0 text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. .SS "decode_prefix" .IX Subsection "decode_prefix" .Vb 1 \& ($perl_scalar, $characters) = $json\->decode_prefix($json_text) .Ve .PP This works like the \f(CW\*(C`decode\*(C'\fR method, but instead of raising an exception when there is trailing garbage after the first \s-1JSON\s0 object, it will silently stop parsing there and return the number of characters consumed so far. .PP This is useful if your \s-1JSON\s0 texts are not delimited by an outer protocol and you need to know where the \s-1JSON\s0 text ends. .PP .Vb 2 \& JSON::PP\->new\->decode_prefix ("[1] the tail") \& => ([1], 3) .Ve .SH "FLAGS FOR JSON::PP ONLY" .IX Header "FLAGS FOR JSON::PP ONLY" The following flags and properties are for \s-1JSON::PP\s0 only. If you use any of these, you can't make your application run faster by replacing \&\s-1JSON::PP\s0 with \s-1JSON::XS.\s0 If you need these and also speed boost, you might want to try Cpanel::JSON::XS, a fork of \s-1JSON::XS\s0 by Reini Urban, which supports some of these (with a different set of incompatibilities). Most of these historical flags are only kept for backward compatibility, and should not be used in a new application. .SS "allow_singlequote" .IX Subsection "allow_singlequote" .Vb 2 \& $json = $json\->allow_singlequote([$enable]) \& $enabled = $json\->get_allow_singlequote .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept invalid \s-1JSON\s0 texts that contain strings that begin and end with single quotation marks. \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \&\fIBe aware that this option makes you accept invalid \s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP .Vb 3 \& $json\->allow_singlequote\->decode(qq|{"foo":\*(Aqbar\*(Aq}|); \& $json\->allow_singlequote\->decode(qq|{\*(Aqfoo\*(Aq:"bar"}|); \& $json\->allow_singlequote\->decode(qq|{\*(Aqfoo\*(Aq:\*(Aqbar\*(Aq}|); .Ve .SS "allow_barekey" .IX Subsection "allow_barekey" .Vb 2 \& $json = $json\->allow_barekey([$enable]) \& $enabled = $json\->get_allow_barekey .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept invalid \s-1JSON\s0 texts that contain \s-1JSON\s0 objects whose names don't begin and end with quotation marks. \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \fIBe aware that this option makes you accept invalid \s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP .Vb 1 \& $json\->allow_barekey\->decode(qq|{foo:"bar"}|); .Ve .SS "allow_bignum" .IX Subsection "allow_bignum" .Vb 2 \& $json = $json\->allow_bignum([$enable]) \& $enabled = $json\->get_allow_bignum .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will convert big integers Perl cannot handle as integer into Math::BigInt objects and convert floating numbers into Math::BigFloat objects. \f(CW\*(C`encode\*(C'\fR will convert \f(CW\*(C`Math::BigInt\*(C'\fR and \f(CW\*(C`Math::BigFloat\*(C'\fR objects into \s-1JSON\s0 numbers. .PP .Vb 4 \& $json\->allow_nonref\->allow_bignum; \& $bigfloat = $json\->decode(\*(Aq2.000000000000000000000000001\*(Aq); \& print $json\->encode($bigfloat); \& # => 2.000000000000000000000000001 .Ve .PP See also \s-1MAPPING\s0. .SS "loose" .IX Subsection "loose" .Vb 2 \& $json = $json\->loose([$enable]) \& $enabled = $json\->get_loose .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept invalid \s-1JSON\s0 texts that contain unescaped [\ex00\-\ex1f\ex22\ex5c] characters. \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \&\fIBe aware that this option makes you accept invalid \s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP .Vb 2 \& $json\->loose\->decode(qq|["abc \& def"]|); .Ve .SS "escape_slash" .IX Subsection "escape_slash" .Vb 2 \& $json = $json\->escape_slash([$enable]) \& $enabled = $json\->get_escape_slash .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR will explicitly escape \fIslash\fR (solidus; \f(CW\*(C`U+002F\*(C'\fR) characters to reduce the risk of \&\s-1XSS\s0 (cross site scripting) that may be caused by \f(CW\*(C`\*(C'\fR in a \s-1JSON\s0 text, with the cost of bloating the size of \s-1JSON\s0 texts. .PP This option may be useful when you embed \s-1JSON\s0 in \s-1HTML,\s0 but embedding arbitrary \s-1JSON\s0 in \s-1HTML\s0 (by some \s-1HTML\s0 template toolkit or by string interpolation) is risky in general. You must escape necessary characters in correct order, depending on the context. .PP \&\f(CW\*(C`decode\*(C'\fR will not be affected in any way. .SS "indent_length" .IX Subsection "indent_length" .Vb 2 \& $json = $json\->indent_length($number_of_spaces) \& $length = $json\->get_indent_length .Ve .PP This option is only useful when you also enable \f(CW\*(C`indent\*(C'\fR or \f(CW\*(C`pretty\*(C'\fR. .PP \&\s-1JSON::XS\s0 indents with three spaces when you \f(CW\*(C`encode\*(C'\fR (if requested by \f(CW\*(C`indent\*(C'\fR or \f(CW\*(C`pretty\*(C'\fR), and the number cannot be changed. \&\s-1JSON::PP\s0 allows you to change/get the number of indent spaces with these mutator/accessor. The default number of spaces is three (the same as \&\s-1JSON::XS\s0), and the acceptable range is from \f(CW0\fR (no indentation; it'd be better to disable indentation by \f(CWindent(0)\fR) to \f(CW15\fR. .SS "sort_by" .IX Subsection "sort_by" .Vb 2 \& $json = $json\->sort_by($code_ref) \& $json = $json\->sort_by($subroutine_name) .Ve .PP If you just want to sort keys (names) in \s-1JSON\s0 objects when you \&\f(CW\*(C`encode\*(C'\fR, enable \f(CW\*(C`canonical\*(C'\fR option (see above) that allows you to sort object keys alphabetically. .PP If you do need to sort non-alphabetically for whatever reasons, you can give a code reference (or a subroutine name) to \f(CW\*(C`sort_by\*(C'\fR, then the argument will be passed to Perl's \f(CW\*(C`sort\*(C'\fR built-in function. .PP As the sorting is done in the \s-1JSON::PP\s0 scope, you usually need to prepend \f(CW\*(C`JSON::PP::\*(C'\fR to the subroutine name, and the special variables \&\f(CW$a\fR and \f(CW$b\fR used in the subrontine used by \f(CW\*(C`sort\*(C'\fR function. .PP Example: .PP .Vb 9 \& my %ORDER = (id => 1, class => 2, name => 3); \& $json\->sort_by(sub { \& ($ORDER{$JSON::PP::a} // 999) <=> ($ORDER{$JSON::PP::b} // 999) \& or $JSON::PP::a cmp $JSON::PP::b \& }); \& print $json\->encode([ \& {name => \*(AqCPAN\*(Aq, id => 1, href => \*(Aqhttp://cpan.org\*(Aq} \& ]); \& # [{"id":1,"name":"CPAN","href":"http://cpan.org"}] .Ve .PP Note that \f(CW\*(C`sort_by\*(C'\fR affects all the plain hashes in the data structure. If you need finer control, \f(CW\*(C`tie\*(C'\fR necessary hashes with a module that implements ordered hash (such as Hash::Ordered and Tie::IxHash). \&\f(CW\*(C`canonical\*(C'\fR and \f(CW\*(C`sort_by\*(C'\fR don't affect the key order in \f(CW\*(C`tie\*(C'\fRd hashes. .PP .Vb 5 \& use Hash::Ordered; \& tie my %hash, \*(AqHash::Ordered\*(Aq, \& (name => \*(AqCPAN\*(Aq, id => 1, href => \*(Aqhttp://cpan.org\*(Aq); \& print $json\->encode([\e%hash]); \& # [{"name":"CPAN","id":1,"href":"http://cpan.org"}] # order is kept .Ve .SH "INCREMENTAL PARSING" .IX Header "INCREMENTAL PARSING" This section is also taken from \s-1JSON::XS.\s0 .PP In some cases, there is the need for incremental parsing of \s-1JSON\s0 texts. While this module always has to keep both \s-1JSON\s0 text and resulting Perl data structure in memory at one time, it does allow you to parse a \&\s-1JSON\s0 stream incrementally. It does so by accumulating text until it has a full \s-1JSON\s0 object, which it then can decode. This process is similar to using \f(CW\*(C`decode_prefix\*(C'\fR to see if a full \s-1JSON\s0 object is available, but is much more efficient (and can be implemented with a minimum of method calls). .PP \&\s-1JSON::PP\s0 will only attempt to parse the \s-1JSON\s0 text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid \s-1JSON\s0 text has been seen. This means you need to set resource limits (e.g. \f(CW\*(C`max_size\*(C'\fR) to ensure the parser will stop parsing in the presence if syntax errors. .PP The following methods implement this incremental parser. .SS "incr_parse" .IX Subsection "incr_parse" .Vb 1 \& $json\->incr_parse( [$string] ) # void context \& \& $obj_or_undef = $json\->incr_parse( [$string] ) # scalar context \& \& @obj_or_empty = $json\->incr_parse( [$string] ) # list context .Ve .PP This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). .PP If \f(CW$string\fR is given, then this string is appended to the already existing \s-1JSON\s0 fragment stored in the \f(CW$json\fR object. .PP After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. .PP If the method is called in scalar context, then it will try to extract exactly \fIone\fR \s-1JSON\s0 object. If that is successful, it will return this object, otherwise it will return \f(CW\*(C`undef\*(C'\fR. If there is a parse error, this method will croak just as \f(CW\*(C`decode\*(C'\fR would do (one can then use \&\f(CW\*(C`incr_skip\*(C'\fR to skip the erroneous part). This is the most common way of using the method. .PP And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the \s-1JSON\s0 objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed \s-1JSON\s0 texts will be lost. .PP Example: Parse some \s-1JSON\s0 arrays/objects in a given string and return them. .PP .Vb 1 \& my @objs = JSON::PP\->new\->incr_parse ("[5][7][1,2]"); .Ve .SS "incr_text" .IX Subsection "incr_text" .Vb 1 \& $lvalue_string = $json\->incr_text .Ve .PP This method returns the currently stored \s-1JSON\s0 fragment as an lvalue, that is, you can manipulate it. This \fIonly\fR works when a preceding call to \&\f(CW\*(C`incr_parse\*(C'\fR in \fIscalar context\fR successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it \fIwill\fR fail under real world conditions). As a special exception, you can also call this method before having parsed anything. .PP That means you can only use this function to look at or manipulate text before or after complete \s-1JSON\s0 objects, not while the parser is in the middle of parsing a \s-1JSON\s0 object. .PP This function is useful in two cases: a) finding the trailing text after a \&\s-1JSON\s0 object or b) parsing multiple \s-1JSON\s0 objects separated by non-JSON text (such as commas). .SS "incr_skip" .IX Subsection "incr_skip" .Vb 1 \& $json\->incr_skip .Ve .PP This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after \&\f(CW\*(C`incr_parse\*(C'\fR died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. .PP The difference to \f(CW\*(C`incr_reset\*(C'\fR is that only text until the parse error occurred is removed. .SS "incr_reset" .IX Subsection "incr_reset" .Vb 1 \& $json\->incr_reset .Ve .PP This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. .PP This is useful if you want to repeatedly parse \s-1JSON\s0 objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. .SH "MAPPING" .IX Header "MAPPING" Most of this section is also taken from \s-1JSON::XS.\s0 .PP This section describes how \s-1JSON::PP\s0 maps Perl values to \s-1JSON\s0 values and vice versa. These mappings are designed to \*(L"do the right thing\*(R" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). .PP For the more enlightened: note that in the following descriptions, lowercase \fIperl\fR refers to the Perl interpreter, while uppercase \fIPerl\fR refers to the abstract Perl language itself. .SS "\s-1JSON\s0 \-> \s-1PERL\s0" .IX Subsection "JSON -> PERL" .IP "object" 4 .IX Item "object" A \s-1JSON\s0 object becomes a reference to a hash in Perl. No ordering of object keys is preserved (\s-1JSON\s0 does not preserve object key ordering itself). .IP "array" 4 .IX Item "array" A \s-1JSON\s0 array becomes a reference to an array in Perl. .IP "string" 4 .IX Item "string" A \s-1JSON\s0 string becomes a string scalar in Perl \- Unicode codepoints in \s-1JSON\s0 are represented by the same codepoints in the Perl string, so no manual decoding is necessary. .IP "number" 4 .IX Item "number" A \s-1JSON\s0 number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. .Sp If the number consists of digits only, \s-1JSON::PP\s0 will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the \s-1JSON\s0 number will be re-encoded to a \s-1JSON\s0 string). .Sp Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the \s-1JSON\s0 number will still be re-encoded as a \s-1JSON\s0 number). .Sp Note that precision is not accuracy \- binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, \s-1JSON::PP\s0 only guarantees precision up to but not including the least significant bit. .Sp When \f(CW\*(C`allow_bignum\*(C'\fR is enabled, big integer values and any numeric values will be converted into Math::BigInt and Math::BigFloat objects respectively, without becoming string scalars or losing precision. .IP "true, false" 4 .IX Item "true, false" These \s-1JSON\s0 atoms become \f(CW\*(C`JSON::PP::true\*(C'\fR and \f(CW\*(C`JSON::PP::false\*(C'\fR, respectively. They are overloaded to act almost exactly like the numbers \&\f(CW1\fR and \f(CW0\fR. You can check whether a scalar is a \s-1JSON\s0 boolean by using the \f(CW\*(C`JSON::PP::is_bool\*(C'\fR function. .IP "null" 4 .IX Item "null" A \s-1JSON\s0 null atom becomes \f(CW\*(C`undef\*(C'\fR in Perl. .ie n .IP "shell-style comments (""# \fItext\fP"")" 4 .el .IP "shell-style comments (\f(CW# \f(CItext\f(CW\fR)" 4 .IX Item "shell-style comments (# text)" As a nonstandard extension to the \s-1JSON\s0 syntax that is enabled by the \&\f(CW\*(C`relaxed\*(C'\fR setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. .ie n .IP "tagged values (""(\fItag\fP)\fIvalue\fP"")." 4 .el .IP "tagged values (\f(CW(\f(CItag\f(CW)\f(CIvalue\f(CW\fR)." 4 .IX Item "tagged values ((tag)value)." Another nonstandard extension to the \s-1JSON\s0 syntax, enabled with the \&\f(CW\*(C`allow_tags\*(C'\fR setting, are tagged values. In this implementation, the \&\fItag\fR must be a perl package/class name encoded as a \s-1JSON\s0 string, and the \&\fIvalue\fR must be a \s-1JSON\s0 array encoding optional constructor arguments. .Sp See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .SS "\s-1PERL\s0 \-> \s-1JSON\s0" .IX Subsection "PERL -> JSON" The mapping from Perl to \s-1JSON\s0 is slightly more difficult, as Perl is a truly typeless language, so we can only guess which \s-1JSON\s0 type is meant by a Perl value. .IP "hash references" 4 .IX Item "hash references" Perl hash references become \s-1JSON\s0 objects. As there is no inherent ordering in hash keys (or \s-1JSON\s0 objects), they will usually be encoded in a pseudo-random order. \s-1JSON::PP\s0 can optionally sort the hash keys (determined by the \fIcanonical\fR flag and/or \fIsort_by\fR property), so the same data structure will serialise to the same \s-1JSON\s0 text (given same settings and version of \s-1JSON::PP\s0), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some \&\s-1JSON\s0 text against another for equality. .IP "array references" 4 .IX Item "array references" Perl array references become \s-1JSON\s0 arrays. .IP "other references" 4 .IX Item "other references" Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers \f(CW0\fR and \&\f(CW1\fR, which get turned into \f(CW\*(C`false\*(C'\fR and \f(CW\*(C`true\*(C'\fR atoms in \s-1JSON.\s0 You can also use \f(CW\*(C`JSON::PP::false\*(C'\fR and \f(CW\*(C`JSON::PP::true\*(C'\fR to improve readability. .Sp .Vb 1 \& to_json [\e0, JSON::PP::true] # yields [false,true] .Ve .IP "JSON::PP::true, JSON::PP::false" 4 .IX Item "JSON::PP::true, JSON::PP::false" These special values become \s-1JSON\s0 true and \s-1JSON\s0 false values, respectively. You can also use \f(CW\*(C`\e1\*(C'\fR and \f(CW\*(C`\e0\*(C'\fR directly if you want. .IP "JSON::PP::null" 4 .IX Item "JSON::PP::null" This special value becomes \s-1JSON\s0 null. .IP "blessed objects" 4 .IX Item "blessed objects" Blessed objects are not directly representable in \s-1JSON,\s0 but \f(CW\*(C`JSON::PP\*(C'\fR allows various ways of handling objects. See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .IP "simple scalars" 4 .IX Item "simple scalars" Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: \s-1JSON::PP\s0 will encode undefined scalars as \&\s-1JSON\s0 \f(CW\*(C`null\*(C'\fR values, scalars that have last been used in a string context before encoding as \s-1JSON\s0 strings, and anything else as number value: .Sp .Vb 4 \& # dump as number \& encode_json [2] # yields [2] \& encode_json [\-3.0e17] # yields [\-3e+17] \& my $value = 5; encode_json [$value] # yields [5] \& \& # used as string, so dump as string \& print $value; \& encode_json [$value] # yields ["5"] \& \& # undef becomes null \& encode_json [undef] # yields [null] .Ve .Sp You can force the type to be a \s-1JSON\s0 string by stringifying it: .Sp .Vb 5 \& my $x = 3.1; # some variable containing a number \& "$x"; # stringified \& $x .= ""; # another, more awkward way to stringify \& print $x; # perl does it for you, too, quite often \& # (but for older perls) .Ve .Sp You can force the type to be a \s-1JSON\s0 number by numifying it: .Sp .Vb 3 \& my $x = "3"; # some variable containing a string \& $x += 0; # numify it, ensuring it will be dumped as a number \& $x *= 1; # same thing, the choice is yours. .Ve .Sp You can not currently force the type in other, less obscure, ways. .Sp Since version 2.91_01, \s-1JSON::PP\s0 uses a different number detection logic that converts a scalar that is possible to turn into a number safely. The new logic is slightly faster, and tends to help people who use older perl or who want to encode complicated data structure. However, this may results in a different \s-1JSON\s0 text from the one \s-1JSON::XS\s0 encodes (and thus may break tests that compare entire \s-1JSON\s0 texts). If you do need the previous behavior for compatibility or for finer control, set \s-1PERL_JSON_PP_USE_B\s0 environmental variable to true before you \&\f(CW\*(C`use\*(C'\fR \s-1JSON::PP\s0 (or \s-1JSON\s0.pm). .Sp Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's \- these cannot be represented in \s-1JSON,\s0 and it is an error to pass those in. .Sp \&\s-1JSON::PP\s0 (and \s-1JSON::XS\s0) trusts what you pass to \f(CW\*(C`encode\*(C'\fR method (or \f(CW\*(C`encode_json\*(C'\fR function) is a clean, validated data structure with values that can be represented as valid \s-1JSON\s0 values only, because it's not from an external data source (as opposed to \s-1JSON\s0 texts you pass to \&\f(CW\*(C`decode\*(C'\fR or \f(CW\*(C`decode_json\*(C'\fR, which \s-1JSON::PP\s0 considers tainted and doesn't trust). As \s-1JSON::PP\s0 doesn't know exactly what you and consumers of your \s-1JSON\s0 texts want the unexpected values to be (you may want to convert them into null, or to stringify them with or without normalisation (string representation of infinities/NaN may vary depending on platforms), or to croak without conversion), you're advised to do what you and your consumers need before you encode, and also not to numify values that may start with values that look like a number (including infinities/NaN), without validating. .SS "\s-1OBJECT SERIALISATION\s0" .IX Subsection "OBJECT SERIALISATION" As \s-1JSON\s0 cannot directly represent Perl objects, you have to choose between a pure \s-1JSON\s0 representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the \s-1JSON\s0 syntax, tagged values. .PP \fI\s-1SERIALISATION\s0\fR .IX Subsection "SERIALISATION" .PP What happens when \f(CW\*(C`JSON::PP\*(C'\fR encounters a Perl object depends on the \&\f(CW\*(C`allow_blessed\*(C'\fR, \f(CW\*(C`convert_blessed\*(C'\fR, \f(CW\*(C`allow_tags\*(C'\fR and \f(CW\*(C`allow_bignum\*(C'\fR settings, which are used in this order: .ie n .IP "1. ""allow_tags"" is enabled and the object has a ""FREEZE"" method." 4 .el .IP "1. \f(CWallow_tags\fR is enabled and the object has a \f(CWFREEZE\fR method." 4 .IX Item "1. allow_tags is enabled and the object has a FREEZE method." In this case, \f(CW\*(C`JSON::PP\*(C'\fR creates a tagged \s-1JSON\s0 value, using a nonstandard extension to the \s-1JSON\s0 syntax. .Sp This works by invoking the \f(CW\*(C`FREEZE\*(C'\fR method on the object, with the first argument being the object to serialise, and the second argument being the constant string \f(CW\*(C`JSON\*(C'\fR to distinguish it from other serialisers. .Sp The \f(CW\*(C`FREEZE\*(C'\fR method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged \s-1JSON\s0 value in the following format: .Sp .Vb 1 \& ("classname")[FREEZE return values...] .Ve .Sp e.g.: .Sp .Vb 3 \& ("URI")["http://www.google.com/"] \& ("MyDate")[2013,10,29] \& ("ImageData::JPEG")["Z3...VlCg=="] .Ve .Sp For example, the hypothetical \f(CW\*(C`My::Object\*(C'\fR \f(CW\*(C`FREEZE\*(C'\fR method might use the objects \f(CW\*(C`type\*(C'\fR and \f(CW\*(C`id\*(C'\fR members to encode the object: .Sp .Vb 2 \& sub My::Object::FREEZE { \& my ($self, $serialiser) = @_; \& \& ($self\->{type}, $self\->{id}) \& } .Ve .ie n .IP "2. ""convert_blessed"" is enabled and the object has a ""TO_JSON"" method." 4 .el .IP "2. \f(CWconvert_blessed\fR is enabled and the object has a \f(CWTO_JSON\fR method." 4 .IX Item "2. convert_blessed is enabled and the object has a TO_JSON method." In this case, the \f(CW\*(C`TO_JSON\*(C'\fR method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into \&\s-1JSON.\s0 This scalar replaces the object in the \s-1JSON\s0 text. .Sp For example, the following \f(CW\*(C`TO_JSON\*(C'\fR method will convert all \s-1URI\s0 objects to \s-1JSON\s0 strings when serialised. The fact that these values originally were \s-1URI\s0 objects is lost. .Sp .Vb 4 \& sub URI::TO_JSON { \& my ($uri) = @_; \& $uri\->as_string \& } .Ve .ie n .IP "3. ""allow_bignum"" is enabled and the object is a ""Math::BigInt"" or ""Math::BigFloat""." 4 .el .IP "3. \f(CWallow_bignum\fR is enabled and the object is a \f(CWMath::BigInt\fR or \f(CWMath::BigFloat\fR." 4 .IX Item "3. allow_bignum is enabled and the object is a Math::BigInt or Math::BigFloat." The object will be serialised as a \s-1JSON\s0 number value. .ie n .IP "4. ""allow_blessed"" is enabled." 4 .el .IP "4. \f(CWallow_blessed\fR is enabled." 4 .IX Item "4. allow_blessed is enabled." The object will be serialised as a \s-1JSON\s0 null value. .IP "5. none of the above" 4 .IX Item "5. none of the above" If none of the settings are enabled or the respective methods are missing, \&\f(CW\*(C`JSON::PP\*(C'\fR throws an exception. .PP \fI\s-1DESERIALISATION\s0\fR .IX Subsection "DESERIALISATION" .PP For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case \f(CW\*(C`allow_tags\*(C'\fR decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the \f(CW\*(C`filter_json_object\*(C'\fR or \&\f(CW\*(C`filter_json_single_key_object\*(C'\fR callbacks to get some real objects our of your \s-1JSON.\s0 .PP This section only considers the tagged value case: a tagged \s-1JSON\s0 object is encountered during decoding and \f(CW\*(C`allow_tags\*(C'\fR is disabled, a parse error will result (as if tagged values were not part of the grammar). .PP If \f(CW\*(C`allow_tags\*(C'\fR is enabled, \f(CW\*(C`JSON::PP\*(C'\fR will look up the \f(CW\*(C`THAW\*(C'\fR method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. .PP Otherwise, the \f(CW\*(C`THAW\*(C'\fR method is invoked with the classname as first argument, the constant string \f(CW\*(C`JSON\*(C'\fR as second argument, and all the values from the \s-1JSON\s0 array (the values originally returned by the \&\f(CW\*(C`FREEZE\*(C'\fR method) as remaining arguments. .PP The method must then return the object. While technically you can return any Perl scalar, you might have to enable the \f(CW\*(C`allow_nonref\*(C'\fR setting to make that work in all cases, so better return an actual blessed reference. .PP As an example, let's implement a \f(CW\*(C`THAW\*(C'\fR function that regenerates the \&\f(CW\*(C`My::Object\*(C'\fR from the \f(CW\*(C`FREEZE\*(C'\fR example earlier: .PP .Vb 2 \& sub My::Object::THAW { \& my ($class, $serialiser, $type, $id) = @_; \& \& $class\->new (type => $type, id => $id) \& } .Ve .SH "ENCODING/CODESET FLAG NOTES" .IX Header "ENCODING/CODESET FLAG NOTES" This section is taken from \s-1JSON::XS.\s0 .PP The interested reader might have seen a number of flags that signify encodings or codesets \- \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR. There seems to be some confusion on what these do, so here is a short comparison: .PP \&\f(CW\*(C`utf8\*(C'\fR controls whether the \s-1JSON\s0 text created by \f(CW\*(C`encode\*(C'\fR (and expected by \f(CW\*(C`decode\*(C'\fR) is \s-1UTF\-8\s0 encoded or not, while \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR only control whether \f(CW\*(C`encode\*(C'\fR escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. .PP Care has been taken to make all flags symmetrical with respect to \&\f(CW\*(C`encode\*(C'\fR and \f(CW\*(C`decode\*(C'\fR, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used \&\- in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. .PP Below comes a verbose discussion of these flags. Note that a \*(L"codeset\*(R" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and \fIencodes\fR them, in our case into octets. Unicode is (among other things) a codeset, \s-1UTF\-8\s0 is an encoding, and \s-1ISO\-8859\-1\s0 (= latin 1) and \s-1ASCII\s0 are both codesets \fIand\fR encodings at the same time, which can be confusing. .ie n .IP """utf8"" flag disabled" 4 .el .IP "\f(CWutf8\fR flag disabled" 4 .IX Item "utf8 flag disabled" When \f(CW\*(C`utf8\*(C'\fR is disabled (the default), then \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except \&\*(L"(re\-)interpreting\*(R" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). .Sp This is useful when you want to do the encoding yourself (e.g. when you want to have \s-1UTF\-16\s0 encoded \s-1JSON\s0 texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to \s-1UTF\-8\s0 you certainly do \s-1NOT\s0 want to \s-1UTF\-8\s0 encode your data first and have Perl encode it another time). .ie n .IP """utf8"" flag enabled" 4 .el .IP "\f(CWutf8\fR flag enabled" 4 .IX Item "utf8 flag enabled" If the \f(CW\*(C`utf8\*(C'\fR\-flag is enabled, \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR will encode all characters using the corresponding \s-1UTF\-8\s0 multi-byte sequence, and will expect your input strings to be encoded as \s-1UTF\-8,\s0 that is, no \*(L"character\*(R" of the input string must have any value > 255, as \s-1UTF\-8\s0 does not allow that. .Sp The \f(CW\*(C`utf8\*(C'\fR flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get an \s-1UTF\-8\s0 encoded octet/binary string in Perl. .ie n .IP """latin1"" or ""ascii"" flags enabled" 4 .el .IP "\f(CWlatin1\fR or \f(CWascii\fR flags enabled" 4 .IX Item "latin1 or ascii flags enabled" With \f(CW\*(C`latin1\*(C'\fR (or \f(CW\*(C`ascii\*(C'\fR) enabled, \f(CW\*(C`encode\*(C'\fR will escape characters with ordinal values > 255 (> 127 with \f(CW\*(C`ascii\*(C'\fR) and encode the remaining characters as specified by the \f(CW\*(C`utf8\*(C'\fR flag. .Sp If \f(CW\*(C`utf8\*(C'\fR is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a \&\s-1ISO\-8859\-1\s0 string, and a Unicode string with all character values < 128 is the same thing as an \s-1ASCII\s0 string in Perl). .Sp If \f(CW\*(C`utf8\*(C'\fR is enabled, you still get a correct UTF\-8\-encoded string, regardless of these flags, just some more characters will be escaped using \&\f(CW\*(C`\euXXXX\*(C'\fR then before. .Sp Note that \s-1ISO\-8859\-1\-\s0\fIencoded\fR strings are not compatible with \s-1UTF\-8\s0 encoding, while ASCII-encoded strings are. That is because the \s-1ISO\-8859\-1\s0 encoding is \s-1NOT\s0 a subset of \s-1UTF\-8\s0 (despite the \s-1ISO\-8859\-1\s0 \fIcodeset\fR being a subset of Unicode), while \s-1ASCII\s0 is. .Sp Surprisingly, \f(CW\*(C`decode\*(C'\fR will ignore these flags and so treat all input values as governed by the \f(CW\*(C`utf8\*(C'\fR flag. If it is disabled, this allows you to decode \s-1ISO\-8859\-1\-\s0 and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode \s-1UTF\-8\s0 encoded strings. .Sp So neither \f(CW\*(C`latin1\*(C'\fR nor \f(CW\*(C`ascii\*(C'\fR are incompatible with the \f(CW\*(C`utf8\*(C'\fR flag \- they only govern when the \s-1JSON\s0 output engine escapes a character or not. .Sp The main use for \f(CW\*(C`latin1\*(C'\fR is to relatively efficiently store binary data as \s-1JSON,\s0 at the expense of breaking compatibility with most \s-1JSON\s0 decoders. .Sp The main use for \f(CW\*(C`ascii\*(C'\fR is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as \s-1UTF\-8, ISO\-8859\-1, ASCII, KOI8\-R\s0 or most about any character set and 8\-bit\-encoding, and still get the same data structure back. This is useful when your channel for \s-1JSON\s0 transfer is not 8\-bit clean or the encoding might be mangled in between (e.g. in mail), and works because \s-1ASCII\s0 is a proper subset of most 8\-bit and multibyte encodings in use in the world. .SH "BUGS" .IX Header "BUGS" Please report bugs on a specific behavior of this module to \s-1RT\s0 or GitHub issues (preferred): .PP .PP .PP As for new features and requests to change common behaviors, please ask the author of \s-1JSON::XS\s0 (Marc Lehmann, ) first, by email (important!), to keep compatibility among \s-1JSON\s0.pm backends. .PP Generally speaking, if you need something special for you, you are advised to create a new module, maybe based on JSON::Tiny, which is smaller and written in a much cleaner way than this module. .SH "SEE ALSO" .IX Header "SEE ALSO" The \fIjson_pp\fR command line utility for quick experiments. .PP \&\s-1JSON::XS\s0, Cpanel::JSON::XS, and JSON::Tiny for faster alternatives. \&\s-1JSON\s0 and JSON::MaybeXS for easy migration. .PP JSON::PP::Compat5005 and JSON::PP::Compat5006 for older perl users. .PP \&\s-1RFC4627\s0 () .PP \&\s-1RFC7159\s0 () .PP \&\s-1RFC8259\s0 () .SH "AUTHOR" .IX Header "AUTHOR" Makamaka Hannyaharamitu, .SH "CURRENT MAINTAINER" .IX Header "CURRENT MAINTAINER" Kenichi Ishigaki, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2007\-2016 by Makamaka Hannyaharamitu .PP Most of the documentation is taken from \s-1JSON::XS\s0 by Marc Lehmann .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::ProfileDumper.3pm000044400000020541152462503210012056 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::ProfileDumper 3" .TH DBI::ProfileDumper 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::ProfileDumper \- profile DBI usage and output data to a file .SH "SYNOPSIS" .IX Header "SYNOPSIS" To profile an existing program using DBI::ProfileDumper, set the \&\s-1DBI_PROFILE\s0 environment variable and run your program as usual. For example, using bash: .PP .Vb 1 \& DBI_PROFILE=2/DBI::ProfileDumper program.pl .Ve .PP Then analyze the generated file (\fIdbi.prof\fR) with dbiprof: .PP .Vb 1 \& dbiprof .Ve .PP You can also activate DBI::ProfileDumper from within your code: .PP .Vb 1 \& use DBI; \& \& # profile with default path (2) and output file (dbi.prof) \& $dbh\->{Profile} = "!Statement/DBI::ProfileDumper"; \& \& # same thing, spelled out \& $dbh\->{Profile} = "!Statement/DBI::ProfileDumper/File:dbi.prof"; \& \& # another way to say it \& use DBI::ProfileDumper; \& $dbh\->{Profile} = DBI::ProfileDumper\->new( \& Path => [ \*(Aq!Statement\*(Aq ], \& File => \*(Aqdbi.prof\*(Aq ); \& \& # using a custom path \& $dbh\->{Profile} = DBI::ProfileDumper\->new( \& Path => [ "foo", "bar" ], \& File => \*(Aqdbi.prof\*(Aq, \& ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBI::ProfileDumper is a subclass of DBI::Profile which dumps profile data to disk instead of printing a summary to your screen. You can then use dbiprof to analyze the data in a number of interesting ways, or you can roll your own analysis using DBI::ProfileData. .PP \&\fB\s-1NOTE:\s0\fR For Apache/mod_perl applications, use DBI::ProfileDumper::Apache. .SH "USAGE" .IX Header "USAGE" One way to use this module is just to enable it in your \f(CW$dbh\fR: .PP .Vb 1 \& $dbh\->{Profile} = "1/DBI::ProfileDumper"; .Ve .PP This will write out profile data by statement into a file called \&\fIdbi.prof\fR. If you want to modify either of these properties, you can construct the DBI::ProfileDumper object yourself: .PP .Vb 5 \& use DBI::ProfileDumper; \& $dbh\->{Profile} = DBI::ProfileDumper\->new( \& Path => [ \*(Aq!Statement\*(Aq ], \& File => \*(Aqdbi.prof\*(Aq \& ); .Ve .PP The \f(CW\*(C`Path\*(C'\fR option takes the same values as in DBI::Profile. The \f(CW\*(C`File\*(C'\fR option gives the name of the file where results will be collected. If it already exists it will be overwritten. .PP You can also activate this module by setting the \s-1DBI_PROFILE\s0 environment variable: .PP .Vb 1 \& $ENV{DBI_PROFILE} = "!Statement/DBI::ProfileDumper"; .Ve .PP This will cause all \s-1DBI\s0 handles to share the same profiling object. .SH "METHODS" .IX Header "METHODS" The following methods are available to be called using the profile object. You can get access to the profile object from the Profile key in any \s-1DBI\s0 handle: .PP .Vb 1 \& my $profile = $dbh\->{Profile}; .Ve .SS "flush_to_disk" .IX Subsection "flush_to_disk" .Vb 1 \& $profile\->flush_to_disk() .Ve .PP Flushes all collected profile data to disk and empties the Data hash. Returns the filename written to. If no profile data has been collected then the file is not written and \fBflush_to_disk()\fR returns undef. .PP The file is locked while it's being written. A process 'consuming' the files while they're being written to, should rename the file first, then lock it, then read it, then close and delete it. The \f(CW\*(C`DeleteFiles\*(C'\fR option to DBI::ProfileData does the right thing. .PP This method may be called multiple times during a program run. .SS "empty" .IX Subsection "empty" .Vb 1 \& $profile\->empty() .Ve .PP Clears the Data hash without writing to disk. .SS "filename" .IX Subsection "filename" .Vb 1 \& $filename = $profile\->filename(); .Ve .PP Get or set the filename. .PP The filename can be specified as a \s-1CODE\s0 reference, in which case the referenced code should return the filename to be used. The code will be called with the profile object as its first argument. .SH "DATA FORMAT" .IX Header "DATA FORMAT" The data format written by DBI::ProfileDumper starts with a header containing the version number of the module used to generate it. Then a block of variable declarations describes the profile. After two newlines, the profile data forms the body of the file. For example: .PP .Vb 3 \& DBI::ProfileDumper 2.003762 \& Path = [ \*(Aq!Statement\*(Aq, \*(Aq!MethodName\*(Aq ] \& Program = t/42profile_data.t \& \& + 1 SELECT name FROM users WHERE id = ? \& + 2 prepare \& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 \& + 2 execute \& 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 \& + 2 fetchrow_hashref \& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 \& + 1 UPDATE users SET name = ? WHERE id = ? \& + 2 prepare \& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 \& + 2 execute \& = 1 0.0312958955764771 0.000490069389343262 0.000176072120666504 0.00140702724456787 1023115819.83019 1023115819.86576 .Ve .PP The lines beginning with \f(CW\*(C`+\*(C'\fR signs signify keys. The number after the \f(CW\*(C`+\*(C'\fR sign shows the nesting level of the key. Lines beginning with \f(CW\*(C`=\*(C'\fR are the actual profile data, in the same order as in DBI::Profile. .PP Note that the same path may be present multiple times in the data file since \f(CW\*(C`format()\*(C'\fR may be called more than once. When read by DBI::ProfileData the data points will be merged to produce a single data set for each distinct path. .PP The key strings are transformed in three ways. First, all backslashes are doubled. Then all newlines and carriage-returns are transformed into \f(CW\*(C`\en\*(C'\fR and \f(CW\*(C`\er\*(C'\fR respectively. Finally, any \s-1NULL\s0 bytes (\f(CW\*(C`\e0\*(C'\fR) are entirely removed. When DBI::ProfileData reads the file the first two transformations will be reversed, but \s-1NULL\s0 bytes will not be restored. .SH "AUTHOR" .IX Header "AUTHOR" Sam Tregar .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2002 Sam Tregar .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself. man/man3/Crypt::SSLeay.3pm000044400000053070152462503210011147 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "SSLeay 3" .TH SSLeay 3 "2014-04-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Crypt::SSLeay \- OpenSSL support for LWP .SH "HEARTBLEED WARNING" .IX Header "HEARTBLEED WARNING" \&\f(CW\*(C`perl Makefile.PL\*(C'\fR will display a warning if it thinks your OpenSSL might be vulnerable to the Heartbleed Bug . You can, of course, go ahead and install the module, but you should be aware that your system might be exposed to an extremely serious vulnerability. This is just a heuristic based on the version reported by OpenSSL. It is entirely possible that your distrbution actually pushed a patched library, so if you have concerns, you should investigate further. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use Net::SSL; \& use LWP::UserAgent; \& \& my $ua = LWP::UserAgent\->new( \& ssl_opts => { verify_hostname => 0 }, \& ); \& \& my $response = $ua\->get(\*(Aqhttps://www.example.com/\*(Aq); \& print $response\->content, "\en"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This Perl module provides support for the \s-1HTTPS\s0 protocol under \s-1LWP\s0, to allow an LWP::UserAgent object to perform \s-1GET, HEAD,\s0 and \s-1POST\s0 requests over encrypted socket connections. Please see \s-1LWP\s0 for more information on \s-1POST\s0 requests. .PP The \f(CW\*(C`Crypt::SSLeay\*(C'\fR package provides \f(CW\*(C`Net::SSL\*(C'\fR, which, if requested, is loaded by \f(CW\*(C`LWP::Protocol::https\*(C'\fR for https requests and provides the necessary \s-1SSL\s0 glue. .PP This distribution also makes following deprecated modules available: .PP .Vb 3 \& Crypt::SSLeay::CTX \& Crypt::SSLeay::Conn \& Crypt::SSLeay::X509 .Ve .SH "DO YOU NEED Crypt::SSLeay?" .IX Header "DO YOU NEED Crypt::SSLeay?" Starting with version 6.02 of \s-1LWP\s0, \f(CW\*(C`https\*(C'\fR support was unbundled into LWP::Protocol::https. This module specifies as one of its prerequisites IO::Socket::SSL which is automatically used by LWP::UserAgent unless this preference is overridden separately. \f(CW\*(C`IO::Socket::SSL\*(C'\fR is a more complete implementation, and, crucially, it allows hostname verification. \&\f(CW\*(C`Crypt::SSLeay\*(C'\fR does not support this. At this point, \f(CW\*(C`Crypt::SSLeay\*(C'\fR is maintained to support existing software that already depends on it. However, it is possible that your software does not really depend on \&\f(CW\*(C`Crypt::SSLeay\*(C'\fR, only on the ability of \f(CW\*(C`LWP::UserAgent\*(C'\fR class to communicate with sites over \s-1SSL/TLS.\s0 .PP If are using version \f(CW\*(C`LWP\*(C'\fR 6.02 or later, and therefore have installed \&\f(CW\*(C`LWP::Protocol::https\*(C'\fR and its dependencies, and do not explicitly \f(CW\*(C`use\*(C'\fR \&\f(CW\*(C`Net::SSL\*(C'\fR before loading \f(CW\*(C`LWP::UserAgent\*(C'\fR, or override the default socket class, you are probably using \f(CW\*(C`IO::Socket::SSL\*(C'\fR and do not really need \&\f(CW\*(C`Crypt::SSLeay\*(C'\fR. .PP If you have both \f(CW\*(C`Crypt::SSLeay\*(C'\fR and \f(CW\*(C`IO::Socket::SSL\*(C'\fR installed, and would like to force \f(CW\*(C`LWP::UserAgent\*(C'\fR to use \f(CW\*(C`Crypt::SSLeay\*(C'\fR, you can use: .PP .Vb 3 \& use Net::HTTPS; \& $Net::HTTPS::SSL_SOCKET_CLASS = \*(AqNet::SSL\*(Aq; \& use LWP::UserAgent; .Ve .PP or .PP .Vb 2 \& local $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = \*(AqNet::SSL\*(Aq; \& use LWP::UserAgent; .Ve .PP or .PP .Vb 2 \& use Net::SSL; \& use LWP::UserAgent; .Ve .SH "ENVIRONMENT VARIABLES" .IX Header "ENVIRONMENT VARIABLES" .IP "Specify \s-1SSL\s0 Socket Class" 4 .IX Item "Specify SSL Socket Class" \&\f(CW$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}\fR can be used to instruct \&\f(CW\*(C`LWP::UserAgent\*(C'\fR to use \f(CW\*(C`Net::SSL\*(C'\fR for \s-1HTTPS\s0 support rather than \&\f(CW\*(C`IO::Socket::SSL\*(C'\fR. .IP "Proxy Support" 4 .IX Item "Proxy Support" .Vb 1 \& $ENV{HTTPS_PROXY} = \*(Aqhttp://proxy_hostname_or_ip:port\*(Aq; .Ve .IP "Proxy Basic Authentication" 4 .IX Item "Proxy Basic Authentication" .Vb 2 \& $ENV{HTTPS_PROXY_USERNAME} = \*(Aqusername\*(Aq; \& $ENV{HTTPS_PROXY_PASSWORD} = \*(Aqpassword\*(Aq; .Ve .IP "\s-1SSL\s0 diagnostics and Debugging" 4 .IX Item "SSL diagnostics and Debugging" .Vb 1 \& $ENV{HTTPS_DEBUG} = 1; .Ve .IP "Default \s-1SSL\s0 Version" 4 .IX Item "Default SSL Version" .Vb 1 \& $ENV{HTTPS_VERSION} = \*(Aq3\*(Aq; .Ve .IP "Client Certificate Support" 4 .IX Item "Client Certificate Support" .Vb 2 \& $ENV{HTTPS_CERT_FILE} = \*(Aqcerts/notacacert.pem\*(Aq; \& $ENV{HTTPS_KEY_FILE} = \*(Aqcerts/notacakeynopass.pem\*(Aq; .Ve .IP "\s-1CA\s0 cert Peer Verification" 4 .IX Item "CA cert Peer Verification" .Vb 2 \& $ENV{HTTPS_CA_FILE} = \*(Aqcerts/ca\-bundle.crt\*(Aq; \& $ENV{HTTPS_CA_DIR} = \*(Aqcerts/\*(Aq; .Ve .IP "Client \s-1PKCS12\s0 cert support" 4 .IX Item "Client PKCS12 cert support" .Vb 2 \& $ENV{HTTPS_PKCS12_FILE} = \*(Aqcerts/pkcs12.pkcs12\*(Aq; \& $ENV{HTTPS_PKCS12_PASSWORD} = \*(AqPKCS12_PASSWORD\*(Aq; .Ve .SH "INSTALL" .IX Header "INSTALL" .SS "OpenSSL" .IX Subsection "OpenSSL" You must have OpenSSL installed before compiling this module. You can get the latest OpenSSL package from . We no longer support pre\-2000 versions of OpenSSL. .PP If you are building OpenSSL from source, please follow the directions included in the source package. .SS "Crypt::SSLeay via Makefile.PL" .IX Subsection "Crypt::SSLeay via Makefile.PL" \&\f(CW\*(C`Makefile.PL\*(C'\fR accepts the following command line arguments: .ie n .IP """incpath""" 4 .el .IP "\f(CWincpath\fR" 4 .IX Item "incpath" Path to OpenSSL headers. Can also be specified via \f(CW$ENV{OPENSSL_INCLUDE}\fR. If the command line argument is provided, it overrides any value specified via the environment variable. Of course, you can ignore both the command line argument and the environment variable, and just add the path to your compiler specific environment variable such as \f(CW\*(C`CPATH\*(C'\fR or \f(CW\*(C`INCLUDE\*(C'\fR etc. .ie n .IP """libpath""" 4 .el .IP "\f(CWlibpath\fR" 4 .IX Item "libpath" Path to OpenSSL libraries. Can also be specified via \f(CW$ENV{OPENSSL_LIB}\fR. If the command line argument is provided, it overrides any value specified by the environment variable. Of course, you can ignore both the command line argument and the environment variable and just add the path to your compiler specific environment variable such as \f(CW\*(C`LIBRARY_PATH\*(C'\fR or \f(CW\*(C`LIB\*(C'\fR etc. .ie n .IP """live\-tests""" 4 .el .IP "\f(CWlive\-tests\fR" 4 .IX Item "live-tests" Use \f(CW\*(C`\-\-live\-tests\*(C'\fR to request tests that try to connect to an external web site, and \f(CW\*(C`\-\-no\-live_tests\*(C'\fR to prevent such tests from running. If you run \&\f(CW\*(C`Makefile.PL\*(C'\fR interactively, and this argument is not specified on the command line, you will be prompted for a value. .Sp Default is false. .ie n .IP """static""" 4 .el .IP "\f(CWstatic\fR" 4 .IX Item "static" Boolean. Default is false. \fB\s-1TODO\s0\fR: Does it work? .ie n .IP """verbose""" 4 .el .IP "\f(CWverbose\fR" 4 .IX Item "verbose" Boolean. Default is false. If you pass \f(CW\*(C`\-\-verbose\*(C'\fR on the command line, both \f(CW\*(C`Devel::CheckLib\*(C'\fR and \f(CW\*(C`ExtUtils::CBuilder\*(C'\fR instances will be configured to echo what they are doing. .PP If everything builds \s-1OK,\s0 but you get failures when during tests, ensure that \&\f(CW\*(C`LD_LIBRARY_PATH\*(C'\fR points to the location where the correct shared libraries are located. .PP If you are using a custom OpenSSL build, please keep in mind that \&\f(CW\*(C`Crypt::SSLeay\*(C'\fR must be built using the same compiler and build tools used to build \f(CW\*(C`perl\*(C'\fR and OpenSSL. This can be more of an issue on Windows. If you are using Active State Perl, install the MinGW package distributed by them, and build OpenSSL using that before trying to build this module. If you have built your own Perl using Microsoft \s-1SDK\s0 tools or IDEs, make sure you build OpenSSL using the same tools. .PP Depending on your \s-1OS,\s0 pre-built OpenSSL packages may be available. To get the require headers and import libraries, you may need to install a development version of your operating system's OpenSSL library package. The key is that \f(CW\*(C`Crypt::SSLeay\*(C'\fR makes calls to the OpenSSL library, and how to do so is specified in the C header files that come with the library. Some systems break out the header files into a separate package from that of the libraries. Once the program has been built, you don't need the headers any more. .SS "Crypt::SSLeay" .IX Subsection "Crypt::SSLeay" The latest Crypt::SSLeay can be found at your nearest \s-1CPAN\s0 mirror, as well as . .PP Once you have downloaded it, \f(CW\*(C`Crypt::SSLeay\*(C'\fR installs easily using the standard build process: .PP .Vb 4 \& $ perl Makefile.PL \& $ make \& $ make test \& $ make install .Ve .PP or .PP .Vb 1 \& $ cpanm Crypt::SSLeay .Ve .PP If you have OpenSSL headers and libraries in nonstandard locations, you can use .PP .Vb 1 \& $ perl Makefile.PL \-\-incpath=... \-\-libpath=... .Ve .PP If you would like to use \f(CW\*(C`cpanm\*(C'\fR with such custom locations, you can do .PP .Vb 1 \& $ OPENSSL_INCLUDE=... OPENSSL_LIB=... cpanm Crypt::SSLeay .Ve .PP or, on Windows, .PP .Vb 3 \& > set OPENSSL_INCLUDE=... \& > set OPENSSL_LIB=... \& > cpanm Crypt::SSLeay .Ve .PP If you are on Windows, and using a MinGW distribution bundled with ActiveState Perl or Strawberry Perl, you would use \f(CW\*(C`dmake\*(C'\fR rather than \&\f(CW\*(C`make\*(C'\fR. If you are using Microsoft's build tools, you would use \f(CW\*(C`nmake\*(C'\fR. .PP For unattended (batch) installations, to be absolutely certain that \&\fIMakefile.PL\fR does not prompt for questions on \s-1STDIN,\s0 set the environment variable \f(CW\*(C`PERL_MM_USE_DEFAULT=1\*(C'\fR as with any \s-1CPAN\s0 module built using ExtUtils::MakeMaker. .PP \fI\s-1VMS\s0\fR .IX Subsection "VMS" .PP I do not have any experience with \s-1VMS.\s0 If OpenSSL headers and libraries are not in standard locations searched by your build system by default, please set things up so that they are. If you have generic instructions on how to do it, please open a ticket on \s-1RT\s0 with the information so I can add it to this document. .SH "PROXY SUPPORT" .IX Header "PROXY SUPPORT" LWP::UserAgent and Crypt::SSLeay have their own versions of proxy support. Please read these sections to see which one is appropriate. .SS "LWP::UserAgent proxy support" .IX Subsection "LWP::UserAgent proxy support" \&\f(CW\*(C`LWP::UserAgent\*(C'\fR has its own methods of proxying which may work for you and is likely to be incompatible with \f(CW\*(C`Crypt::SSLeay\*(C'\fR proxy support. To use \f(CW\*(C`LWP::UserAgent\*(C'\fR proxy support, try something like: .PP .Vb 2 \& my $ua = LWP::UserAgent\->new; \& $ua\->proxy([qw( https http )], "$proxy_ip:$proxy_port"); .Ve .PP At the time of this writing, libwww v5.6 seems to proxy https requests fine with an Apache \fImod_proxy\fR server. It sends a line like: .PP .Vb 1 \& GET https://www.example.com HTTP/1.1 .Ve .PP to the proxy server, which is not the \f(CW\*(C`CONNECT\*(C'\fR request that some proxies would expect, so this may not work with other proxy servers than \&\fImod_proxy\fR. The \f(CW\*(C`CONNECT\*(C'\fR method is used by \f(CW\*(C`Crypt::SSLeay\*(C'\fR's internal proxy support. .SS "Crypt::SSLeay proxy support" .IX Subsection "Crypt::SSLeay proxy support" For native \f(CW\*(C`Crypt::SSLeay\*(C'\fR proxy support of https requests, you need to set the environment variable \f(CW\*(C`HTTPS_PROXY\*(C'\fR to your proxy server and port, as in: .PP .Vb 3 \& # proxy support \& $ENV{HTTPS_PROXY} = \*(Aqhttp://proxy_hostname_or_ip:port\*(Aq; \& $ENV{HTTPS_PROXY} = \*(Aq127.0.0.1:8080\*(Aq; .Ve .PP Use of the \f(CW\*(C`HTTPS_PROXY\*(C'\fR environment variable in this way is similar to \f(CW\*(C`LWP::UserAgent\-\*(C'\fR\fBenv_proxy()\fR> usage, but calling that method will likely override or break the \f(CW\*(C`Crypt::SSLeay\*(C'\fR support, so do not mix the two. .PP Basic auth credentials to the proxy server can be provided this way: .PP .Vb 3 \& # proxy_basic_auth \& $ENV{HTTPS_PROXY_USERNAME} = \*(Aqusername\*(Aq; \& $ENV{HTTPS_PROXY_PASSWORD} = \*(Aqpassword\*(Aq; .Ve .PP For an example of \s-1LWP\s0 scripting with \f(CW\*(C`Crypt::SSLeay\*(C'\fR native proxy support, please look at the \fIeg/lwp\-ssl\-test\fR script in the \&\f(CW\*(C`Crypt::SSLeay\*(C'\fR distribution. .SH "CLIENT CERTIFICATE SUPPORT" .IX Header "CLIENT CERTIFICATE SUPPORT" Client certificates are supported. \s-1PEM\s0 encoded certificate and private key files may be used like this: .PP .Vb 2 \& $ENV{HTTPS_CERT_FILE} = \*(Aqcerts/notacacert.pem\*(Aq; \& $ENV{HTTPS_KEY_FILE} = \*(Aqcerts/notacakeynopass.pem\*(Aq; .Ve .PP You may test your files with the \fIeg/net\-ssl\-test\fR program, bundled with the distribution, by issuing a command like: .PP .Vb 2 \& perl eg/net\-ssl\-test \-cert=certs/notacacert.pem \e \& \-key=certs/notacakeynopass.pem \-d GET $HOST_NAME .Ve .PP Additionally, if you would like to tell the client where the \s-1CA\s0 file is, you may set these. .PP .Vb 2 \& $ENV{HTTPS_CA_FILE} = "some_file"; \& $ENV{HTTPS_CA_DIR} = "some_dir"; .Ve .PP Note that, if specified, \f(CW$ENV{HTTPS_CA_FILE}\fR must point to the actual certificate file. That is, \f(CW$ENV{HTTPS_CA_DIR}\fR is *not* the path were \&\f(CW$ENV{HTTPS_CA_FILE}\fR is located. .PP For certificates in \f(CW$ENV{HTTPS_CA_DIR}\fR to be picked up, follow the instructions on .PP There is no sample \s-1CA\s0 cert file at this time for testing, but you may configure \fIeg/net\-ssl\-test\fR to use your \s-1CA\s0 cert with the \-CAfile option. .PP (\s-1TODO:\s0 then what is the \fI./certs\fR directory in the distribution?) .SS "Creating a test certificate" .IX Subsection "Creating a test certificate" To create simple test certificates with OpenSSL, you may run the following command: .PP .Vb 3 \& openssl req \-config /usr/local/openssl/openssl.cnf \e \& \-new \-days 365 \-newkey rsa:1024 \-x509 \e \& \-keyout notacakey.pem \-out notacacert.pem .Ve .PP To remove the pass phrase from the key file, run: .PP .Vb 1 \& openssl rsa \-in notacakey.pem \-out notacakeynopass.pem .Ve .SS "\s-1PKCS12\s0 support" .IX Subsection "PKCS12 support" The directives for enabling use of \s-1PKCS12\s0 certificates is: .PP .Vb 2 \& $ENV{HTTPS_PKCS12_FILE} = \*(Aqcerts/pkcs12.pkcs12\*(Aq; \& $ENV{HTTPS_PKCS12_PASSWORD} = \*(AqPKCS12_PASSWORD\*(Aq; .Ve .PP Use of this type of certificate takes precedence over previous certificate settings described. .PP (\s-1TODO:\s0 unclear? Meaning \*(L"the presence of this type of certificate\*(R"?) .SH "SSL versions" .IX Header "SSL versions" \&\f(CW\*(C`Crypt::SSLeay\*(C'\fR tries very hard to connect to \fIany\fR \s-1SSL\s0 web server accommodating servers that are buggy, old or simply not standards-compliant. To this effect, this module will try \s-1SSL\s0 connections in this order: .IP "\s-1SSL\s0 v23" 4 .IX Item "SSL v23" should allow v2 and v3 servers to pick their best type .IP "\s-1SSL\s0 v3" 4 .IX Item "SSL v3" best connection type .IP "\s-1SSL\s0 v2" 4 .IX Item "SSL v2" old connection type .PP Unfortunately, some servers seem not to handle a reconnect to \s-1SSL\s0 v3 after a failed connect of \s-1SSL\s0 v23 is tried, so you may set before using \s-1LWP\s0 or Net::SSL: .PP .Vb 1 \& $ENV{HTTPS_VERSION} = 3; .Ve .PP to force a version 3 \s-1SSL\s0 connection first. At this time only a version 2 \s-1SSL\s0 connection will be tried after this, as the connection attempt order remains unchanged by this setting. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" Many thanks to the following individuals who helped improve \&\f(CW\*(C`Crypt\-SSLeay\*(C'\fR: .PP \&\fIGisle Aas\fR for writing this module and many others including libwww, for perl. The web will never be the same :) .PP \&\fIBen Laurie\fR deserves kudos for his excellent patches for better error handling, \s-1SSL\s0 information inspection, and random seeding. .PP \&\fIDongqiang Bai\fR for host name resolution fix when using a proxy. .PP \&\fIStuart Horner\fR of Core Communications, Inc. who found the need for building \f(CW\*(C`\-\-shared\*(C'\fR OpenSSL libraries. .PP \&\fIPavel Hlavnicka\fR for a patch for freeing memory when using a pkcs12 file, and for inspiring more robust \f(CW\*(C`read()\*(C'\fR behavior. .PP \&\fIJames Woodyatt\fR is a champ for finding a ridiculous memory leak that has been the bane of many a Crypt::SSLeay user. .PP \&\fIBryan Hart\fR for his patch adding proxy support, and thanks to \fITobias Manthey\fR for submitting another approach. .PP \&\fIAlex Rhomberg\fR for Alpha linux ccc patch. .PP \&\fITobias Manthey\fR for his patches for client certificate support. .PP \&\fIDaisuke Kuroda\fR for adding \s-1PKCS12\s0 certificate support. .PP \&\fIGamid Isayev\fR for \s-1CA\s0 cert support and insights into error messaging. .PP \&\fIJeff Long\fR for working through a tricky \s-1CA\s0 cert SSLClientVerify issue. .PP \&\fIChip Turner\fR for a patch to build under perl 5.8.0. .PP \&\fIJoshua Chamas\fR for the time he spent maintaining the module. .PP \&\fIJeff Lavallee\fR for help with alarms on read failures (\s-1CPAN\s0 bug #12444). .PP \&\fIGuenter Knauf\fR for significant improvements in configuring things in Win32 and Netware lands and Jan Dubois for various suggestions for improvements. .PP and \fImany others\fR who provided bug reports, suggestions, fixes and patches. .PP If you have reported a bug or provided feedback, and you would like to be mentioned by name in this section, please file request on rt.cpan.org . .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "Net::SSL" 4 .IX Item "Net::SSL" If you have downloaded this distribution as of a dependency of another distribution, it's probably due to this module (which is included in this distribution). .IP "Net::SSLeay" 4 .IX Item "Net::SSLeay" Net::SSLeay provides access to the OpenSSL \s-1API\s0 directly from Perl. See . .IP "Building OpenSSL on 64\-bit Windows 8.1 Pro using \s-1SDK\s0 tools" 4 .IX Item "Building OpenSSL on 64-bit Windows 8.1 Pro using SDK tools" My blog post might be helpful. .SH "SUPPORT" .IX Header "SUPPORT" For issues related to using of \f(CW\*(C`Crypt::SSLeay\*(C'\fR & \f(CW\*(C`Net::SSL\*(C'\fR with Perl's \&\s-1LWP\s0, please send email to \f(CW\*(C`libwww@perl.org\*(C'\fR. .PP For OpenSSL or general \s-1SSL\s0 support, including issues associated with building and installing OpenSSL on your system, please email the OpenSSL users mailing list at \f(CW\*(C`openssl\-users@openssl.org\*(C'\fR. See for other mailing lists and archives. .PP Please report all bugs using rt.cpan.org . .SH "AUTHORS" .IX Header "AUTHORS" This module was originally written by Gisle Aas, and was subsequently maintained by Joshua Chamas, David Landgren, brian d foy and Sinan Unur. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2010\-2014 A. Sinan Unur .PP Copyright (c) 2006\-2007 David Landgren .PP Copyright (c) 1999\-2003 Joshua Chamas .PP Copyright (c) 1998 Gisle Aas .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the terms of Artistic License 2.0 (see ). man/man3/DBD::File::HowTo.3pm000044400000017650152462503210011327 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::File::HowTo 3" .TH DBD::File::HowTo 3 "2020-01-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::File::HowTo \- Guide to create DBD::File based driver .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 12 \& perldoc DBD::File::HowTo \& perldoc DBI \& perldoc DBI::DBD \& perldoc DBD::File::Developers \& perldoc DBI::DBD::SqlEngine::Developers \& perldoc DBI::DBD::SqlEngine \& perldoc SQL::Eval \& perldoc DBI::DBD::SqlEngine::HowTo \& perldoc SQL::Statement::Embed \& perldoc DBD::File \& perldoc DBD::File::HowTo \& perldoc DBD::File::Developers .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document provides a step-by-step guide, how to create a new \&\f(CW\*(C`DBD::File\*(C'\fR based \s-1DBD.\s0 It expects that you carefully read the \s-1DBI\s0 documentation and that you're familiar with \s-1DBI::DBD\s0 and had read and understood DBD::ExampleP. .PP This document addresses experienced developers who are really sure that they need to invest time when writing a new \s-1DBI\s0 Driver. Writing a \s-1DBI\s0 Driver is neither a weekend project nor an easy job for hobby coders after work. Expect one or two man-month of time for the first start. .PP Those who are still reading, should be able to sing the rules of \&\*(L"\s-1CREATING A NEW DRIVER\*(R"\s0 in \s-1DBI::DBD\s0. .PP Of course, DBD::File is a DBI::DBD::SqlEngine and you surely read DBI::DBD::SqlEngine::HowTo before continuing here. .SH "CREATING DRIVER CLASSES" .IX Header "CREATING DRIVER CLASSES" Do you have an entry in \s-1DBI\s0's \s-1DBD\s0 registry? For this guide, a prefix of \&\f(CW\*(C`foo_\*(C'\fR is assumed. .SS "Sample Skeleton" .IX Subsection "Sample Skeleton" .Vb 1 \& package DBD::Foo; \& \& use strict; \& use warnings; \& use vars qw(@ISA $VERSION); \& use base qw(DBD::File); \& \& use DBI (); \& \& $VERSION = "0.001"; \& \& package DBD::Foo::dr; \& \& use vars qw(@ISA $imp_data_size); \& \& @ISA = qw(DBD::File::dr); \& $imp_data_size = 0; \& \& package DBD::Foo::db; \& \& use vars qw(@ISA $imp_data_size); \& \& @ISA = qw(DBD::File::db); \& $imp_data_size = 0; \& \& package DBD::Foo::st; \& \& use vars qw(@ISA $imp_data_size); \& \& @ISA = qw(DBD::File::st); \& $imp_data_size = 0; \& \& package DBD::Foo::Statement; \& \& use vars qw(@ISA); \& \& @ISA = qw(DBD::File::Statement); \& \& package DBD::Foo::Table; \& \& use vars qw(@ISA); \& \& @ISA = qw(DBD::File::Table); \& \& 1; .Ve .PP Tiny, eh? And all you have now is a \s-1DBD\s0 named foo which will be able to deal with temporary tables, as long as you use SQL::Statement. In DBI::SQL::Nano environments, this \s-1DBD\s0 can do nothing. .SS "Start over" .IX Subsection "Start over" Based on DBI::DBD::SqlEngine::HowTo, we're now having a driver which could do basic things. Of course, it should now derive from DBD::File instead of DBI::DBD::SqlEngine, shouldn't it? .PP DBD::File extends DBI::DBD::SqlEngine to deal with any kind of files. In principle, the only extensions required are to the table class: .PP .Vb 1 \& package DBD::Foo::Table; \& \& sub bootstrap_table_meta \& { \& my ( $self, $dbh, $meta, $table ) = @_; \& \& # initialize all $meta attributes which might be relevant for \& # file2table \& \& return $self\->SUPER::bootstrap_table_meta($dbh, $meta, $table); \& } \& \& sub init_table_meta \& { \& my ( $self, $dbh, $meta, $table ) = @_; \& \& # called after $meta contains the results from file2table \& # initialize all missing $meta attributes \& \& $self\->SUPER::init_table_meta( $dbh, $meta, $table ); \& } .Ve .PP In case \f(CW\*(C`DBD::File::Table::open_file\*(C'\fR doesn't open the files as the driver needs that, override it! .PP .Vb 7 \& sub open_file \& { \& my ( $self, $meta, $attrs, $flags ) = @_; \& # ensure that $meta\->{f_dontopen} is set \& $self\->SUPER::open_file( $meta, $attrs, $flags ); \& # now do what ever needs to be done \& } .Ve .PP Combined with the methods implemented using the SQL::Statement::Embed guide, the table is full working and you could try a start over. .SS "User comfort" .IX Subsection "User comfort" \&\f(CW\*(C`DBD::File\*(C'\fR since \f(CW0.39\fR consolidates all persistent meta data of a table into a single structure stored in \f(CW\*(C`$dbh\->{f_meta}\*(C'\fR. With \f(CW\*(C`DBD::File\*(C'\fR version \f(CW0.41\fR and \f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR version \f(CW0.05\fR, this consolidation moves to DBI::DBD::SqlEngine. It's still the \&\f(CW\*(C`$dbh\->{$drv_prefix . "_meta"}\*(C'\fR attribute which cares, so what you learned at this place before, is still valid. .PP .Vb 3 \& sub init_valid_attributes \& { \& my $dbh = $_[0]; \& \& $dbh\->SUPER::init_valid_attributes (); \& \& $dbh\->{foo_valid_attrs} = { ... }; \& $dbh\->{foo_readonly_attrs} = { ... }; \& \& $dbh\->{foo_meta} = "foo_tables"; \& \& return $dbh; \& } .Ve .PP See updates at \*(L"User comfort\*(R" in DBI::DBD::SqlEngine::HowTo. .SS "Testing" .IX Subsection "Testing" Now you should have your own DBD::File based driver. Was easy, wasn't it? But does it work well? Prove it by writing tests and remember to use dbd_edit_mm_attribs from \s-1DBI::DBD\s0 to ensure testing even rare cases. .SH "AUTHOR" .IX Header "AUTHOR" This guide is written by Jens Rehsack. DBD::File is written by Jochen Wiedmann and Jeff Zucker. .PP The module DBD::File is currently maintained by .PP H.Merijn Brand < h.m.brand at xs4all.nl > and Jens Rehsack < rehsack at googlemail.com > .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack .PP All rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. man/man3/IO::Pty.3pm000044400000020577152462503210007777 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Pty 3" .TH Pty 3 "2021-01-22" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" IO::Pty \- Pseudo TTY object class .SH "VERSION" .IX Header "VERSION" 1.16 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use IO::Pty; \& \& $pty = new IO::Pty; \& \& $slave = $pty\->slave; \& \& foreach $val (1..10) { \& print $pty "$val\en"; \& $_ = <$slave>; \& print "$_"; \& } \& \& close($slave); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\f(CW\*(C`IO::Pty\*(C'\fR provides an interface to allow the creation of a pseudo tty. .PP \&\f(CW\*(C`IO::Pty\*(C'\fR inherits from \f(CW\*(C`IO::Handle\*(C'\fR and so provide all the methods defined by the \f(CW\*(C`IO::Handle\*(C'\fR package. .PP Please note that pty creation is very system-dependent. If you have problems, see IO::Tty for help. .SH "CONSTRUCTOR" .IX Header "CONSTRUCTOR" .IP "new" 3 .IX Item "new" The \f(CW\*(C`new\*(C'\fR constructor takes no arguments and returns a new file object which is the master side of the pseudo tty. .SH "METHODS" .IX Header "METHODS" .IP "\fBttyname()\fR" 4 .IX Item "ttyname()" Returns the name of the slave pseudo tty. On \s-1UNIX\s0 machines this will be the pathname of the device. Use this name for informational purpose only, to get a slave filehandle, use \fBslave()\fR. .IP "\fBslave()\fR" 4 .IX Item "slave()" The \f(CW\*(C`slave\*(C'\fR method will return the slave filehandle of the given master pty, opening it anew if necessary. If IO::Stty is installed, you can then call \f(CW\*(C`$slave\->stty()\*(C'\fR to modify the terminal settings. .IP "\fBclose_slave()\fR" 4 .IX Item "close_slave()" The slave filehandle will be closed and destroyed. This is necessary in the parent after forking to get rid of the open filehandle, otherwise the parent will not notice if the child exits. Subsequent calls of \f(CW\*(C`slave()\*(C'\fR will return a newly opened slave filehandle. .IP "\fBmake_slave_controlling_terminal()\fR" 4 .IX Item "make_slave_controlling_terminal()" This will set the slave filehandle as the controlling terminal of the current process, which will become a session leader, so this should only be called by a child process after a \fBfork()\fR, e.g. in the callback to \f(CW\*(C`sync_exec()\*(C'\fR (see Proc::SyncExec). See the \f(CW\*(C`try\*(C'\fR script (also \f(CW\*(C`test.pl\*(C'\fR) for an example how to correctly spawn a subprocess. .IP "\fBset_raw()\fR" 4 .IX Item "set_raw()" Will set the pty to raw. Note that this is a one-way operation, you need IO::Stty to set the terminal settings to anything else. .Sp On some systems, the master pty is not a tty. This method checks for that and returns success anyway on such systems. Note that this method must be called on the slave, and probably should be called on the master, just to be sure, i.e. .Sp .Vb 2 \& $pty\->slave\->set_raw(); \& $pty\->set_raw(); .Ve .IP "clone_winsize_from(\e*FH)" 4 .IX Item "clone_winsize_from(*FH)" Gets the terminal size from filehandle \s-1FH\s0 (which must be a terminal) and transfers it to the pty. Returns true on success and undef on failure. Note that this must be called upon the \fIslave\fR, i.e. .Sp .Vb 1 \& $pty\->slave\->clone_winsize_from(\e*STDIN); .Ve .Sp On some systems, the master pty also isatty. I actually have no idea if setting terminal sizes there is passed through to the slave, so if this method is called for a master that is not a tty, it silently returns \s-1OK.\s0 .Sp See the \f(CW\*(C`try\*(C'\fR script for example code how to propagate \s-1SIGWINCH.\s0 .IP "\fBget_winsize()\fR" 4 .IX Item "get_winsize()" Returns the terminal size, in a 4\-element list. .Sp .Vb 1 \& ($row, $col, $xpixel, $ypixel) = $tty\->get_winsize() .Ve .ie n .IP "set_winsize($row, $col, $xpixel, $ypixel)" 4 .el .IP "set_winsize($row, \f(CW$col\fR, \f(CW$xpixel\fR, \f(CW$ypixel\fR)" 4 .IX Item "set_winsize($row, $col, $xpixel, $ypixel)" Sets the terminal size. If not specified, \f(CW$xpixel\fR and \f(CW$ypixel\fR are set to 0. As with \f(CW\*(C`clone_winsize_from\*(C'\fR, this must be called upon the \fIslave\fR. .SH "SEE ALSO" .IX Header "SEE ALSO" IO::Tty, IO::Tty::Constant, IO::Handle, Expect, Proc::SyncExec .SH "MAILING LISTS" .IX Header "MAILING LISTS" As this module is mainly used by Expect, support for it is available via the two Expect mailing lists, expectperl-announce and expectperl-discuss, at .PP .Vb 1 \& http://lists.sourceforge.net/lists/listinfo/expectperl\-announce .Ve .PP and .PP .Vb 1 \& http://lists.sourceforge.net/lists/listinfo/expectperl\-discuss .Ve .SH "AUTHORS" .IX Header "AUTHORS" Originally by Graham Barr <\fIgbarr@pobox.com\fR>, based on the Ptty module by Nick Ing-Simmons <\fInik@tiuk.ti.com\fR>. .PP Now maintained and heavily rewritten by Roland Giersig <\fIRGiersig@cpan.org\fR>. .PP Contains copyrighted stuff from openssh v3.0p1, authored by Tatu Ylonen , Markus Friedl and Todd C. Miller . .SH "COPYRIGHT" .IX Header "COPYRIGHT" Now all code is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP Nevertheless the above \s-1AUTHORS\s0 retain their copyrights to the various parts and want to receive credit if their source code is used. See the source for details. .SH "DISCLAIMER" .IX Header "DISCLAIMER" \&\s-1THIS SOFTWARE IS PROVIDED\s0 ``\s-1AS IS\s0'' \s-1AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\s0 (\s-1INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES\s0; \s-1LOSS OF USE, DATA, OR PROFITS\s0; \s-1OR BUSINESS INTERRUPTION\s0) \s-1HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\s0 (\s-1INCLUDING NEGLIGENCE OR OTHERWISE\s0) \s-1ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\s0 .PP In other words: Use at your own risk. Provided as is. Your mileage may vary. Read the source, Luke! .PP And finally, just to be sure: .PP Any Use of This Product, in Any Manner Whatsoever, Will Increase the Amount of Disorder in the Universe. Although No Liability Is Implied Herein, the Consumer Is Warned That This Process Will Ultimately Lead to the Heat Death of the Universe. man/man3/DBD::Gofer::Policy::pedantic.3pm000044400000006447152462503210013607 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Policy::pedantic 3" .TH DBD::Gofer::Policy::pedantic 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Policy::pedantic \- The 'pedantic' policy for DBD::Gofer .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=pedantic", ...) .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`pedantic\*(C'\fR policy tries to be as transparent as possible. To do this it makes round-trips to the server for almost every \s-1DBI\s0 method call. .PP This is the best policy to use when first testing existing code with Gofer. Once it's working well you should consider moving to the \f(CW\*(C`classic\*(C'\fR policy or defining your own policy class. .PP Temporary docs: See the source code for list of policies and their defaults. .PP In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/LWP::Simple.3pm000044400000016637152462503210010611 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::Simple 3" .TH LWP::Simple 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::Simple \- simple procedural interface to LWP .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& perl \-MLWP::Simple \-e \*(Aqgetprint "http://www.sn.no"\*(Aq \& \& use LWP::Simple; \& $content = get("http://www.sn.no/"); \& die "Couldn\*(Aqt get it!" unless defined $content; \& \& if (mirror("http://www.sn.no/", "foo") == RC_NOT_MODIFIED) { \& ... \& } \& \& if (is_success(getprint("http://www.sn.no/"))) { \& ... \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module is meant for people who want a simplified view of the libwww-perl library. It should also be suitable for one-liners. If you need more control or access to the header fields in the requests sent and responses received, then you should use the full object-oriented interface provided by the LWP::UserAgent module. .PP The module will also export the LWP::UserAgent object as \f(CW$ua\fR if you ask for it explicitly. .PP The user agent created by this module will identify itself as \&\f(CW\*(C`LWP::Simple/#.##\*(C'\fR and will initialize its proxy defaults from the environment (by calling \f(CW\*(C`$ua\->env_proxy\*(C'\fR). .SH "FUNCTIONS" .IX Header "FUNCTIONS" The following functions are provided (and exported) by this module: .SS "get" .IX Subsection "get" .Vb 1 \& my $res = get($url); .Ve .PP The \fBget()\fR function will fetch the document identified by the given \s-1URL\s0 and return it. It returns \f(CW\*(C`undef\*(C'\fR if it fails. The \f(CW$url\fR argument can be either a string or a reference to a \s-1URI\s0 object. .PP You will not be able to examine the response code or response headers (like \f(CW\*(C`Content\-Type\*(C'\fR) when you are accessing the web using this function. If you need that information you should use the full \s-1OO\s0 interface (see LWP::UserAgent). .SS "head" .IX Subsection "head" .Vb 1 \& my $res = head($url); .Ve .PP Get document headers. Returns the following 5 values if successful: ($content_type, \f(CW$document_length\fR, \f(CW$modified_time\fR, \f(CW$expires\fR, \f(CW$server\fR) .PP Returns an empty list if it fails. In scalar context returns \s-1TRUE\s0 if successful. .SS "getprint" .IX Subsection "getprint" .Vb 1 \& my $code = getprint($url); .Ve .PP Get and print a document identified by a \s-1URL.\s0 The document is printed to the selected default filehandle for output (normally \s-1STDOUT\s0) as data is received from the network. If the request fails, then the status code and message are printed on \s-1STDERR.\s0 The return value is the \s-1HTTP\s0 response code. .SS "getstore" .IX Subsection "getstore" .Vb 1 \& my $code = getstore($url, $file) .Ve .PP Gets a document identified by a \s-1URL\s0 and stores it in the file. The return value is the \s-1HTTP\s0 response code. .SS "mirror" .IX Subsection "mirror" .Vb 1 \& my $code = mirror($url, $file); .Ve .PP Get and store a document identified by a \s-1URL,\s0 using \&\fIIf-modified-since\fR, and checking the \fIContent-Length\fR. Returns the \s-1HTTP\s0 response code. .SH "STATUS CONSTANTS" .IX Header "STATUS CONSTANTS" This module also exports the HTTP::Status constants and procedures. You can use them when you check the response code from \*(L"getprint\*(R" in LWP::Simple, \&\*(L"getstore\*(R" in LWP::Simple or \*(L"mirror\*(R" in LWP::Simple. The constants are: .PP .Vb 10 \& RC_CONTINUE \& RC_SWITCHING_PROTOCOLS \& RC_OK \& RC_CREATED \& RC_ACCEPTED \& RC_NON_AUTHORITATIVE_INFORMATION \& RC_NO_CONTENT \& RC_RESET_CONTENT \& RC_PARTIAL_CONTENT \& RC_MULTIPLE_CHOICES \& RC_MOVED_PERMANENTLY \& RC_MOVED_TEMPORARILY \& RC_SEE_OTHER \& RC_NOT_MODIFIED \& RC_USE_PROXY \& RC_BAD_REQUEST \& RC_UNAUTHORIZED \& RC_PAYMENT_REQUIRED \& RC_FORBIDDEN \& RC_NOT_FOUND \& RC_METHOD_NOT_ALLOWED \& RC_NOT_ACCEPTABLE \& RC_PROXY_AUTHENTICATION_REQUIRED \& RC_REQUEST_TIMEOUT \& RC_CONFLICT \& RC_GONE \& RC_LENGTH_REQUIRED \& RC_PRECONDITION_FAILED \& RC_REQUEST_ENTITY_TOO_LARGE \& RC_REQUEST_URI_TOO_LARGE \& RC_UNSUPPORTED_MEDIA_TYPE \& RC_INTERNAL_SERVER_ERROR \& RC_NOT_IMPLEMENTED \& RC_BAD_GATEWAY \& RC_SERVICE_UNAVAILABLE \& RC_GATEWAY_TIMEOUT \& RC_HTTP_VERSION_NOT_SUPPORTED .Ve .SH "CLASSIFICATION FUNCTIONS" .IX Header "CLASSIFICATION FUNCTIONS" The HTTP::Status classification functions are: .SS "is_success" .IX Subsection "is_success" .Vb 1 \& my $bool = is_success($rc); .Ve .PP True if response code indicated a successful request. .SS "is_error" .IX Subsection "is_error" .Vb 1 \& my $bool = is_error($rc) .Ve .PP True if response code indicated that an error occurred. .SH "CAVEAT" .IX Header "CAVEAT" Note that if you are using both LWP::Simple and the very popular \s-1CGI\s0 module, you may be importing a \f(CW\*(C`head\*(C'\fR function from each module, producing a warning like \f(CW\*(C`Prototype mismatch: sub main::head ($) vs none\*(C'\fR. Get around this problem by just not importing LWP::Simple's \&\f(CW\*(C`head\*(C'\fR function, like so: .PP .Vb 2 \& use LWP::Simple qw(!head); \& use CGI qw(:standard); # then only CGI.pm defines a head() .Ve .PP Then if you do need LWP::Simple's \f(CW\*(C`head\*(C'\fR function, you can just call it as \f(CW\*(C`LWP::Simple::head($url)\*(C'\fR. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1LWP\s0, lwpcook, LWP::UserAgent, HTTP::Status, lwp-request, lwp-mirror man/man3/version::Internals.3pm000044400000073113152462503210012332 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "version::Internals 3" .TH version::Internals 3 "2020-07-31" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" version::Internals \- Perl extension for Version Objects .SH "DESCRIPTION" .IX Header "DESCRIPTION" Overloaded version objects for all modern versions of Perl. This documents the internal data representation and underlying code for version.pm. See \&\fIversion.pod\fR for daily usage. This document is only useful for users interested in the gory details. .SH "WHAT IS A VERSION?" .IX Header "WHAT IS A VERSION?" For the purposes of this module, a version \*(L"number\*(R" is a sequence of positive integer values separated by one or more decimal points and optionally a single underscore. This corresponds to what Perl itself uses for a version, as well as extending the \*(L"version as number\*(R" that is discussed in the various editions of the Camel book. .PP There are actually two distinct kinds of version objects: .IP "Decimal versions" 4 .IX Item "Decimal versions" Any version which \*(L"looks like a number\*(R", see \*(L"Decimal Versions\*(R". This also includes versions with a single decimal point and a single embedded underscore, see \*(L"Alpha Versions\*(R", even though these must be quoted to preserve the underscore formatting. .IP "Dotted-Decimal versions" 4 .IX Item "Dotted-Decimal versions" Also referred to as \*(L"Dotted-Integer\*(R", these contains more than one decimal point and may have an optional embedded underscore, see Dotted-Decimal Versions. This is what is commonly used in most open source software as the \*(L"external\*(R" version (the one used as part of the tag or tarfile name). A leading 'v' character is now required and will warn if it missing. .PP Both of these methods will produce similar version objects, in that the default stringification will yield the version \*(L"Normal Form\*(R" only if required: .PP .Vb 3 \& $v = version\->new(1.002); # 1.002, but compares like 1.2.0 \& $v = version\->new(1.002003); # 1.002003 \& $v2 = version\->new("v1.2.3"); # v1.2.3 .Ve .PP In specific, version numbers initialized as \*(L"Decimal Versions\*(R" will stringify as they were originally created (i.e. the same string that was passed to \f(CW\*(C`new()\*(C'\fR. Version numbers initialized as \*(L"Dotted-Decimal Versions\*(R" will be stringified as \*(L"Normal Form\*(R". .SS "Decimal Versions" .IX Subsection "Decimal Versions" These correspond to historical versions of Perl itself prior to 5.6.0, as well as all other modules which follow the Camel rules for the \&\f(CW$VERSION\fR scalar. A Decimal version is initialized with what looks like a floating point number. Leading zeros \fBare\fR significant and trailing zeros are implied so that a minimum of three places is maintained between subversions. What this means is that any subversion (digits to the right of the decimal place) that contains less than three digits will have trailing zeros added to make up the difference, but only for purposes of comparison with other version objects. For example: .PP .Vb 7 \& # Prints Equivalent to \& $v = version\->new( 1.2); # 1.2 v1.200.0 \& $v = version\->new( 1.02); # 1.02 v1.20.0 \& $v = version\->new( 1.002); # 1.002 v1.2.0 \& $v = version\->new( 1.0023); # 1.0023 v1.2.300 \& $v = version\->new( 1.00203); # 1.00203 v1.2.30 \& $v = version\->new( 1.002003); # 1.002003 v1.2.3 .Ve .PP All of the preceding examples are true whether or not the input value is quoted. The important feature is that the input value contains only a single decimal. See also \*(L"Alpha Versions\*(R". .PP \&\s-1IMPORTANT NOTE:\s0 As shown above, if your Decimal version contains more than 3 significant digits after the decimal place, it will be split on each multiple of 3, so 1.0003 is equivalent to v1.0.300, due to the need to remain compatible with Perl's own 5.005_03 == 5.5.30 interpretation. Any trailing zeros are ignored for mathematical comparison purposes. .SS "Dotted-Decimal Versions" .IX Subsection "Dotted-Decimal Versions" These are the newest form of versions, and correspond to Perl's own version style beginning with 5.6.0. Starting with Perl 5.10.0, and most likely Perl 6, this is likely to be the preferred form. This method normally requires that the input parameter be quoted, although Perl's after 5.8.1 can use v\-strings as a special form of quoting, but this is highly discouraged. .PP Unlike \*(L"Decimal Versions\*(R", Dotted-Decimal Versions have more than a single decimal point, e.g.: .PP .Vb 6 \& # Prints \& $v = version\->new( "v1.200"); # v1.200.0 \& $v = version\->new("v1.20.0"); # v1.20.0 \& $v = qv("v1.2.3"); # v1.2.3 \& $v = qv("1.2.3"); # v1.2.3 \& $v = qv("1.20"); # v1.20.0 .Ve .PP In general, Dotted-Decimal Versions permit the greatest amount of freedom to specify a version, whereas Decimal Versions enforce a certain uniformity. .PP Just like \*(L"Decimal Versions\*(R", Dotted-Decimal Versions can be used as \&\*(L"Alpha Versions\*(R". .SS "Alpha Versions" .IX Subsection "Alpha Versions" For module authors using \s-1CPAN,\s0 the convention has been to note unstable releases with an underscore in the version string. (See \s-1CPAN\s0.) version.pm follows this convention and alpha releases will test as being newer than the more recent stable release, and less than the next stable release. Only the last element may be separated by an underscore: .PP .Vb 2 \& # Declaring \& use version 0.77; our $VERSION = version\->declare("v1.2_3"); \& \& # Parsing \& $v1 = version\->parse("v1.2_3"); \& $v1 = version\->parse("1.002_003"); .Ve .PP Note that you \fBmust\fR quote the version when writing an alpha Decimal version. The stringified form of Decimal versions will always be the same string that was used to initialize the version object. .SS "Regular Expressions for Version Parsing" .IX Subsection "Regular Expressions for Version Parsing" A formalized definition of the legal forms for version strings is included in the \f(CW\*(C`version::regex\*(C'\fR class. Primitives are included for common elements, although they are scoped to the file so they are useful for reference purposes only. There are two publicly accessible scalars that can be used in other code (not exported): .ie n .IP "$version::LAX" 4 .el .IP "\f(CW$version::LAX\fR" 4 .IX Item "$version::LAX" This regexp covers all of the legal forms allowed under the current version string parser. This is not to say that all of these forms are recommended, and some of them can only be used when quoted. .Sp For dotted decimals: .Sp .Vb 3 \& v1.2 \& 1.2345.6 \& v1.23_4 .Ve .Sp The leading 'v' is optional if two or more decimals appear. If only a single decimal is included, then the leading 'v' is required to trigger the dotted-decimal parsing. A leading zero is permitted, though not recommended except when quoted, because of the risk that Perl will treat the number as octal. A trailing underscore plus one or more digits denotes an alpha or development release (and must be quoted to be parsed properly). .Sp For decimal versions: .Sp .Vb 3 \& 1 \& 1.2345 \& 1.2345_01 .Ve .Sp an integer portion, an optional decimal point, and optionally one or more digits to the right of the decimal are all required. A trailing underscore is permitted and a leading zero is permitted. Just like the lax dotted-decimal version, quoting the values is required for alpha/development forms to be parsed correctly. .ie n .IP "$version::STRICT" 4 .el .IP "\f(CW$version::STRICT\fR" 4 .IX Item "$version::STRICT" This regexp covers a much more limited set of formats and constitutes the best practices for initializing version objects. Whether you choose to employ decimal or dotted-decimal for is a personal preference however. .RS 4 .IP "v1.234.5" 4 .IX Item "v1.234.5" For dotted-decimal versions, a leading 'v' is required, with three or more sub-versions of no more than three digits. A leading 0 (zero) before the first sub-version (in the above example, '1') is also prohibited. .IP "2.3456" 4 .IX Item "2.3456" For decimal versions, an integer portion (no leading 0), a decimal point, and one or more digits to the right of the decimal are all required. .RE .RS 4 .RE .PP Both of the provided scalars are already compiled as regular expressions and do not contain either anchors or implicit groupings, so they can be included in your own regular expressions freely. For example, consider the following code: .PP .Vb 6 \& ($pkg, $ver) =~ / \& ^[ \et]* \& use [ \et]+($PKGNAME) \& (?:[ \et]+($version::STRICT))? \& [ \et]*; \& /x; .Ve .PP This would match a line of the form: .PP .Vb 1 \& use Foo::Bar::Baz v1.2.3; # legal only in Perl 5.8.1+ .Ve .PP where \f(CW$PKGNAME\fR is another regular expression that defines the legal forms for package names. .SH "IMPLEMENTATION DETAILS" .IX Header "IMPLEMENTATION DETAILS" .SS "Equivalence between Decimal and Dotted-Decimal Versions" .IX Subsection "Equivalence between Decimal and Dotted-Decimal Versions" When Perl 5.6.0 was released, the decision was made to provide a transformation between the old-style decimal versions and new-style dotted-decimal versions: .PP .Vb 2 \& 5.6.0 == 5.006000 \& 5.005_04 == 5.5.40 .Ve .PP The floating point number is taken and split first on the single decimal place, then each group of three digits to the right of the decimal makes up the next digit, and so on until the number of significant digits is exhausted, \&\fBplus\fR enough trailing zeros to reach the next multiple of three. .PP This was the method that version.pm adopted as well. Some examples may be helpful: .PP .Vb 9 \& equivalent \& decimal zero\-padded dotted\-decimal \& \-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\- \& 1.2 1.200 v1.200.0 \& 1.02 1.020 v1.20.0 \& 1.002 1.002 v1.2.0 \& 1.0023 1.002300 v1.2.300 \& 1.00203 1.002030 v1.2.30 \& 1.002003 1.002003 v1.2.3 .Ve .SS "Quoting Rules" .IX Subsection "Quoting Rules" Because of the nature of the Perl parsing and tokenizing routines, certain initialization values \fBmust\fR be quoted in order to correctly parse as the intended version, especially when using the \f(CW\*(C`declare\*(C'\fR or \&\*(L"\fBqv()\fR\*(R" methods. While you do not have to quote decimal numbers when creating version objects, it is always safe to quote \fBall\fR initial values when using version.pm methods, as this will ensure that what you type is what is used. .PP Additionally, if you quote your initializer, then the quoted value that goes \&\fBin\fR will be exactly what comes \fBout\fR when your \f(CW$VERSION\fR is printed (stringified). If you do not quote your value, Perl's normal numeric handling comes into play and you may not get back what you were expecting. .PP If you use a mathematic formula that resolves to a floating point number, you are dependent on Perl's conversion routines to yield the version you expect. You are pretty safe by dividing by a power of 10, for example, but other operations are not likely to be what you intend. For example: .PP .Vb 4 \& $VERSION = version\->new((qw$Revision: 1.4)[1]/10); \& print $VERSION; # yields 0.14 \& $V2 = version\->new(100/9); # Integer overflow in decimal number \& print $V2; # yields something like 11.111.111.100 .Ve .PP Perl 5.8.1 and beyond are able to automatically quote v\-strings but that is not possible in earlier versions of Perl. In other words: .PP .Vb 2 \& $version = version\->new("v2.5.4"); # legal in all versions of Perl \& $newvers = version\->new(v2.5.4); # legal only in Perl >= 5.8.1 .Ve .SS "What about v\-strings?" .IX Subsection "What about v-strings?" There are two ways to enter v\-strings: a bare number with two or more decimal points, or a bare number with one or more decimal points and a leading 'v' character (also bare). For example: .PP .Vb 2 \& $vs1 = 1.2.3; # encoded as \e1\e2\e3 \& $vs2 = v1.2; # encoded as \e1\e2 .Ve .PP However, the use of bare v\-strings to initialize version objects is \&\fBstrongly\fR discouraged in all circumstances. Also, bare v\-strings are not completely supported in any version of Perl prior to 5.8.1. .PP If you insist on using bare v\-strings with Perl > 5.6.0, be aware of the following limitations: .PP 1) For Perl releases 5.6.0 through 5.8.0, the v\-string code merely guesses, based on some characteristics of v\-strings. You \fBmust\fR use a three part version, e.g. 1.2.3 or v1.2.3 in order for this heuristic to be successful. .PP 2) For Perl releases 5.8.1 and later, v\-strings have changed in the Perl core to be magical, which means that the version.pm code can automatically determine whether the v\-string encoding was used. .PP 3) In all cases, a version created using v\-strings will have a stringified form that has a leading 'v' character, for the simple reason that sometimes it is impossible to tell whether one was present initially. .SS "Version Object Internals" .IX Subsection "Version Object Internals" version.pm provides an overloaded version object that is designed to both encapsulate the author's intended \f(CW$VERSION\fR assignment as well as make it completely natural to use those objects as if they were numbers (e.g. for comparisons). To do this, a version object contains both the original representation as typed by the author, as well as a parsed representation to ease comparisons. Version objects employ overload methods to simplify code that needs to compare, print, etc the objects. .PP The internal structure of version objects is a blessed hash with several components: .PP .Vb 11 \& bless( { \& \*(Aqoriginal\*(Aq => \*(Aqv1.2.3_4\*(Aq, \& \*(Aqalpha\*(Aq => 1, \& \*(Aqqv\*(Aq => 1, \& \*(Aqversion\*(Aq => [ \& 1, \& 2, \& 3, \& 4 \& ] \& }, \*(Aqversion\*(Aq ); .Ve .IP "original" 4 .IX Item "original" A faithful representation of the value used to initialize this version object. The only time this will not be precisely the same characters that exist in the source file is if a short dotted-decimal version like v1.2 was used (in which case it will contain 'v1.2'). This form is \&\fB\s-1STRONGLY\s0\fR discouraged, in that it will confuse you and your users. .IP "qv" 4 .IX Item "qv" A boolean that denotes whether this is a decimal or dotted-decimal version. See \*(L"\fBis_qv()\fR\*(R" in version. .IP "alpha" 4 .IX Item "alpha" A boolean that denotes whether this is an alpha version. \s-1NOTE:\s0 that the underscore can only appear in the last position. See \*(L"\fBis_alpha()\fR\*(R" in version. .IP "version" 4 .IX Item "version" An array of non-negative integers that is used for comparison purposes with other version objects. .SS "Replacement \s-1UNIVERSAL::VERSION\s0" .IX Subsection "Replacement UNIVERSAL::VERSION" In addition to the version objects, this modules also replaces the core \&\s-1UNIVERSAL::VERSION\s0 function with one that uses version objects for its comparisons. The return from this operator is always the stringified form as a simple scalar (i.e. not an object), but the warning message generated includes either the stringified form or the normal form, depending on how it was called. .PP For example: .PP .Vb 2 \& package Foo; \& $VERSION = 1.2; \& \& package Bar; \& $VERSION = "v1.3.5"; # works with all Perl\*(Aqs (since it is quoted) \& \& package main; \& use version; \& \& print $Foo::VERSION; # prints 1.2 \& \& print $Bar::VERSION; # prints 1.003005 \& \& eval "use foo 10"; \& print $@; # prints "foo version 10 required..." \& eval "use foo 1.3.5; # work in Perl 5.6.1 or better \& print $@; # prints "foo version 1.3.5 required..." \& \& eval "use bar 1.3.6"; \& print $@; # prints "bar version 1.3.6 required..." \& eval "use bar 1.004"; # note Decimal version \& print $@; # prints "bar version 1.004 required..." .Ve .PP \&\s-1IMPORTANT NOTE:\s0 This may mean that code which searches for a specific string (to determine whether a given module is available) may need to be changed. It is always better to use the built-in comparison implicit in \&\f(CW\*(C`use\*(C'\fR or \f(CW\*(C`require\*(C'\fR, rather than manually poking at \f(CW\*(C`class\->VERSION\*(C'\fR and then doing a comparison yourself. .PP The replacement \s-1UNIVERSAL::VERSION,\s0 when used as a function, like this: .PP .Vb 1 \& print $module\->VERSION; .Ve .PP will also exclusively return the stringified form. See \*(L"Stringification\*(R" for more details. .SH "USAGE DETAILS" .IX Header "USAGE DETAILS" .SS "Using modules that use version.pm" .IX Subsection "Using modules that use version.pm" As much as possible, the version.pm module remains compatible with all current code. However, if your module is using a module that has defined \&\f(CW$VERSION\fR using the version class, there are a couple of things to be aware of. For purposes of discussion, we will assume that we have the following module installed: .PP .Vb 4 \& package Example; \& use version; $VERSION = qv(\*(Aq1.2.2\*(Aq); \& ...module code here... \& 1; .Ve .IP "Decimal versions always work" 4 .IX Item "Decimal versions always work" Code of the form: .Sp .Vb 1 \& use Example 1.002003; .Ve .Sp will always work correctly. The \f(CW\*(C`use\*(C'\fR will perform an automatic \&\f(CW$VERSION\fR comparison using the floating point number given as the first term after the module name (e.g. above 1.002.003). In this case, the installed module is too old for the requested line, so you would see an error like: .Sp .Vb 1 \& Example version 1.002003 (v1.2.3) required\-\-this is only version 1.002002 (v1.2.2)... .Ve .IP "Dotted-Decimal version work sometimes" 4 .IX Item "Dotted-Decimal version work sometimes" With Perl >= 5.6.2, you can also use a line like this: .Sp .Vb 1 \& use Example 1.2.3; .Ve .Sp and it will again work (i.e. give the error message as above), even with releases of Perl which do not normally support v\-strings (see \*(L"What about v\-strings?\*(R" above). This has to do with that fact that \f(CW\*(C`use\*(C'\fR only checks to see if the second term \fIlooks like a number\fR and passes that to the replacement \s-1UNIVERSAL::VERSION\s0. This is not true in Perl 5.005_04, however, so you are \fBstrongly encouraged\fR to always use a Decimal version in your code, even for those versions of Perl which support the Dotted-Decimal version. .SS "Object Methods" .IX Subsection "Object Methods" .IP "\fBnew()\fR" 4 .IX Item "new()" Like many \s-1OO\s0 interfaces, the \fBnew()\fR method is used to initialize version objects. If two arguments are passed to \f(CW\*(C`new()\*(C'\fR, the \fBsecond\fR one will be used as if it were prefixed with \*(L"v\*(R". This is to support historical use of the \&\f(CW\*(C`qw\*(C'\fR operator with the \s-1CVS\s0 variable \f(CW$Revision\fR, which is automatically incremented by \s-1CVS\s0 every time the file is committed to the repository. .Sp In order to facilitate this feature, the following code can be employed: .Sp .Vb 1 \& $VERSION = version\->new(qw$Revision: 2.7 $); .Ve .Sp and the version object will be created as if the following code were used: .Sp .Vb 1 \& $VERSION = version\->new("v2.7"); .Ve .Sp In other words, the version will be automatically parsed out of the string, and it will be quoted to preserve the meaning \s-1CVS\s0 normally carries for versions. The \s-1CVS\s0 \f(CW$Revision\fR$ increments differently from Decimal versions (i.e. 1.10 follows 1.9), so it must be handled as if it were a Dotted-Decimal Version. .Sp A new version object can be created as a copy of an existing version object, either as a class method: .Sp .Vb 2 \& $v1 = version\->new(12.3); \& $v2 = version\->new($v1); .Ve .Sp or as an object method: .Sp .Vb 2 \& $v1 = version\->new(12.3); \& $v2 = $v1\->new(12.3); .Ve .Sp and in each case, \f(CW$v1\fR and \f(CW$v2\fR will be identical. \s-1NOTE:\s0 if you create a new object using an existing object like this: .Sp .Vb 1 \& $v2 = $v1\->new(); .Ve .Sp the new object \fBwill not\fR be a clone of the existing object. In the example case, \f(CW$v2\fR will be an empty object of the same type as \f(CW$v1\fR. .IP "\fBqv()\fR" 4 .IX Item "qv()" An alternate way to create a new version object is through the exported \&\fBqv()\fR sub. This is not strictly like other q? operators (like qq, qw), in that the only delimiters supported are parentheses (or spaces). It is the best way to initialize a short version without triggering the floating point interpretation. For example: .Sp .Vb 2 \& $v1 = qv(1.2); # v1.2.0 \& $v2 = qv("1.2"); # also v1.2.0 .Ve .Sp As you can see, either a bare number or a quoted string can usually be used interchangeably, except in the case of a trailing zero, which must be quoted to be converted properly. For this reason, it is strongly recommended that all initializers to \fBqv()\fR be quoted strings instead of bare numbers. .Sp To prevent the \f(CW\*(C`qv()\*(C'\fR function from being exported to the caller's namespace, either use version with a null parameter: .Sp .Vb 1 \& use version (); .Ve .Sp or just require version, like this: .Sp .Vb 1 \& require version; .Ve .Sp Both methods will prevent the \fBimport()\fR method from firing and exporting the \&\f(CW\*(C`qv()\*(C'\fR sub. .PP For the subsequent examples, the following three objects will be used: .PP .Vb 3 \& $ver = version\->new("1.2.3.4"); # see "Quoting Rules" \& $alpha = version\->new("1.2.3_4"); # see "Alpha Versions" \& $nver = version\->new(1.002); # see "Decimal Versions" .Ve .IP "Normal Form" 4 .IX Item "Normal Form" For any version object which is initialized with multiple decimal places (either quoted or if possible v\-string), or initialized using the \fBqv()\fR operator, the stringified representation is returned in a normalized or reduced form (no extraneous zeros), and with a leading 'v': .Sp .Vb 6 \& print $ver\->normal; # prints as v1.2.3.4 \& print $ver\->stringify; # ditto \& print $ver; # ditto \& print $nver\->normal; # prints as v1.2.0 \& print $nver\->stringify; # prints as 1.002, \& # see "Stringification" .Ve .Sp In order to preserve the meaning of the processed version, the normalized representation will always contain at least three sub terms. In other words, the following is guaranteed to always be true: .Sp .Vb 3 \& my $newver = version\->new($ver\->stringify); \& if ($newver eq $ver ) # always true \& {...} .Ve .IP "Numification" 4 .IX Item "Numification" Although all mathematical operations on version objects are forbidden by default, it is possible to retrieve a number which corresponds to the version object through the use of the \f(CW$obj\fR\->numify method. For formatting purposes, when displaying a number which corresponds a version object, all sub versions are assumed to have three decimal places. So for example: .Sp .Vb 2 \& print $ver\->numify; # prints 1.002003004 \& print $nver\->numify; # prints 1.002 .Ve .Sp Unlike the stringification operator, there is never any need to append trailing zeros to preserve the correct version value. .IP "Stringification" 4 .IX Item "Stringification" The default stringification for version objects returns exactly the same string as was used to create it, whether you used \f(CW\*(C`new()\*(C'\fR or \f(CW\*(C`qv()\*(C'\fR, with one exception. The sole exception is if the object was created using \&\f(CW\*(C`qv()\*(C'\fR and the initializer did not have two decimal places or a leading \&'v' (both optional), then the stringified form will have a leading 'v' prepended, in order to support round-trip processing. .Sp For example: .Sp .Vb 7 \& Initialized as Stringifies to \& ============== ============== \& version\->new("1.2") 1.2 \& version\->new("v1.2") v1.2 \& qv("1.2.3") 1.2.3 \& qv("v1.3.5") v1.3.5 \& qv("1.2") v1.2 ### exceptional case .Ve .Sp See also \s-1UNIVERSAL::VERSION\s0, as this also returns the stringified form when used as a class method. .Sp \&\s-1IMPORTANT NOTE:\s0 There is one exceptional cases shown in the above table where the \*(L"initializer\*(R" is not stringwise equivalent to the stringified representation. If you use the \f(CW\*(C`qv\*(C'\fR() operator on a version without a leading 'v' \fBand\fR with only a single decimal place, the stringified output will have a leading 'v', to preserve the sense. See the \*(L"\fBqv()\fR\*(R" operator for more details. .Sp \&\s-1IMPORTANT NOTE 2:\s0 Attempting to bypass the normal stringification rules by manually applying \fBnumify()\fR and \fBnormal()\fR will sometimes yield surprising results: .Sp .Vb 1 \& print version\->new(version\->new("v1.0")\->numify)\->normal; # v1.0.0 .Ve .Sp The reason for this is that the \fBnumify()\fR operator will turn \*(L"v1.0\*(R" into the equivalent string \*(L"1.000000\*(R". Forcing the outer version object to \fBnormal()\fR form will display the mathematically equivalent \*(L"v1.0.0\*(R". .Sp As the example in \*(L"\fBnew()\fR\*(R" shows, you can always create a copy of an existing version object with the same value by the very compact: .Sp .Vb 1 \& $v2 = $v1\->new($v1); .Ve .Sp and be assured that both \f(CW$v1\fR and \f(CW$v2\fR will be completely equivalent, down to the same internal representation as well as stringification. .IP "Comparison operators" 4 .IX Item "Comparison operators" Both \f(CW\*(C`cmp\*(C'\fR and \f(CW\*(C`<=>\*(C'\fR operators perform the same comparison between terms (upgrading to a version object automatically). Perl automatically generates all of the other comparison operators based on those two. In addition to the obvious equalities listed below, appending a single trailing 0 term does not change the value of a version for comparison purposes. In other words \*(L"v1.2\*(R" and \*(L"1.2.0\*(R" will compare as identical. .Sp For example, the following relations hold: .Sp .Vb 7 \& As Number As String Truth Value \& \-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\- \& $ver > 1.0 $ver gt "1.0" true \& $ver < 2.5 $ver lt true \& $ver != 1.3 $ver ne "1.3" true \& $ver == 1.2 $ver eq "1.2" false \& $ver == 1.2.3.4 $ver eq "1.2.3.4" see discussion below .Ve .Sp It is probably best to chose either the Decimal notation or the string notation and stick with it, to reduce confusion. Perl6 version objects \&\fBmay\fR only support Decimal comparisons. See also \*(L"Quoting Rules\*(R". .Sp \&\s-1WARNING:\s0 Comparing version with unequal numbers of decimal points (whether explicitly or implicitly initialized), may yield unexpected results at first glance. For example, the following inequalities hold: .Sp .Vb 2 \& version\->new(0.96) > version\->new(0.95); # 0.960.0 > 0.950.0 \& version\->new("0.96.1") < version\->new(0.95); # 0.096.1 < 0.950.0 .Ve .Sp For this reason, it is best to use either exclusively \*(L"Decimal Versions\*(R" or \&\*(L"Dotted-Decimal Versions\*(R" with multiple decimal points. .IP "Logical Operators" 4 .IX Item "Logical Operators" If you need to test whether a version object has been initialized, you can simply test it directly: .Sp .Vb 2 \& $vobj = version\->new($something); \& if ( $vobj ) # true only if $something was non\-blank .Ve .Sp You can also test whether a version object is an alpha version, for example to prevent the use of some feature not present in the main release: .Sp .Vb 3 \& $vobj = version\->new("1.2_3"); # MUST QUOTE \& ...later... \& if ( $vobj\->is_alpha ) # True .Ve .SH "AUTHOR" .IX Header "AUTHOR" John Peacock .SH "SEE ALSO" .IX Header "SEE ALSO" perl. man/man3/IO::LockedFile::Flock.3pm000044400000005557152462503210012370 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LockedFile::Flock 3" .TH LockedFile::Flock 3 "2003-02-20" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" IO::LockedFile::Flock Class implements the IO::LockedFile class for the Flock scheme. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& See IO::LockedFile; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This class implements the two methods lock and unlock for the Flock scheme. .SH "AUTHORS" .IX Header "AUTHORS" Rani Pinchuk, rani@cpan.org .PP Rob Napier, rnapier@employees.org .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2001\-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBIO::File\fR\|(3), \&\fBIO::LockedFile\fR\|(3) man/man3/common::sense.3pm000044400000000000152462503210011274 0ustar00man/man3/DBI::Const::GetInfoType.3pm000044400000005253152462503210012674 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Const::GetInfoType 3" .TH DBI::Const::GetInfoType 3 "2018-08-04" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Const::GetInfoType \- Data describing GetInfo type codes .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use DBI::Const::GetInfoType; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Imports a \f(CW%GetInfoType\fR hash which maps names for GetInfo Type Codes into their corresponding numeric values. For example: .PP .Vb 1 \& $database_version = $dbh\->get_info( $GetInfoType{SQL_DBMS_VER} ); .Ve .PP The interface to this module is new and nothing beyond what is written here is guaranteed. man/man3/Log::LogLite.3pm000044400000015600152462503210010763 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LogLite 3" .TH LogLite 3 "2002-09-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Log::LogLite \- The "Log::LogLite" class helps us create simple logs for our application. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use Log::LogLite; \& my $LOG_DIRECTORY = "/where/ever/our/log/file/should/be"; \& my $ERROR_LOG_LEVEL = 6; \& \& # create new Log::LogLite object \& my $log = new Log::LogLite($LOG_DIRECTORY."/error.log", $ERROR_LOG_LEVEL); \& \& ... \& \& # we had an error \& $log\->write("Could not open the file ".$file_name.": $!", 4); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" In order to have a log we have first to create a \f(CW\*(C`Log::LogLite\*(C'\fR object. The c object is created with a logging level. The default logging level is 5. After the \f(CW\*(C`Log::LogLite\*(C'\fR object is created, each call to the \f(CW\*(C`write\*(C'\fR method may write a new line in the log file. If the level of the message is lower or equal to the logging level, the message will be written to the log file. The format of the logging messages can be controled by changing the template, and by defining a default message. The class uses the IO::LockedFile class. .SH "CONSTRUCTOR" .IX Header "CONSTRUCTOR" .IP "new ( \s-1FILEPATH\s0 [,LEVEL [,DEFAULT_MESSAGE ]] )" 4 .IX Item "new ( FILEPATH [,LEVEL [,DEFAULT_MESSAGE ]] )" The constructor. \s-1FILEPATH\s0 is the path of the log file. \s-1LEVEL\s0 is the defined logging level \- the \s-1LEVEL\s0 data member. \s-1DEFAULT_MESSAGE\s0 will define the \&\s-1DEFAULT_MESSAGE\s0 data member \- a message that will be added to the message of each entry in the log (according to the \s-1TEMPLATE\s0 data member, see below). .Sp The levels can be any levels that the user chooses to use. There are, though, recommended levels: 0 the application is unusable 1 the application is going to be unusable 2 critical conditions 3 error conditions 4 warning conditions 5 normal but significant condition 6 informational 7+ debug-level messages .Sp The default value of \s-1LEVEL\s0 is 5. The default value of \s-1DEFAULT_MESSAGE\s0 is "". Returns the new object. .SH "METHODS" .IX Header "METHODS" .IP "write( \s-1MESSAGE\s0 [, \s-1LEVEL\s0 ] )" 4 .IX Item "write( MESSAGE [, LEVEL ] )" If \s-1LEVEL\s0 is less or equal to the \s-1LEVEL\s0 data member, or if \s-1LEVEL\s0 is undefined, the string in \s-1MESSAGE\s0 will be written to the log file. Does not return anything. .IP "level( [ \s-1LEVEL\s0 ] )" 4 .IX Item "level( [ LEVEL ] )" Access method to the \s-1LEVEL\s0 data member. If \s-1LEVEL\s0 is defined, the \s-1LEVEL\s0 data member will get its value. Returns the value of the \s-1LEVEL\s0 data member. .IP "default_message( [ \s-1MESSAGE\s0 ] )" 4 .IX Item "default_message( [ MESSAGE ] )" Access method to the \s-1DEFAULT_MESSAGE\s0 data member. If \s-1MESSAGE\s0 is defined, the \&\s-1DEFAULT_MESSAGE\s0 data member will get its value. Returns the value of the \s-1DEFAULT_MESSAGE\s0 data member. .IP "log_line_numbers( [ \s-1BOOLEAN\s0 ] )" 4 .IX Item "log_line_numbers( [ BOOLEAN ] )" If this flag is set to true, the string will hold the file that calls the subroutine and the line where the call is issued. The default value is zero. .IP "template( [ \s-1TEMPLATE\s0 ] )" 4 .IX Item "template( [ TEMPLATE ] )" Access method to the \s-1TEMPLATE\s0 data member. The \s-1TEMPLATE\s0 data member is a string that defines how the log entries will look like. The default \s-1TEMPLATE\s0 is: .Sp \&'[] <> ' .Sp Where: .Sp .Vb 10 \& will be replaced by a string that represent \& the date. For example: 09/01/2000 17:00:13 \& will be replaced by the level of the entry. \& will be replaced by a call trace string. For \& example: \& CGIDaemon::listen > MyCGIDaemon::accepted \& will be replaced by the value of the \& DEFAULT_MESSAGE data member. \& will be replaced by the message string that \& is sent to the C method. .Ve .Sp Returns the value of the \s-1TEMPLATE\s0 data member. .SH "AUTHOR" .IX Header "AUTHOR" Rani Pinchuk, rani@cpan.org .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2001\-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBIO::LockedFile\fR\|(3) .SH "POD ERRORS" .IX Header "POD ERRORS" Hey! \fBThe above document had some coding errors, which are explained below:\fR .IP "Around line 282:" 4 .IX Item "Around line 282:" You forgot a '=back' before '=head1' man/man3/LWP::ConnCache.3pm000044400000020755152462503210011175 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::ConnCache 3" .TH LWP::ConnCache 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::ConnCache \- Connection cache manager .SH "NOTE" .IX Header "NOTE" This module is experimental. Details of its interface is likely to change in the future. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 4 \& use LWP::ConnCache; \& my $cache = LWP::ConnCache\->new; \& $cache\->deposit($type, $key, $sock); \& $sock = $cache\->withdraw($type, $key); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`LWP::ConnCache\*(C'\fR class is the standard connection cache manager for LWP::UserAgent. .SH "METHODS" .IX Header "METHODS" The following basic methods are provided: .SS "new" .IX Subsection "new" .Vb 1 \& my $cache = LWP::ConnCache\->new( %options ) .Ve .PP This method constructs a new LWP::ConnCache object. The only option currently accepted is \f(CW\*(C`total_capacity\*(C'\fR. If specified it initializes the \*(L"total_capacity\*(R" in LWP::ConnCache option. It defaults to \f(CW1\fR. .SS "total_capacity" .IX Subsection "total_capacity" .Vb 4 \& my $cap = $cache\->total_capacity; \& $cache\->total_capacity(0); # drop all immediately \& $cache\->total_capacity(undef); # no limit \& $cache\->total_capacity($number); .Ve .PP Get/sets the number of connection that will be cached. Connections will start to be dropped when this limit is reached. If set to \f(CW0\fR, then all connections are immediately dropped. If set to \f(CW\*(C`undef\*(C'\fR, then there is no limit. .SS "capacity" .IX Subsection "capacity" .Vb 2 \& my $http_capacity = $cache\->capacity(\*(Aqhttp\*(Aq); \& $cache\->capacity(\*(Aqhttp\*(Aq, 2 ); .Ve .PP Get/set a limit for the number of connections of the specified type that can be cached. The first parameter is a short string like \&\f(CW"http"\fR or \f(CW"ftp"\fR. .SS "drop" .IX Subsection "drop" .Vb 10 \& $cache\->drop(); # Drop ALL connections \& # which is just a synonym for: \& $cache\->drop(sub{1}); # Drop ALL connections \& # drop all connections older than 22 seconds and add a reason for it! \& $cache\->drop(22, "Older than 22 secs dropped"); \& # which is just a synonym for: \& $cache\->drop(sub { \& my ($conn, $type, $key, $deposit_time) = @_; \& if ($deposit_time < 22) { \& # true values drop the connection \& return 1; \& } \& # false values don\*(Aqt drop the connection \& return 0; \& }, "Older than 22 secs dropped" ); .Ve .PP Drop connections by some criteria. The \f(CW$checker\fR argument is a subroutine that is called for each connection. If the routine returns a \s-1TRUE\s0 value then the connection is dropped. The routine is called with \f(CW\*(C`($conn, $type, $key, $deposit_time)\*(C'\fR as arguments. .PP Shortcuts: If the \f(CW$checker\fR argument is absent (or \f(CW\*(C`undef\*(C'\fR) all cached connections are dropped. If the \f(CW$checker\fR is a number then all connections untouched that the given number of seconds or more are dropped. If \f(CW$checker\fR is a string then all connections of the given type are dropped. .PP The \f(CW\*(C`reason\*(C'\fR is passed on to the \*(L"dropped\*(R" in LWP::ConnCache method. .SS "prune" .IX Subsection "prune" .Vb 1 \& $cache\->prune(); .Ve .PP Calling this method will drop all connections that are dead. This is tested by calling the \*(L"ping\*(R" in LWP::ConnCache method on the connections. If the \*(L"ping\*(R" in LWP::ConnCache method exists and returns a false value, then the connection is dropped. .SS "get_types" .IX Subsection "get_types" .Vb 1 \& my @types = $cache\->get_types(); .Ve .PP This returns all the \f(CW\*(C`type\*(C'\fR fields used for the currently cached connections. .SS "get_connections" .IX Subsection "get_connections" .Vb 2 \& my @conns = $cache\->get_connections(); # all connections \& my @conns = $cache\->get_connections(\*(Aqhttp\*(Aq); # connections for http .Ve .PP This returns all connection objects of the specified type. If no type is specified then all connections are returned. In scalar context the number of cached connections of the specified type is returned. .SH "PROTOCOL METHODS" .IX Header "PROTOCOL METHODS" The following methods are called by low-level protocol modules to try to save away connections and to get them back. .SS "deposit" .IX Subsection "deposit" .Vb 1 \& $cache\->deposit($type, $key, $conn); .Ve .PP This method adds a new connection to the cache. As a result, other already cached connections might be dropped. Multiple connections with the same type/key might be added. .SS "withdraw" .IX Subsection "withdraw" .Vb 1 \& my $conn = $cache\->withdraw($type, $key); .Ve .PP This method tries to fetch back a connection that was previously deposited. If no cached connection with the specified \f(CW$type\fR/$key is found, then \f(CW\*(C`undef\*(C'\fR is returned. There is not guarantee that a deposited connection can be withdrawn, as the cache manger is free to drop connections at any time. .SH "INTERNAL METHODS" .IX Header "INTERNAL METHODS" The following methods are called internally. Subclasses might want to override them. .SS "enforce_limits" .IX Subsection "enforce_limits" .Vb 1 \& $conn\->enforce_limits([$type]) .Ve .PP This method is called with after a new connection is added (deposited) in the cache or capacity limits are adjusted. The default implementation drops connections until the specified capacity limits are not exceeded. .SS "dropping" .IX Subsection "dropping" .Vb 1 \& $conn\->dropping($conn_record, $reason) .Ve .PP This method is called when a connection is dropped. The record belonging to the dropped connection is passed as the first argument and a string describing the reason for the drop is passed as the second argument. The default implementation makes some noise if the \&\f(CW$LWP::ConnCache::DEBUG\fR variable is set and nothing more. .SH "SUBCLASSING" .IX Header "SUBCLASSING" For specialized cache policy it makes sense to subclass \&\f(CW\*(C`LWP::ConnCache\*(C'\fR and perhaps override the \*(L"deposit\*(R" in LWP::ConnCache, \&\*(L"enforce_limits\*(R" in LWP::ConnCache, and \*(L"dropping\*(R" in LWP::ConnCache methods. .PP The object itself is a hash. Keys prefixed with \f(CW\*(C`cc_\*(C'\fR are reserved for the base class. .SH "SEE ALSO" .IX Header "SEE ALSO" LWP::UserAgent .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2001 Gisle Aas. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBD::Gofer::Policy::Base.3pm000044400000012225152462503210012661 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Policy::Base 3" .TH DBD::Gofer::Policy::Base 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Policy::Base \- Base class for DBD::Gofer policies .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=...", ...) .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBD::Gofer can be configured via a 'policy' mechanism that allows you to fine-tune the number of round-trips to the Gofer server. The policies are grouped into classes (which may be subclassed) and referenced by the name of the class. .PP The DBD::Gofer::Policy::Base class is the base class for all the policy classes and describes all the individual policy items. .PP The Base policy is not used directly. You should use a policy class derived from it. .SH "POLICY CLASSES" .IX Header "POLICY CLASSES" Three policy classes are supplied with DBD::Gofer: .PP DBD::Gofer::Policy::pedantic is most 'transparent' but slowest because it makes more round-trips to the Gofer server. .PP DBD::Gofer::Policy::classic is a reasonable compromise \- it's the default policy. .PP DBD::Gofer::Policy::rush is fastest, but may require code changes in your applications. .PP Generally the default \f(CW\*(C`classic\*(C'\fR policy is fine. When first testing an existing application with Gofer it is a good idea to start with the \f(CW\*(C`pedantic\*(C'\fR policy first and then switch to \f(CW\*(C`classic\*(C'\fR or a custom policy, for final testing. .SH "POLICY ITEMS" .IX Header "POLICY ITEMS" These are temporary docs: See the source code for list of policies and their defaults. .PP In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. .PP See the source code to this module for more details. .SH "POLICY CUSTOMIZATION" .IX Header "POLICY CUSTOMIZATION" \&\s-1XXX\s0 This area of DBD::Gofer is subject to change. .PP There are three ways to customize policies: .PP Policy classes are designed to influence the overall behaviour of DBD::Gofer with existing, unaltered programs, so they work in a reasonably optimal way without requiring code changes. You can implement new policy classes as subclasses of existing policies. .PP In many cases individual policy items can be overridden on a case-by-case basis within your application code. You do this by passing a corresponding \&\f(CW\*(C`> attribute into \s-1DBI\s0 methods by your application code. This let's you fine-tune the behaviour for special cases. .PP The policy items are implemented as methods. In many cases the methods are passed parameters relating to the DBD::Gofer code being executed. This means the policy can implement dynamic behaviour that varies depending on the particular circumstances, such as the particular statement being executed. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/DBI::ProfileData.3pm000044400000032015152462503210011472 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::ProfileData 3" .TH DBI::ProfileData 3 "2017-08-13" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::ProfileData \- manipulate DBI::ProfileDumper data dumps .SH "SYNOPSIS" .IX Header "SYNOPSIS" The easiest way to use this module is through the dbiprof frontend (see dbiprof for details): .PP .Vb 1 \& dbiprof \-\-number 15 \-\-sort count .Ve .PP This module can also be used to roll your own profile analysis: .PP .Vb 2 \& # load data from dbi.prof \& $prof = DBI::ProfileData\->new(File => "dbi.prof"); \& \& # get a count of the records (unique paths) in the data set \& $count = $prof\->count(); \& \& # sort by longest overall time \& $prof\->sort(field => "longest"); \& \& # sort by longest overall time, least to greatest \& $prof\->sort(field => "longest", reverse => 1); \& \& # exclude records with key2 eq \*(Aqdisconnect\*(Aq \& $prof\->exclude(key2 => \*(Aqdisconnect\*(Aq); \& \& # exclude records with key1 matching /^UPDATE/i \& $prof\->exclude(key1 => qr/^UPDATE/i); \& \& # remove all records except those where key1 matches /^SELECT/i \& $prof\->match(key1 => qr/^SELECT/i); \& \& # produce a formatted report with the given number of items \& $report = $prof\->report(number => 10); \& \& # clone the profile data set \& $clone = $prof\->clone(); \& \& # get access to hash of header values \& $header = $prof\->header(); \& \& # get access to sorted array of nodes \& $nodes = $prof\->nodes(); \& \& # format a single node in the same style as report() \& $text = $prof\->format($nodes\->[0]); \& \& # get access to Data hash in DBI::Profile format \& $Data = $prof\->Data(); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module offers the ability to read, manipulate and format DBI::ProfileDumper profile data. .PP Conceptually, a profile consists of a series of records, or nodes, each of each has a set of statistics and set of keys. Each record must have a unique set of keys, but there is no requirement that every record have the same number of keys. .SH "METHODS" .IX Header "METHODS" The following methods are supported by DBI::ProfileData objects. .ie n .SS "$prof = DBI::ProfileData\->new(File => ""dbi.prof"")" .el .SS "\f(CW$prof\fP = DBI::ProfileData\->new(File => ``dbi.prof'')" .IX Subsection "$prof = DBI::ProfileData->new(File => dbi.prof)" .ie n .SS "$prof = DBI::ProfileData\->new(File => ""dbi.prof"", Filter => sub { ... })" .el .SS "\f(CW$prof\fP = DBI::ProfileData\->new(File => ``dbi.prof'', Filter => sub { ... })" .IX Subsection "$prof = DBI::ProfileData->new(File => dbi.prof, Filter => sub { ... })" .ie n .SS "$prof = DBI::ProfileData\->new(Files => [ ""dbi.prof.1"", ""dbi.prof.2"" ])" .el .SS "\f(CW$prof\fP = DBI::ProfileData\->new(Files => [ ``dbi.prof.1'', ``dbi.prof.2'' ])" .IX Subsection "$prof = DBI::ProfileData->new(Files => [ dbi.prof.1, dbi.prof.2 ])" Creates a new DBI::ProfileData object. Takes either a single file through the File option or a list of Files in an array ref. If multiple files are specified then the header data from the first file is used. .PP \fIFiles\fR .IX Subsection "Files" .PP Reference to an array of file names to read. .PP \fIFile\fR .IX Subsection "File" .PP Name of file to read. Takes precedence over \f(CW\*(C`Files\*(C'\fR. .PP \fIDeleteFiles\fR .IX Subsection "DeleteFiles" .PP If true, the files are deleted after being read. .PP Actually the files are renamed with a \f(CW\*(C`deleteme\*(C'\fR suffix before being read, and then, after reading all the files, they're all deleted together. .PP The files are locked while being read which, combined with the rename, makes it safe to 'consume' files that are still being generated by DBI::ProfileDumper. .PP \fIFilter\fR .IX Subsection "Filter" .PP The \f(CW\*(C`Filter\*(C'\fR parameter can be used to supply a code reference that can manipulate the profile data as it is being read. This is most useful for editing \s-1SQL\s0 statements so that slightly different statements in the raw data will be merged and aggregated in the loaded data. For example: .PP .Vb 4 \& Filter => sub { \& my ($path_ref, $data_ref) = @_; \& s/foo = \*(Aq.*?\*(Aq/foo = \*(Aq...\*(Aq/ for @$path_ref; \& } .Ve .PP Here's an example that performs some normalization on the \s-1SQL.\s0 It converts all numbers to \f(CW\*(C`N\*(C'\fR and all quoted strings to \f(CW\*(C`S\*(C'\fR. It can also convert digits to N within names. Finally, it summarizes long \*(L"\s-1IN\s0 (...)\*(R" clauses. .PP It's aggressive and simplistic, but it's often sufficient, and serves as an example that you can tailor to suit your own needs: .PP .Vb 12 \& Filter => sub { \& my ($path_ref, $data_ref) = @_; \& local $_ = $path_ref\->[0]; # whichever element contains the SQL Statement \& s/\eb\ed+\eb/N/g; # 42 \-> N \& s/\eb0x[0\-9A\-Fa\-f]+\eb/N/g; # 0xFE \-> N \& s/\*(Aq.*?\*(Aq/\*(AqS\*(Aq/g; # single quoted strings (doesn\*(Aqt handle escapes) \& s/".*?"/"S"/g; # double quoted strings (doesn\*(Aqt handle escapes) \& # convert names like log_20001231 into log_NNNNNNNN, controlled by $opt{n} \& s/([a\-z_]+)(\ed{$opt{n},})/$1.(\*(AqN\*(Aq x length($2))/ieg if $opt{n}; \& # abbreviate massive "in (...)" statements and similar \& s!(([NS],){100,})!sprintf("$2,{repeated %d times}",length($1)/2)!eg; \& } .Ve .PP It's often better to perform this kinds of normalization in the \s-1DBI\s0 while the data is being collected, to avoid too much memory being used by storing profile data for many different \s-1SQL\s0 statement. See DBI::Profile. .ie n .SS "$copy = $prof\->\fBclone()\fP;" .el .SS "\f(CW$copy\fP = \f(CW$prof\fP\->\fBclone()\fP;" .IX Subsection "$copy = $prof->clone();" Clone a profile data set creating a new object. .ie n .SS "$header = $prof\->\fBheader()\fP;" .el .SS "\f(CW$header\fP = \f(CW$prof\fP\->\fBheader()\fP;" .IX Subsection "$header = $prof->header();" Returns a reference to a hash of header values. These are the key value pairs included in the header section of the DBI::ProfileDumper data format. For example: .PP .Vb 4 \& $header = { \& Path => [ \*(Aq!Statement\*(Aq, \*(Aq!MethodName\*(Aq ], \& Program => \*(Aqt/42profile_data.t\*(Aq, \& }; .Ve .PP Note that modifying this hash will modify the header data stored inside the profile object. .ie n .SS "$nodes = $prof\->\fBnodes()\fP" .el .SS "\f(CW$nodes\fP = \f(CW$prof\fP\->\fBnodes()\fP" .IX Subsection "$nodes = $prof->nodes()" Returns a reference the sorted nodes array. Each element in the array is a single record in the data set. The first seven elements are the same as the elements provided by DBI::Profile. After that each key is in a separate element. For example: .PP .Vb 10 \& $nodes = [ \& [ \& 2, # 0, count \& 0.0312958955764771, # 1, total duration \& 0.000490069389343262, # 2, first duration \& 0.000176072120666504, # 3, shortest duration \& 0.00140702724456787, # 4, longest duration \& 1023115819.83019, # 5, time of first event \& 1023115819.86576, # 6, time of last event \& \*(AqSELECT foo FROM bar\*(Aq # 7, key1 \& \*(Aqexecute\*(Aq # 8, key2 \& # 6+N, keyN \& ], \& # ... \& ]; .Ve .PP Note that modifying this array will modify the node data stored inside the profile object. .ie n .SS "$count = $prof\->\fBcount()\fP" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->\fBcount()\fP" .IX Subsection "$count = $prof->count()" Returns the number of items in the profile data set. .ie n .SS "$prof\->sort(field => ""field"")" .el .SS "\f(CW$prof\fP\->sort(field => ``field'')" .IX Subsection "$prof->sort(field => field)" .ie n .SS "$prof\->sort(field => ""field"", reverse => 1)" .el .SS "\f(CW$prof\fP\->sort(field => ``field'', reverse => 1)" .IX Subsection "$prof->sort(field => field, reverse => 1)" Sorts data by the given field. Available fields are: .PP .Vb 4 \& longest \& total \& count \& shortest .Ve .PP The default sort is greatest to smallest, which is the opposite of the normal Perl meaning. This, however, matches the expected behavior of the dbiprof frontend. .ie n .SS "$count = $prof\->exclude(key2 => ""disconnect"")" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->exclude(key2 => ``disconnect'')" .IX Subsection "$count = $prof->exclude(key2 => disconnect)" .ie n .SS "$count = $prof\->exclude(key2 => ""disconnect"", case_sensitive => 1)" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->exclude(key2 => ``disconnect'', case_sensitive => 1)" .IX Subsection "$count = $prof->exclude(key2 => disconnect, case_sensitive => 1)" .ie n .SS "$count = $prof\->exclude(key1 => qr/^SELECT/i)" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->exclude(key1 => qr/^SELECT/i)" .IX Subsection "$count = $prof->exclude(key1 => qr/^SELECT/i)" Removes records from the data set that match the given string or regular expression. This method modifies the data in a permanent fashion \- use \fBclone()\fR first to maintain the original data after \&\fBexclude()\fR. Returns the number of nodes left in the profile data set. .ie n .SS "$count = $prof\->match(key2 => ""disconnect"")" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->match(key2 => ``disconnect'')" .IX Subsection "$count = $prof->match(key2 => disconnect)" .ie n .SS "$count = $prof\->match(key2 => ""disconnect"", case_sensitive => 1)" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->match(key2 => ``disconnect'', case_sensitive => 1)" .IX Subsection "$count = $prof->match(key2 => disconnect, case_sensitive => 1)" .ie n .SS "$count = $prof\->match(key1 => qr/^SELECT/i)" .el .SS "\f(CW$count\fP = \f(CW$prof\fP\->match(key1 => qr/^SELECT/i)" .IX Subsection "$count = $prof->match(key1 => qr/^SELECT/i)" Removes records from the data set that do not match the given string or regular expression. This method modifies the data in a permanent fashion \- use \fBclone()\fR first to maintain the original data after \&\fBmatch()\fR. Returns the number of nodes left in the profile data set. .ie n .SS "$Data = $prof\->\fBData()\fP" .el .SS "\f(CW$Data\fP = \f(CW$prof\fP\->\fBData()\fP" .IX Subsection "$Data = $prof->Data()" Returns the same Data hash structure as seen in DBI::Profile. This structure is not sorted. The \fBnodes()\fR structure probably makes more sense for most analysis. .ie n .SS "$text = $prof\->format($nodes\->[0])" .el .SS "\f(CW$text\fP = \f(CW$prof\fP\->format($nodes\->[0])" .IX Subsection "$text = $prof->format($nodes->[0])" Formats a single node into a human-readable block of text. .ie n .SS "$text = $prof\->report(number => 10)" .el .SS "\f(CW$text\fP = \f(CW$prof\fP\->report(number => 10)" .IX Subsection "$text = $prof->report(number => 10)" Produces a report with the given number of items. .SH "AUTHOR" .IX Header "AUTHOR" Sam Tregar .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2002 Sam Tregar .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself. man/man3/DBD::Gofer::Policy::rush.3pm000044400000006110152462503210012764 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Policy::rush 3" .TH DBD::Gofer::Policy::rush 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Policy::rush \- The 'rush' policy for DBD::Gofer .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=rush", ...) .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`rush\*(C'\fR policy tries to make as few round-trips as possible. It's the opposite end of the policy spectrum to the \f(CW\*(C`pedantic\*(C'\fR policy. .PP Temporary docs: See the source code for list of policies and their defaults. .PP In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/JSON::PP::Boolean.3pm000044400000005367152462503210011470 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::PP::Boolean 3" .TH JSON::PP::Boolean 3 "2021-01-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::PP::Boolean \- dummy module providing JSON::PP::Boolean .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& # do not "use" yourself .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module exists only to provide overload resolution for Storable and similar modules. See \&\s-1JSON::PP\s0 for more info about this class. .SH "AUTHOR" .IX Header "AUTHOR" This idea is from JSON::XS::Boolean written by Marc Lehmann .SH "LICENSE" .IX Header "LICENSE" This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::W32ODBC.3pm000044400000005730152462503210010307 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::W32ODBC 3" .TH DBI::W32ODBC 3 "2013-05-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::W32ODBC \- An experimental DBI emulation layer for Win32::ODBC .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use DBI::W32ODBC; \& \& # apart from the line above everything is just the same as with \& # the real DBI when using a basic driver with few features. .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is an experimental pure perl \s-1DBI\s0 emulation layer for Win32::ODBC .PP If you can improve this code I'd be interested in hearing about it. If you are having trouble using it please respect the fact that it's very experimental. Ideally fix it yourself and send me the details. .SS "Some Things Not Yet Implemented" .IX Subsection "Some Things Not Yet Implemented" .Vb 2 \& Most attributes including PrintError & RaiseError. \& type_info and table_info .Ve .PP Volunteers welcome! man/man3/DBD::mysql.3pm000044400000135641152462503210010451 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::mysql 3" .TH DBD::mysql 3 "2019-01-09" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::mysql \- MySQL driver for the Perl5 Database Interface (DBI) .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use DBI; \& \& my $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; \& my $dbh = DBI\->connect($dsn, $user, $password); \& \& my $sth = $dbh\->prepare( \& \*(AqSELECT id, first_name, last_name FROM authors WHERE last_name = ?\*(Aq) \& or die "prepare statement failed: $dbh\->errstr()"; \& $sth\->execute(\*(AqEggers\*(Aq) or die "execution failed: $dbh\->errstr()"; \& print $sth\->rows . " rows found.\en"; \& while (my $ref = $sth\->fetchrow_hashref()) { \& print "Found a row: id = $ref\->{\*(Aqid\*(Aq}, fn = $ref\->{\*(Aqfirst_name\*(Aq}\en"; \& } \& $sth\->finish; .Ve .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 1 \& #!/usr/bin/perl \& \& use strict; \& use warnings; \& use DBI; \& \& # Connect to the database. \& my $dbh = DBI\->connect("DBI:mysql:database=test;host=localhost", \& "joe", "joe\*(Aqs password", \& {\*(AqRaiseError\*(Aq => 1}); \& \& # Drop table \*(Aqfoo\*(Aq. This may fail, if \*(Aqfoo\*(Aq doesn\*(Aqt exist \& # Thus we put an eval around it. \& eval { $dbh\->do("DROP TABLE foo") }; \& print "Dropping foo failed: $@\en" if $@; \& \& # Create a new table \*(Aqfoo\*(Aq. This must not fail, thus we don\*(Aqt \& # catch errors. \& $dbh\->do("CREATE TABLE foo (id INTEGER, name VARCHAR(20))"); \& \& # INSERT some data into \*(Aqfoo\*(Aq. We are using $dbh\->quote() for \& # quoting the name. \& $dbh\->do("INSERT INTO foo VALUES (1, " . $dbh\->quote("Tim") . ")"); \& \& # same thing, but using placeholders (recommended!) \& $dbh\->do("INSERT INTO foo VALUES (?, ?)", undef, 2, "Jochen"); \& \& # now retrieve data from the table. \& my $sth = $dbh\->prepare("SELECT * FROM foo"); \& $sth\->execute(); \& while (my $ref = $sth\->fetchrow_hashref()) { \& print "Found a row: id = $ref\->{\*(Aqid\*(Aq}, name = $ref\->{\*(Aqname\*(Aq}\en"; \& } \& $sth\->finish(); \& \& # Disconnect from the database. \& $dbh\->disconnect(); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBDBD::mysql\fR is the Perl5 Database Interface driver for the MySQL database. In other words: DBD::mysql is an interface between the Perl programming language and the MySQL programming \s-1API\s0 that comes with the MySQL relational database management system. Most functions provided by this programming \s-1API\s0 are supported. Some rarely used functions are missing, mainly because no-one ever requested them. :\-) .PP In what follows we first discuss the use of DBD::mysql, because this is what you will need the most. For installation, see the separate document DBD::mysql::INSTALL. See \*(L"\s-1EXAMPLE\*(R"\s0 for a simple example above. .PP From perl you activate the interface with the statement .PP .Vb 1 \& use DBI; .Ve .PP After that you can connect to multiple MySQL database servers and send multiple queries to any of them via a simple object oriented interface. Two types of objects are available: database handles and statement handles. Perl returns a database handle to the connect method like so: .PP .Vb 2 \& $dbh = DBI\->connect("DBI:mysql:database=$db;host=$host", \& $user, $password, {RaiseError => 1}); .Ve .PP Once you have connected to a database, you can execute \s-1SQL\s0 statements with: .PP .Vb 3 \& my $query = sprintf("INSERT INTO foo VALUES (%d, %s)", \& $number, $dbh\->quote("name")); \& $dbh\->do($query); .Ve .PP See \s-1DBI\s0 for details on the quote and do methods. An alternative approach is .PP .Vb 2 \& $dbh\->do("INSERT INTO foo VALUES (?, ?)", undef, \& $number, $name); .Ve .PP in which case the quote method is executed automatically. See also the bind_param method in \s-1DBI\s0. See \*(L"\s-1DATABASE HANDLES\*(R"\s0 below for more details on database handles. .PP If you want to retrieve results, you need to create a so-called statement handle with: .PP .Vb 2 \& $sth = $dbh\->prepare("SELECT * FROM $table"); \& $sth\->execute(); .Ve .PP This statement handle can be used for multiple things. First of all you can retrieve a row of data: .PP .Vb 1 \& my $row = $sth\->fetchrow_hashref(); .Ve .PP If your table has columns \s-1ID\s0 and \s-1NAME,\s0 then \f(CW$row\fR will be hash ref with keys \s-1ID\s0 and \s-1NAME.\s0 See \*(L"\s-1STATEMENT HANDLES\*(R"\s0 below for more details on statement handles. .PP But now for a more formal approach: .SS "Class Methods" .IX Subsection "Class Methods" .IP "\fBconnect\fR" 4 .IX Item "connect" .Vb 1 \& use DBI; \& \& $dsn = "DBI:mysql:$database"; \& $dsn = "DBI:mysql:database=$database;host=$hostname"; \& $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port"; \& \& $dbh = DBI\->connect($dsn, $user, $password); .Ve .Sp The \f(CW\*(C`database\*(C'\fR is not a required attribute, but please note that MySQL has no such thing as a default database. If you don't specify the database at connection time your active database will be null and you'd need to prefix your tables with the database name; i.e. '\s-1SELECT\s0 * \s-1FROM\s0 mydb.mytable'. .Sp This is similar to the behavior of the mysql command line client. Also, \&'\s-1SELECT \fBDATABASE\s0()\fR' will return the current database active for the handle. .RS 4 .IP "host" 4 .IX Item "host" .PD 0 .IP "port" 4 .IX Item "port" .PD The hostname, if not specified or specified as '' or 'localhost', will default to a MySQL server running on the local machine using the default for the \s-1UNIX\s0 socket. To connect to a MySQL server on the local machine via \s-1TCP,\s0 you must specify the loopback \s-1IP\s0 address (127.0.0.1) as the host. .Sp Should the MySQL server be running on a non-standard port number, you may explicitly state the port number to connect to in the \f(CW\*(C`hostname\*(C'\fR argument, by concatenating the \fIhostname\fR and \fIport number\fR together separated by a colon ( \f(CW\*(C`:\*(C'\fR ) character or by using the \f(CW\*(C`port\*(C'\fR argument. .Sp To connect to a MySQL server on localhost using \s-1TCP/IP,\s0 you must specify the hostname as 127.0.0.1 (with the optional port). .Sp When connecting to a MySQL Server with IPv6, a bracketed IPv6 address should be used. Example \s-1DSN:\s0 .Sp .Vb 1 \& my $dsn = "DBI:mysql:;host=[1a12:2800:6f2:85::f20:8cf];port=3306"; .Ve .IP "mysql_client_found_rows" 4 .IX Item "mysql_client_found_rows" Enables (\s-1TRUE\s0 value) or disables (\s-1FALSE\s0 value) the flag \s-1CLIENT_FOUND_ROWS\s0 while connecting to the MySQL server. This has a somewhat funny effect: Without mysql_client_found_rows, if you perform a query like .Sp .Vb 1 \& UPDATE $table SET id = 1 WHERE id = 1; .Ve .Sp then the MySQL engine will always return 0, because no rows have changed. With mysql_client_found_rows however, it will return the number of rows that have an id 1, as some people are expecting. (At least for compatibility to other engines.) .IP "mysql_compression" 4 .IX Item "mysql_compression" If your \s-1DSN\s0 contains the option \*(L"mysql_compression=1\*(R", then the communication between client and server will be compressed. .IP "mysql_connect_timeout" 4 .IX Item "mysql_connect_timeout" If your \s-1DSN\s0 contains the option \*(L"mysql_connect_timeout=##\*(R", the connect request to the server will timeout if it has not been successful after the given number of seconds. .IP "mysql_write_timeout" 4 .IX Item "mysql_write_timeout" If your \s-1DSN\s0 contains the option \*(L"mysql_write_timeout=##\*(R", the write operation to the server will timeout if it has not been successful after the given number of seconds. .IP "mysql_read_timeout" 4 .IX Item "mysql_read_timeout" If your \s-1DSN\s0 contains the option \*(L"mysql_read_timeout=##\*(R", the read operation to the server will timeout if it has not been successful after the given number of seconds. .IP "mysql_init_command" 4 .IX Item "mysql_init_command" If your \s-1DSN\s0 contains the option \*(L"mysql_init_command=##\*(R", then this \s-1SQL\s0 statement is executed when connecting to the MySQL server. It is automatically re-executed if reconnection occurs. .IP "mysql_skip_secure_auth" 4 .IX Item "mysql_skip_secure_auth" This option is for older mysql databases that don't have secure auth set. .IP "mysql_read_default_file" 4 .IX Item "mysql_read_default_file" .PD 0 .IP "mysql_read_default_group" 4 .IX Item "mysql_read_default_group" .PD These options can be used to read a config file like /etc/my.cnf or ~/.my.cnf. By default MySQL's C client library doesn't use any config files unlike the client programs (mysql, mysqladmin, ...) that do, but outside of the C client library. Thus you need to explicitly request reading a config file, as in .Sp .Vb 2 \& $dsn = "DBI:mysql:test;mysql_read_default_file=/home/joe/my.cnf"; \& $dbh = DBI\->connect($dsn, $user, $password) .Ve .Sp The option mysql_read_default_group can be used to specify the default group in the config file: Usually this is the \fIclient\fR group, but see the following example: .Sp .Vb 2 \& [client] \& host=localhost \& \& [perl] \& host=perlhost .Ve .Sp (Note the order of the entries! The example won't work, if you reverse the [client] and [perl] sections!) .Sp If you read this config file, then you'll be typically connected to \&\fIlocalhost\fR. However, by using .Sp .Vb 3 \& $dsn = "DBI:mysql:test;mysql_read_default_group=perl;" \& . "mysql_read_default_file=/home/joe/my.cnf"; \& $dbh = DBI\->connect($dsn, $user, $password); .Ve .Sp you'll be connected to \fIperlhost\fR. Note that if you specify a default group and do not specify a file, then the default config files will all be read. See the documentation of the C function \fBmysql_options()\fR for details. .IP "mysql_socket" 4 .IX Item "mysql_socket" It is possible to choose the Unix socket that is used for connecting to the server. This is done, for example, with .Sp .Vb 1 \& mysql_socket=/dev/mysql .Ve .Sp Usually there's no need for this option, unless you are using another location for the socket than that built into the client. .IP "mysql_ssl" 4 .IX Item "mysql_ssl" A true value turns on the \s-1CLIENT_SSL\s0 flag when connecting to the MySQL server and enforce \s-1SSL\s0 encryption. A false value (which is default) disable \s-1SSL\s0 encryption with the MySQL server. .Sp When enabling \s-1SSL\s0 encryption you should set also other \s-1SSL\s0 options, at least mysql_ssl_ca_file or mysql_ssl_ca_path. .Sp .Vb 1 \& mysql_ssl=1 mysql_ssl_verify_server_cert=1 mysql_ssl_ca_file=/path/to/ca_cert.pem .Ve .Sp This means that your communication with the server will be encrypted. .Sp Please note that this can only work if you enabled \s-1SSL\s0 when compiling DBD::mysql; this is the default starting version 4.034. See DBD::mysql::INSTALL for more details. .IP "mysql_ssl_ca_file" 4 .IX Item "mysql_ssl_ca_file" The path to a file in \s-1PEM\s0 format that contains a list of trusted \s-1SSL\s0 certificate authorities. .Sp When set MySQL server certificate is checked that it is signed by some \&\s-1CA\s0 certificate in the list. Common Name value is not verified unless \&\f(CW\*(C`mysql_ssl_verify_server_cert\*(C'\fR is enabled. .IP "mysql_ssl_ca_path" 4 .IX Item "mysql_ssl_ca_path" The path to a directory that contains trusted \s-1SSL\s0 certificate authority certificates in \s-1PEM\s0 format. .Sp When set MySQL server certificate is checked that it is signed by some \&\s-1CA\s0 certificate in the list. Common Name value is not verified unless \&\f(CW\*(C`mysql_ssl_verify_server_cert\*(C'\fR is enabled. .Sp Please note that this option is supported only if your MySQL client was compiled with OpenSSL library, and not with default yaSSL library. .IP "mysql_ssl_verify_server_cert" 4 .IX Item "mysql_ssl_verify_server_cert" Checks the server's Common Name value in the certificate that the server sends to the client. The client verifies that name against the host name the client uses for connecting to the server, and the connection fails if there is a mismatch. For encrypted connections, this option helps prevent man-in-the-middle attacks. .Sp Verification of the host name is disabled by default. .IP "mysql_ssl_client_key" 4 .IX Item "mysql_ssl_client_key" The name of the \s-1SSL\s0 key file in \s-1PEM\s0 format to use for establishing a secure connection. .IP "mysql_ssl_client_cert" 4 .IX Item "mysql_ssl_client_cert" The name of the \s-1SSL\s0 certificate file in \s-1PEM\s0 format to use for establishing a secure connection. .IP "mysql_ssl_cipher" 4 .IX Item "mysql_ssl_cipher" A list of permissible ciphers to use for connection encryption. If no cipher in the list is supported, encrypted connections will not work. .Sp .Vb 2 \& mysql_ssl_cipher=AES128\-SHA \& mysql_ssl_cipher=DHE\-RSA\-AES256\-SHA:AES128\-SHA .Ve .IP "mysql_ssl_optional" 4 .IX Item "mysql_ssl_optional" Setting \f(CW\*(C`mysql_ssl_optional\*(C'\fR to true disables strict \s-1SSL\s0 enforcement and makes \s-1SSL\s0 connection optional. This option opens security hole for man-in-the-middle attacks. Default value is false which means that \f(CW\*(C`mysql_ssl\*(C'\fR set to true enforce \s-1SSL\s0 encryption. .Sp This option was introduced in 4.043 version of DBD::mysql. Due to The \s-1BACKRONYM\s0 and The Riddle vulnerabilities in libmysqlclient library, enforcement of \s-1SSL\s0 encryption was not possbile and therefore \f(CW\*(C`mysql_ssl_optional=1\*(C'\fR was effectively set for all DBD::mysql versions prior to 4.043. Starting with 4.043, DBD::mysql with \f(CW\*(C`mysql_ssl=1\*(C'\fR could refuse connection to MySQL server if underlaying libmysqlclient library is vulnerable. Option \f(CW\*(C`mysql_ssl_optional\*(C'\fR can be used to make \s-1SSL\s0 connection vulnerable. .IP "mysql_server_pubkey" 4 .IX Item "mysql_server_pubkey" Path to the \s-1RSA\s0 public key of the server. This is used for the sha256_password and caching_sha2_password authentication plugins. .IP "mysql_get_server_pubkey" 4 .IX Item "mysql_get_server_pubkey" Setting \f(CW\*(C`mysql_get_server_pubkey\*(C'\fR to true requests the public \&\s-1RSA\s0 key of the server. .IP "mysql_local_infile" 4 .IX Item "mysql_local_infile" The \s-1LOCAL\s0 capability for \s-1LOAD DATA\s0 may be disabled in the MySQL client library by default. If your \s-1DSN\s0 contains the option \&\*(L"mysql_local_infile=1\*(R", \s-1LOAD DATA LOCAL\s0 will be enabled. (However, this option is *ineffective* if the server has also been configured to disallow \s-1LOCAL.\s0) .IP "mysql_multi_statements" 4 .IX Item "mysql_multi_statements" Support for multiple statements separated by a semicolon (;) may be enabled by using this option. Enabling this option may cause problems if server-side prepared statements are also enabled. .IP "mysql_server_prepare" 4 .IX Item "mysql_server_prepare" This option is used to enable server side prepared statements. .Sp To use server side prepared statements, all you need to do is set the variable mysql_server_prepare in the connect: .Sp .Vb 6 \& $dbh = DBI\->connect( \& "DBI:mysql:database=test;host=localhost;mysql_server_prepare=1", \& "", \& "", \& { RaiseError => 1, AutoCommit => 1 } \& ); .Ve .Sp or: .Sp .Vb 6 \& $dbh = DBI\->connect( \& "DBI:mysql:database=test;host=localhost", \& "", \& "", \& { RaiseError => 1, AutoCommit => 1, mysql_server_prepare => 1 } \& ); .Ve .Sp There are many benefits to using server side prepare statements, mostly if you are performing many inserts because of that fact that a single statement is prepared to accept multiple insert values. .Sp To make sure that the 'make test' step tests whether server prepare works, you just need to export the env variable \s-1MYSQL_SERVER_PREPARE:\s0 .Sp .Vb 1 \& export MYSQL_SERVER_PREPARE=1 .Ve .Sp Please note that mysql server cannot prepare or execute some prepared statements. In this case DBD::mysql fallbacks to normal non-prepared statement and tries again. .IP "mysql_server_prepare_disable_fallback" 4 .IX Item "mysql_server_prepare_disable_fallback" This option disable fallback to normal non-prepared statement when mysql server does not support execution of current statement as prepared. .Sp Useful when you want to be sure that statement is going to be executed as server side prepared. Error message and code in case of failure is propagated back to \s-1DBI.\s0 .IP "mysql_embedded_options" 4 .IX Item "mysql_embedded_options" The option can be used to pass 'command\-line' options to embedded server. .Sp Example: .Sp .Vb 3 \& use DBI; \& $testdsn="DBI:mysqlEmb:database=test;mysql_embedded_options=\-\-help,\-\-verbose"; \& $dbh = DBI\->connect($testdsn,"a","b"); .Ve .Sp This would cause the command line help to the embedded MySQL server library to be printed. .IP "mysql_embedded_groups" 4 .IX Item "mysql_embedded_groups" The option can be used to specify the groups in the config file(\fImy.cnf\fR) which will be used to get options for embedded server. If not specified [server] and [embedded] groups will be used. .Sp Example: .Sp .Vb 1 \& $testdsn="DBI:mysqlEmb:database=test;mysql_embedded_groups=embedded_server,common"; .Ve .IP "mysql_conn_attrs" 4 .IX Item "mysql_conn_attrs" The option is a hash of attribute names and values which can be used to send custom connection attributes to the server. Some attributes like \&'_os', '_platform', '_client_name' and '_client_version' are added by libmysqlclient and 'program_name' is added by DBD::mysql. .Sp You can then later read these attributes from the performance schema tables which can be quite helpful for profiling your database or creating statistics. You'll have to use a MySQL 5.6 server and libmysqlclient or newer to leverage this feature. .Sp .Vb 7 \& my $dbh= DBI\->connect($dsn, $user, $password, \& { AutoCommit => 0, \& mysql_conn_attrs => { \& foo => \*(Aqbar\*(Aq, \& wiz => \*(Aqbang\*(Aq \& }, \& }); .Ve .Sp Now you can select the results from the performance schema tables. You can do this in the same session, but also afterwards. It can be very useful to answer questions like 'which script sent this query?'. .Sp .Vb 4 \& my $results = $dbh\->selectall_hashref( \& \*(AqSELECT * FROM performance_schema.session_connect_attrs\*(Aq, \& \*(AqATTR_NAME\*(Aq \& ); .Ve .Sp This returns: .Sp .Vb 10 \& $result = { \& \*(Aqfoo\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aqbar\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aqfoo\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq6\*(Aq \& }, \& \*(Aqwiz\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aqbang\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aqwiz\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq3\*(Aq \& }, \& \*(Aqprogram_name\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aq./foo.pl\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aqprogram_name\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq5\*(Aq \& }, \& \*(Aq_client_name\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aqlibmysql\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aq_client_name\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq1\*(Aq \& }, \& \*(Aq_client_version\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aq5.6.24\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aq_client_version\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq7\*(Aq \& }, \& \*(Aq_os\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aqosx10.8\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aq_os\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq0\*(Aq \& }, \& \*(Aq_pid\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aq59860\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aq_pid\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq2\*(Aq \& }, \& \*(Aq_platform\*(Aq => { \& \*(AqATTR_VALUE\*(Aq => \*(Aqx86_64\*(Aq, \& \*(AqPROCESSLIST_ID\*(Aq => \*(Aq3\*(Aq, \& \*(AqATTR_NAME\*(Aq => \*(Aq_platform\*(Aq, \& \*(AqORDINAL_POSITION\*(Aq => \*(Aq4\*(Aq \& } \& }; .Ve .RE .RS 4 .RE .SS "Private MetaData Methods" .IX Subsection "Private MetaData Methods" .IP "\fBListDBs\fR" 4 .IX Item "ListDBs" .Vb 4 \& my $drh = DBI\->install_driver("mysql"); \& @dbs = $drh\->func("$hostname:$port", \*(Aq_ListDBs\*(Aq); \& @dbs = $drh\->func($hostname, $port, \*(Aq_ListDBs\*(Aq); \& @dbs = $dbh\->func(\*(Aq_ListDBs\*(Aq); .Ve .Sp Returns a list of all databases managed by the MySQL server running on \f(CW$hostname\fR, port \f(CW$port\fR. This is a legacy method. Instead, you should use the portable method .Sp .Vb 1 \& @dbs = DBI\->data_sources("mysql"); .Ve .SH "DATABASE HANDLES" .IX Header "DATABASE HANDLES" The DBD::mysql driver supports the following attributes of database handles (read only): .PP .Vb 9 \& $errno = $dbh\->{\*(Aqmysql_errno\*(Aq}; \& $error = $dbh\->{\*(Aqmysql_error\*(Aq}; \& $info = $dbh\->{\*(Aqmysql_hostinfo\*(Aq}; \& $info = $dbh\->{\*(Aqmysql_info\*(Aq}; \& $insertid = $dbh\->{\*(Aqmysql_insertid\*(Aq}; \& $info = $dbh\->{\*(Aqmysql_protoinfo\*(Aq}; \& $info = $dbh\->{\*(Aqmysql_serverinfo\*(Aq}; \& $info = $dbh\->{\*(Aqmysql_stat\*(Aq}; \& $threadId = $dbh\->{\*(Aqmysql_thread_id\*(Aq}; .Ve .PP These correspond to \fBmysql_errno()\fR, \fBmysql_error()\fR, \fBmysql_get_host_info()\fR, \&\fBmysql_info()\fR, \fBmysql_insert_id()\fR, \fBmysql_get_proto_info()\fR, \&\fBmysql_get_server_info()\fR, \fBmysql_stat()\fR and \fBmysql_thread_id()\fR, respectively. .IP "mysql_clientinfo" 2 .IX Item "mysql_clientinfo" List information of the MySQL client library that DBD::mysql was built against: .Sp .Vb 1 \& print "$dbh\->{mysql_clientinfo}\en"; \& \& 5.2.0\-MariaDB .Ve .IP "mysql_clientversion" 2 .IX Item "mysql_clientversion" .Vb 1 \& print "$dbh\->{mysql_clientversion}\en"; \& \& 50200 .Ve .IP "mysql_serverversion" 2 .IX Item "mysql_serverversion" .Vb 1 \& print "$dbh\->{mysql_serverversion}\en"; \& \& 50200 .Ve .IP "mysql_dbd_stats" 2 .IX Item "mysql_dbd_stats" .Vb 1 \& $info_hashref = $dbh\->{mysql_dbd_stats}; .Ve .Sp DBD::mysql keeps track of some statistics in the mysql_dbd_stats attribute. The following stats are being maintained: .RS 2 .IP "auto_reconnects_ok" 8 .IX Item "auto_reconnects_ok" The number of times that DBD::mysql successfully reconnected to the mysql server. .IP "auto_reconnects_failed" 8 .IX Item "auto_reconnects_failed" The number of times that DBD::mysql tried to reconnect to mysql but failed. .RE .RS 2 .RE .PP The DBD::mysql driver also supports the following attributes of database handles (read/write): .IP "mysql_auto_reconnect" 4 .IX Item "mysql_auto_reconnect" This attribute determines whether DBD::mysql will automatically reconnect to mysql if the connection be lost. This feature defaults to off; however, if either the \s-1GATEWAY_INTERFACE\s0 or \s-1MOD_PERL\s0 environment variable is set, DBD::mysql will turn mysql_auto_reconnect on. Setting mysql_auto_reconnect to on is not advised if 'lock tables' is used because if DBD::mysql reconnect to mysql all table locks will be lost. This attribute is ignored when AutoCommit is turned off, and when AutoCommit is turned off, DBD::mysql will not automatically reconnect to the server. .Sp It is also possible to set the default value of the \f(CW\*(C`mysql_auto_reconnect\*(C'\fR attribute for the \f(CW$dbh\fR by passing it in the \f(CW\*(C`\e%attr\*(C'\fR hash for \f(CW\*(C`DBI\-\*(C'\fRconnect>. .Sp .Vb 1 \& $dbh\->{mysql_auto_reconnect} = 1; .Ve .Sp or .Sp .Vb 3 \& my $dbh = DBI\->connect($dsn, $user, $password, { \& mysql_auto_reconnect => 1, \& }); .Ve .Sp Note that if you are using a module or framework that performs reconnections for you (for example DBIx::Connector in fixup mode), this value must be set to 0. .IP "mysql_use_result" 4 .IX Item "mysql_use_result" This attribute forces the driver to use mysql_use_result rather than mysql_store_result. The former is faster and less memory consuming, but tends to block other processes. mysql_store_result is the default due to that fact storing the result is expected behavior with most applications. .Sp It is possible to set the default value of the \f(CW\*(C`mysql_use_result\*(C'\fR attribute for the \f(CW$dbh\fR via the \s-1DSN:\s0 .Sp .Vb 1 \& $dbh = DBI\->connect("DBI:mysql:test;mysql_use_result=1", "root", ""); .Ve .Sp You can also set it after creation of the database handle: .Sp .Vb 2 \& $dbh\->{mysql_use_result} = 0; # disable \& $dbh\->{mysql_use_result} = 1; # enable .Ve .Sp You can also set or unset the \f(CW\*(C`mysql_use_result\*(C'\fR setting on your statement handle, when creating the statement handle or after it has been created. See \*(L"\s-1STATEMENT HANDLES\*(R"\s0. .IP "mysql_enable_utf8" 4 .IX Item "mysql_enable_utf8" This attribute determines whether DBD::mysql should assume strings stored in the database are utf8. This feature defaults to off. .Sp When set, a data retrieved from a textual column type (char, varchar, etc) will have the \s-1UTF\-8\s0 flag turned on if necessary. This enables character semantics on that string. You will also need to ensure that your database / table / column is configured to use \s-1UTF8.\s0 See for more information the chapter on character set support in the MySQL manual: .Sp Additionally, turning on this flag tells MySQL that incoming data should be treated as \s-1UTF\-8.\s0 This will only take effect if used as part of the call to \fBconnect()\fR. If you turn the flag on after connecting, you will need to issue the command \f(CW\*(C`SET NAMES utf8\*(C'\fR to get the same effect. .IP "mysql_enable_utf8mb4" 4 .IX Item "mysql_enable_utf8mb4" This is similar to mysql_enable_utf8, but is capable of handling 4\-byte \&\s-1UTF\-8\s0 characters. .IP "mysql_bind_type_guessing" 4 .IX Item "mysql_bind_type_guessing" This attribute causes the driver (emulated prepare statements) to attempt to guess if a value being bound is a numeric value, and if so, doesn't quote the value. This was created by Dragonchild and is one way to deal with the performance issue of using quotes in a statement that is inserting or updating a large numeric value. This was previously called \&\f(CW\*(C`unsafe_bind_type_guessing\*(C'\fR because it is experimental. I have successfully run the full test suite with this option turned on, the name can now be simply \f(CW\*(C`mysql_bind_type_guessing\*(C'\fR. .Sp \&\s-1CAVEAT:\s0 Even though you can insert an integer value into a character column, if this column is indexed, if you query that column with the integer value not being quoted, it will not use the index: .Sp .Vb 10 \& MariaDB [test]> explain select * from test where value0 = \*(Aq3\*(Aq \eG \& *************************** 1. row *************************** \& id: 1 \& select_type: SIMPLE \& table: test \& type: ref \& possible_keys: value0 \& key: value0 \& key_len: 13 \& ref: const \& rows: 1 \& Extra: Using index condition \& 1 row in set (0.00 sec) \& \& MariaDB [test]> explain select * from test where value0 = 3 \& \-> \eG \& *************************** 1. row *************************** \& id: 1 \& select_type: SIMPLE \& table: test \& type: ALL \& possible_keys: value0 \& key: NULL \& key_len: NULL \& ref: NULL \& rows: 6 \& Extra: Using where \& 1 row in set (0.00 sec) .Ve .Sp See bug: https://rt.cpan.org/Ticket/Display.html?id=43822 .Sp \&\f(CW\*(C`mysql_bind_type_guessing\*(C'\fR can be turned on via .Sp .Vb 1 \& \- through DSN \& \& my $dbh= DBI\->connect(\*(AqDBI:mysql:test\*(Aq, \*(Aqusername\*(Aq, \*(Aqpass\*(Aq, \& { mysql_bind_type_guessing => 1}) \& \& \- OR after handle creation \& \& $dbh\->{mysql_bind_type_guessing} = 1; .Ve .IP "mysql_bind_comment_placeholders" 4 .IX Item "mysql_bind_comment_placeholders" This attribute causes the driver (emulated prepare statements) will cause any placeholders in comments to be bound. This is not correct prepared statement behavior, but some developers have come to depend on this behavior, so I have made it available in 4.015 .IP "mysql_no_autocommit_cmd" 4 .IX Item "mysql_no_autocommit_cmd" This attribute causes the driver to not issue 'set autocommit' either through explicit or using \fBmysql_autocommit()\fR. This is particularly useful in the case of using MySQL Proxy. .Sp See the bug report: .Sp https://rt.cpan.org/Public/Bug/Display.html?id=46308 .Sp \&\f(CW\*(C`mysql_no_autocommit_cmd\*(C'\fR can be turned on when creating the database handle: .Sp .Vb 2 \& my $dbh = DBI\->connect(\*(AqDBI:mysql:test\*(Aq, \*(Aqusername\*(Aq, \*(Aqpass\*(Aq, \& { mysql_no_autocommit_cmd => 1}); .Ve .Sp or using an existing database handle: .Sp .Vb 1 \& $dbh\->{mysql_no_autocommit_cmd} = 1; .Ve .IP "ping" 4 .IX Item "ping" This can be used to send a ping to the server. .Sp .Vb 1 \& $rc = $dbh\->ping(); .Ve .SH "STATEMENT HANDLES" .IX Header "STATEMENT HANDLES" The statement handles of DBD::mysql support a number of attributes. You access these by using, for example, .PP .Vb 1 \& my $numFields = $sth\->{NUM_OF_FIELDS}; .Ve .PP Note, that most attributes are valid only after a successful \fIexecute\fR. An \f(CW\*(C`undef\*(C'\fR value will returned otherwise. The most important exception is the \f(CW\*(C`mysql_use_result\*(C'\fR attribute, which forces the driver to use mysql_use_result rather than mysql_store_result. The former is faster and less memory consuming, but tends to block other processes. (That's why mysql_store_result is the default.) .PP To set the \f(CW\*(C`mysql_use_result\*(C'\fR attribute, use either of the following: .PP .Vb 1 \& my $sth = $dbh\->prepare("QUERY", { mysql_use_result => 1}); .Ve .PP or .PP .Vb 2 \& my $sth = $dbh\->prepare($sql); \& $sth\->{mysql_use_result} = 1; .Ve .PP Column dependent attributes, for example \fI\s-1NAME\s0\fR, the column names, are returned as a reference to an array. The array indices are corresponding to the indices of the arrays returned by \fIfetchrow\fR and similar methods. For example the following code will print a header of table names together with all rows: .PP .Vb 2 \& my $sth = $dbh\->prepare("SELECT * FROM $table") || \& die "Error:" . $dbh\->errstr . "\en"; \& \& $sth\->execute || die "Error:" . $sth\->errstr . "\en"; \& \& my $names = $sth\->{NAME}; \& my $numFields = $sth\->{\*(AqNUM_OF_FIELDS\*(Aq} \- 1; \& for my $i ( 0..$numFields ) { \& printf("%s%s", $i ? "," : "", $$names[$i]); \& } \& print "\en"; \& while (my $ref = $sth\->fetchrow_arrayref) { \& for my $i ( 0..$numFields ) { \& printf("%s%s", $i ? "," : "", $$ref[$i]); \& } \& print "\en"; \& } .Ve .PP For portable applications you should restrict yourself to attributes with capitalized or mixed case names. Lower case attribute names are private to DBD::mysql. The attribute list includes: .IP "ChopBlanks" 4 .IX Item "ChopBlanks" this attribute determines whether a \fIfetchrow\fR will chop preceding and trailing blanks off the column values. Chopping blanks does not have impact on the \fImax_length\fR attribute. .IP "mysql_gtids" 4 .IX Item "mysql_gtids" Returns \s-1GTID\s0(s) if \s-1GTID\s0 session tracking is ensabled in the server via session_track_gtids. .IP "mysql_insertid" 4 .IX Item "mysql_insertid" If the statement you executed performs an \s-1INSERT,\s0 and there is an \s-1AUTO_INCREMENT\s0 column in the table you inserted in, this attribute holds the value stored into the \s-1AUTO_INCREMENT\s0 column, if that value is automatically generated, by storing \s-1NULL\s0 or 0 or was specified as an explicit value. .Sp Typically, you'd access the value via \f(CW$sth\fR\->{mysql_insertid}. The value can also be accessed via \f(CW$dbh\fR\->{mysql_insertid} but this can easily produce incorrect results in case one database handle is shared. .IP "mysql_is_blob" 4 .IX Item "mysql_is_blob" Reference to an array of boolean values; \s-1TRUE\s0 indicates, that the respective column is a blob. This attribute is valid for MySQL only. .IP "mysql_is_key" 4 .IX Item "mysql_is_key" Reference to an array of boolean values; \s-1TRUE\s0 indicates, that the respective column is a key. This is valid for MySQL only. .IP "mysql_is_num" 4 .IX Item "mysql_is_num" Reference to an array of boolean values; \s-1TRUE\s0 indicates, that the respective column contains numeric values. .IP "mysql_is_pri_key" 4 .IX Item "mysql_is_pri_key" Reference to an array of boolean values; \s-1TRUE\s0 indicates, that the respective column is a primary key. .IP "mysql_is_auto_increment" 4 .IX Item "mysql_is_auto_increment" Reference to an array of boolean values; \s-1TRUE\s0 indicates that the respective column is an \s-1AUTO_INCREMENT\s0 column. This is only valid for MySQL. .IP "mysql_length" 4 .IX Item "mysql_length" .PD 0 .IP "mysql_max_length" 4 .IX Item "mysql_max_length" .PD A reference to an array of maximum column sizes. The \fImax_length\fR is the maximum physically present in the result table, \fIlength\fR gives the theoretically possible maximum. \fImax_length\fR is valid for MySQL only. .IP "\s-1NAME\s0" 4 .IX Item "NAME" A reference to an array of column names. .IP "\s-1NULLABLE\s0" 4 .IX Item "NULLABLE" A reference to an array of boolean values; \s-1TRUE\s0 indicates that this column may contain \s-1NULL\s0's. .IP "\s-1NUM_OF_FIELDS\s0" 4 .IX Item "NUM_OF_FIELDS" Number of fields returned by a \fI\s-1SELECT\s0\fR or \fI\s-1LISTFIELDS\s0\fR statement. You may use this for checking whether a statement returned a result: A zero value indicates a non-SELECT statement like \fI\s-1INSERT\s0\fR, \&\fI\s-1DELETE\s0\fR or \fI\s-1UPDATE\s0\fR. .IP "mysql_table" 4 .IX Item "mysql_table" A reference to an array of table names, useful in a \fI\s-1JOIN\s0\fR result. .IP "\s-1TYPE\s0" 4 .IX Item "TYPE" A reference to an array of column types. The engine's native column types are mapped to portable types like \s-1\fBDBI::SQL_INTEGER\s0()\fR or \&\s-1\fBDBI::SQL_VARCHAR\s0()\fR, as good as possible. Not all native types have a meaningful equivalent, for example DBD::mysql::FIELD_TYPE_INTERVAL is mapped to \s-1\fBDBI::SQL_VARCHAR\s0()\fR. If you need the native column types, use \fImysql_type\fR. See below. .IP "mysql_type" 4 .IX Item "mysql_type" A reference to an array of MySQL's native column types, for example \&\fBDBD::mysql::FIELD_TYPE_SHORT()\fR or \fBDBD::mysql::FIELD_TYPE_STRING()\fR. Use the \fI\s-1TYPE\s0\fR attribute, if you want portable types like \&\s-1\fBDBI::SQL_SMALLINT\s0()\fR or \s-1\fBDBI::SQL_VARCHAR\s0()\fR. .IP "mysql_type_name" 4 .IX Item "mysql_type_name" Similar to mysql, but type names and not numbers are returned. Whenever possible, the \s-1ANSI SQL\s0 name is preferred. .IP "mysql_warning_count" 4 .IX Item "mysql_warning_count" The number of warnings generated during execution of the \s-1SQL\s0 statement. This attribute is available on both statement handles and database handles. .SH "TRANSACTION SUPPORT" .IX Header "TRANSACTION SUPPORT" The transaction support works as follows: .IP "\(bu" 4 By default AutoCommit mode is on, following the \s-1DBI\s0 specifications. .IP "\(bu" 4 If you execute .Sp .Vb 1 \& $dbh\->{AutoCommit} = 0; .Ve .Sp or .Sp .Vb 1 \& $dbh\->{AutoCommit} = 1; .Ve .Sp then the driver will set the MySQL server variable autocommit to 0 or 1, respectively. Switching from 0 to 1 will also issue a \s-1COMMIT,\s0 following the \s-1DBI\s0 specifications. .IP "\(bu" 4 The methods .Sp .Vb 2 \& $dbh\->rollback(); \& $dbh\->commit(); .Ve .Sp will issue the commands \s-1ROLLBACK\s0 and \s-1COMMIT,\s0 respectively. A \&\s-1ROLLBACK\s0 will also be issued if AutoCommit mode is off and the database handles \s-1DESTROY\s0 method is called. Again, this is following the \s-1DBI\s0 specifications. .PP Given the above, you should note the following: .IP "\(bu" 4 You should never change the server variable autocommit manually, unless you are ignoring \s-1DBI\s0's transaction support. .IP "\(bu" 4 Switching AutoCommit mode from on to off or vice versa may fail. You should always check for errors when changing AutoCommit mode. The suggested way of doing so is using the \s-1DBI\s0 flag RaiseError. If you don't like RaiseError, you have to use code like the following: .Sp .Vb 4 \& $dbh\->{AutoCommit} = 0; \& if ($dbh\->{AutoCommit}) { \& # An error occurred! \& } .Ve .IP "\(bu" 4 If you detect an error while changing the AutoCommit mode, you should no longer use the database handle. In other words, you should disconnect and reconnect again, because the transaction mode is unpredictable. Alternatively you may verify the transaction mode by checking the value of the server variable autocommit. However, such behaviour isn't portable. .IP "\(bu" 4 DBD::mysql has a \*(L"reconnect\*(R" feature that handles the so-called MySQL \*(L"morning bug\*(R": If the server has disconnected, most probably due to a timeout, then by default the driver will reconnect and attempt to execute the same \s-1SQL\s0 statement again. However, this behaviour is disabled when AutoCommit is off: Otherwise the transaction state would be completely unpredictable after a reconnect. .IP "\(bu" 4 The \*(L"reconnect\*(R" feature of DBD::mysql can be toggled by using the mysql_auto_reconnect attribute. This behaviour should be turned off in code that uses \s-1LOCK TABLE\s0 because if the database server time out and DBD::mysql reconnect, table locks will be lost without any indication of such loss. .SH "MULTIPLE RESULT SETS" .IX Header "MULTIPLE RESULT SETS" DBD::mysql supports multiple result sets, thanks to Guy Harrison! .PP The basic usage of multiple result sets is .PP .Vb 7 \& do \& { \& while (@row = $sth\->fetchrow_array()) \& { \& do stuff; \& } \& } while ($sth\->more_results) .Ve .PP An example would be: .PP .Vb 1 \& $dbh\->do("drop procedure if exists someproc") or print $DBI::errstr; \& \& $dbh\->do("create procedure someproc() deterministic \& begin \& declare a,b,c,d int; \& set a=1; \& set b=2; \& set c=3; \& set d=4; \& select a, b, c, d; \& select d, c, b, a; \& select b, a, c, d; \& select c, b, d, a; \& end") or print $DBI::errstr; \& \& $sth=$dbh\->prepare(\*(Aqcall someproc()\*(Aq) || \& die $DBI::err.": ".$DBI::errstr; \& \& $sth\->execute || die DBI::err.": ".$DBI::errstr; $rowset=0; \& do { \& print "\enRowset ".++$i."\en\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\en\en"; \& foreach $colno (0..$sth\->{NUM_OF_FIELDS}\-1) { \& print $sth\->{NAME}\->[$colno]."\et"; \& } \& print "\en"; \& while (@row= $sth\->fetchrow_array()) { \& foreach $field (0..$#row) { \& print $row[$field]."\et"; \& } \& print "\en"; \& } \& } until (!$sth\->more_results) .Ve .SS "Issues with multiple result sets" .IX Subsection "Issues with multiple result sets" Please be aware there could be issues if your result sets are \*(L"jagged\*(R", meaning the number of columns of your results vary. Varying numbers of columns could result in your script crashing. .SH "MULTITHREADING" .IX Header "MULTITHREADING" The multithreading capabilities of DBD::mysql depend completely on the underlying C libraries. The modules are working with handle data only, no global variables are accessed or (to the best of my knowledge) thread unsafe functions are called. Thus DBD::mysql is believed to be completely thread safe, if the C libraries are thread safe and you don't share handles among threads. .PP The obvious question is: Are the C libraries thread safe? In the case of MySQL the answer is yes, since MySQL 5.5 it is. .SH "ASYNCHRONOUS QUERIES" .IX Header "ASYNCHRONOUS QUERIES" You can make a single asynchronous query per MySQL connection; this allows you to submit a long-running query to the server and have an event loop inform you when it's ready. An asynchronous query is started by either setting the 'async' attribute to a true value in the \*(L"do\*(R" in \s-1DBI\s0 method, or in the \*(L"prepare\*(R" in \s-1DBI\s0 method. Statements created with 'async' set to true in prepare always run their queries asynchronously when \*(L"execute\*(R" in \s-1DBI\s0 is called. The driver also offers three additional methods: \&\f(CW\*(C`mysql_async_result\*(C'\fR, \f(CW\*(C`mysql_async_ready\*(C'\fR, and \f(CW\*(C`mysql_fd\*(C'\fR. \&\f(CW\*(C`mysql_async_result\*(C'\fR returns what do or execute would have; that is, the number of rows affected. \f(CW\*(C`mysql_async_ready\*(C'\fR returns true if \&\f(CW\*(C`mysql_async_result\*(C'\fR will not block, and zero otherwise. They both return \&\f(CW\*(C`undef\*(C'\fR if that handle was not created with 'async' set to true or if an asynchronous query was not started yet. \&\f(CW\*(C`mysql_fd\*(C'\fR returns the file descriptor number for the MySQL connection; you can use this in an event loop. .PP Here's an example of how to use the asynchronous query interface: .PP .Vb 7 \& use feature \*(Aqsay\*(Aq; \& $dbh\->do(\*(AqSELECT SLEEP(10)\*(Aq, { async => 1 }); \& until($dbh\->mysql_async_ready) { \& say \*(Aqnot ready yet!\*(Aq; \& sleep 1; \& } \& my $rows = $dbh\->mysql_async_result; .Ve .SH "INSTALLATION" .IX Header "INSTALLATION" See DBD::mysql::INSTALL. .SH "AUTHORS" .IX Header "AUTHORS" Originally, there was a non-DBI driver, Mysql, which was much like \&\s-1PHP\s0 drivers such as mysql and mysqli. The \fBMysql\fR module was originally written by Andreas König who still, to this day, contributes patches to DBD::mysql. An emulated version of Mysql was provided to DBD::mysql from Jochen Wiedmann, but eventually deprecated as it was another bundle of code to maintain. .PP The first incarnation of DBD::mysql was developed by Alligator Descartes, who was also aided and abetted by Gary Shea, Andreas König and Tim Bunce. .PP The current incarnation of \fBDBD::mysql\fR was written by Jochen Wiedmann, then numerous changes and bug-fixes were added by Rudy Lippan. Next, prepared statement support was added by Patrick Galbraith and Alexy Stroganov (who also solely added embedded server support). .PP For the past nine years DBD::mysql has been maintained by Patrick Galbraith (\fIpatg@patg.net\fR), and recently with the great help of Michiel Beijen (\fImichiel.beijen@gmail.com\fR), along with the entire community of Perl developers who keep sending patches to help continue improving DBD::mysql .SH "CONTRIBUTIONS" .IX Header "CONTRIBUTIONS" Anyone who desires to contribute to this project is encouraged to do so. Currently, the source code for this project can be found at Github: .PP .PP Either fork this repository and produce a branch with your changeset that the maintainer can merge to his tree, or create a diff with git. The maintainer is more than glad to take contributions from the community as many features and fixes from DBD::mysql have come from the community. .SH "COPYRIGHT" .IX Header "COPYRIGHT" This module is .IP "\(bu" 4 Large Portions Copyright (c) 2004\-2013 Patrick Galbraith .IP "\(bu" 4 Large Portions Copyright (c) 2004\-2006 Alexey Stroganov .IP "\(bu" 4 Large Portions Copyright (c) 2003\-2005 Rudolf Lippan .IP "\(bu" 4 Large Portions Copyright (c) 1997\-2003 Jochen Wiedmann, with code portions .IP "\(bu" 4 Copyright (c)1994\-1997 their original authors .SH "LICENSE" .IX Header "LICENSE" This module is released under the same license as Perl itself. See for details. .SH "MAILING LIST SUPPORT" .IX Header "MAILING LIST SUPPORT" This module is maintained and supported on a mailing list, dbi-users. .PP To subscribe to this list, send an email to .PP dbi\-users\-subscribe@perl.org .PP Mailing list archives are at .PP .SH "ADDITIONAL DBI INFORMATION" .IX Header "ADDITIONAL DBI INFORMATION" Additional information on the \s-1DBI\s0 project can be found on the World Wide Web at the following \s-1URL:\s0 .PP .PP where documentation, pointers to the mailing lists and mailing list archives and pointers to the most current versions of the modules can be used. .PP Information on the \s-1DBI\s0 interface itself can be gained by typing: .PP .Vb 1 \& perldoc DBI .Ve .PP Information on DBD::mysql specifically can be gained by typing: .PP .Vb 1 \& perldoc DBD::mysql .Ve .PP (this will display the document you're currently reading) .SH "BUG REPORTING, ENHANCEMENT/FEATURE REQUESTS" .IX Header "BUG REPORTING, ENHANCEMENT/FEATURE REQUESTS" Please report bugs, including all the information needed such as DBD::mysql version, MySQL version, \s-1OS\s0 type/version, etc to this link: .PP .PP Note: until recently, MySQL/Sun/Oracle responded to bugs and assisted in fixing bugs which many thanks should be given for their help! This driver is outside the realm of the numerous components they support, and the maintainer and community solely support DBD::mysql man/man3/Path::Class.3pm000044400000023273152462503210010651 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Path::Class 3" .TH Path::Class 3 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Path::Class \- Cross\-platform path specification manipulation .SH "VERSION" .IX Header "VERSION" version 0.37 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Path::Class; \& \& my $dir = dir(\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq); # Path::Class::Dir object \& my $file = file(\*(Aqbob\*(Aq, \*(Aqfile.txt\*(Aq); # Path::Class::File object \& \& # Stringifies to \*(Aqfoo/bar\*(Aq on Unix, \*(Aqfoo\ebar\*(Aq on Windows, etc. \& print "dir: $dir\en"; \& \& # Stringifies to \*(Aqbob/file.txt\*(Aq on Unix, \*(Aqbob\efile.txt\*(Aq on Windows \& print "file: $file\en"; \& \& my $subdir = $dir\->subdir(\*(Aqbaz\*(Aq); # foo/bar/baz \& my $parent = $subdir\->parent; # foo/bar \& my $parent2 = $parent\->parent; # foo \& \& my $dir2 = $file\->dir; # bob \& \& # Work with foreign paths \& use Path::Class qw(foreign_file foreign_dir); \& my $file = foreign_file(\*(AqMac\*(Aq, \*(Aq:foo:file.txt\*(Aq); \& print $file\->dir; # :foo: \& print $file\->as_foreign(\*(AqWin32\*(Aq); # foo\efile.txt \& \& # Interact with the underlying filesystem: \& \& # $dir_handle is an IO::Dir object \& my $dir_handle = $dir\->open or die "Can\*(Aqt read $dir: $!"; \& \& # $file_handle is an IO::File object \& my $file_handle = $file\->open($mode) or die "Can\*(Aqt read $file: $!"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\f(CW\*(C`Path::Class\*(C'\fR is a module for manipulation of file and directory specifications (strings describing their locations, like \&\f(CW\*(Aq/home/ken/foo.txt\*(Aq\fR or \f(CW\*(AqC:\eWindows\eFoo.txt\*(Aq\fR) in a cross-platform manner. It supports pretty much every platform Perl runs on, including Unix, Windows, Mac, \s-1VMS,\s0 Epoc, Cygwin, \s-1OS/2,\s0 and NetWare. .PP The well-known module File::Spec also provides this service, but it's sort of awkward to use well, so people sometimes avoid it, or use it in a way that won't actually work properly on platforms significantly different than the ones they've tested their code on. .PP In fact, \f(CW\*(C`Path::Class\*(C'\fR uses \f(CW\*(C`File::Spec\*(C'\fR internally, wrapping all the unsightly details so you can concentrate on your application code. Whereas \f(CW\*(C`File::Spec\*(C'\fR provides functions for some common path manipulations, \f(CW\*(C`Path::Class\*(C'\fR provides an object-oriented model of the world of path specifications and their underlying semantics. \&\f(CW\*(C`File::Spec\*(C'\fR doesn't create any objects, and its classes represent the different ways in which paths must be manipulated on various platforms (not a very intuitive concept). \f(CW\*(C`Path::Class\*(C'\fR creates objects representing files and directories, and provides methods that relate them to each other. For instance, the following \f(CW\*(C`File::Spec\*(C'\fR code: .PP .Vb 3 \& my $absolute = File::Spec\->file_name_is_absolute( \& File::Spec\->catfile( @dirs, $file ) \& ); .Ve .PP can be written using \f(CW\*(C`Path::Class\*(C'\fR as .PP .Vb 1 \& my $absolute = Path::Class::File\->new( @dirs, $file )\->is_absolute; .Ve .PP or even as .PP .Vb 1 \& my $absolute = file( @dirs, $file )\->is_absolute; .Ve .PP Similar readability improvements should happen all over the place when using \f(CW\*(C`Path::Class\*(C'\fR. .PP Using \f(CW\*(C`Path::Class\*(C'\fR can help solve real problems in your code too \- for instance, how many people actually take the \*(L"volume\*(R" (like \f(CW\*(C`C:\*(C'\fR on Windows) into account when writing \f(CW\*(C`File::Spec\*(C'\fR\-using code? I thought not. But if you use \f(CW\*(C`Path::Class\*(C'\fR, your file and directory objects will know what volumes they refer to and do the right thing. .PP The guts of the \f(CW\*(C`Path::Class\*(C'\fR code live in the Path::Class::File and Path::Class::Dir modules, so please see those modules' documentation for more details about how to use them. .SS "\s-1EXPORT\s0" .IX Subsection "EXPORT" The following functions are exported by default. .IP "file" 4 .IX Item "file" A synonym for \f(CW\*(C`Path::Class::File\->new\*(C'\fR. .IP "dir" 4 .IX Item "dir" A synonym for \f(CW\*(C`Path::Class::Dir\->new\*(C'\fR. .PP If you would like to prevent their export, you may explicitly pass an empty list to perl's \f(CW\*(C`use\*(C'\fR, i.e. \f(CW\*(C`use Path::Class ()\*(C'\fR. .PP The following are exported only on demand. .IP "foreign_file" 4 .IX Item "foreign_file" A synonym for \f(CW\*(C`Path::Class::File\->new_foreign\*(C'\fR. .IP "foreign_dir" 4 .IX Item "foreign_dir" A synonym for \f(CW\*(C`Path::Class::Dir\->new_foreign\*(C'\fR. .IP "tempdir" 4 .IX Item "tempdir" Create a new Path::Class::Dir instance pointed to temporary directory. .Sp .Vb 1 \& my $temp = Path::Class::tempdir(CLEANUP => 1); .Ve .Sp A synonym for \f(CW\*(C`Path::Class::Dir\->new(File::Temp::tempdir(@_))\*(C'\fR. .SH "Notes on Cross-Platform Compatibility" .IX Header "Notes on Cross-Platform Compatibility" Although it is much easier to write cross-platform-friendly code with this module than with \f(CW\*(C`File::Spec\*(C'\fR, there are still some issues to be aware of. .IP "\(bu" 4 On some platforms, notably \s-1VMS\s0 and some older versions of \s-1DOS\s0 (I think), all filenames must have an extension. Thus if you create a file called \fIfoo/bar\fR and then ask for a list of files in the directory \&\fIfoo\fR, you may find a file called \fIbar.\fR instead of the \fIbar\fR you were expecting. Thus it might be a good idea to use an extension in the first place. .SH "AUTHOR" .IX Header "AUTHOR" Ken Williams, KWILLIAMS@cpan.org .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) Ken Williams. All rights reserved. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" Path::Class::Dir, Path::Class::File, File::Spec man/man3/DBD::Mem.3pm000044400000014077152462503210010021 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Mem 3" .TH DBD::Mem 3 "2017-12-28" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Mem \- a DBI driver for Mem & MLMem files .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use DBI; \& $dbh = DBI\->connect(\*(Aqdbi:Mem:\*(Aq, undef, undef, {}); \& $dbh = DBI\->connect(\*(Aqdbi:Mem:\*(Aq, undef, undef, {RaiseError => 1}); \& \& # or \& $dbh = DBI\->connect(\*(Aqdbi:Mem:\*(Aq); \& $dbh = DBI\->connect(\*(AqDBI:Mem(RaiseError=1):\*(Aq); .Ve .PP and other variations on \fBconnect()\fR as shown in the \s-1DBI\s0 docs and . .PP Use standard \s-1DBI\s0 prepare, execute, fetch, placeholders, etc., see \*(L"\s-1QUICK START\*(R"\s0 for an example. .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBD::Mem is a database management system that works right out of the box. If you have a standard installation of Perl and \s-1DBI\s0 you can begin creating, accessing, and modifying simple database tables without any further modules. You can add other modules (e.g., SQL::Statement) for improved functionality. .PP DBD::Mem doesn't store any data persistently \- all data has the lifetime of the instantiated \f(CW$dbh\fR. The main reason to use DBD::Mem is to use extended features of SQL::Statement where temporary tables are required. One can use DBD::Mem to simulate \f(CW\*(C`VIEWS\*(C'\fR or sub-queries. .PP Bundling \f(CW\*(C`DBD::Mem\*(C'\fR with \s-1DBI\s0 will allow us further compatibility checks of DBI::DBD::SqlEngine beyond the capabilities of DBD::File and \&\s-1DBD::DBM\s0. This will ensure \s-1DBI\s0 provided basis for drivers like DBD::AnyData2 or DBD::Amazon are better prepared and tested for not-file based backends. .SS "Metadata" .IX Subsection "Metadata" There're no new meta data introduced by \f(CW\*(C`DBD::Mem\*(C'\fR. See \&\*(L"Metadata\*(R" in DBI::DBD::SqlEngine for full description. .SH "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" .IX Header "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" If you need help installing or using DBD::Mem, please write to the \s-1DBI\s0 users mailing list at or to the comp.lang.perl.modules newsgroup on usenet. I cannot always answer every question quickly but there are many on the mailing list or in the newsgroup who can. .PP \&\s-1DBD\s0 developers for \s-1DBD\s0's which rely on DBI::DBD::SqlEngine or DBD::Mem or use one of them as an example are suggested to join the \s-1DBI\s0 developers mailing list at and strongly encouraged to join our \&\s-1IRC\s0 channel at . .PP If you have suggestions, ideas for improvements, or bugs to report, please report a bug as described in \s-1DBI.\s0 Do not mail any of the authors directly, you might not get an answer. .PP When reporting bugs, please send the output of \f(CW\*(C`$dbh\->mem_versions($table)\*(C'\fR for a table that exhibits the bug and as small a sample as you can make of the code that produces the bug. And of course, patches are welcome, too :\-). .PP If you need enhancements quickly, you can get commercial support as described at or you can contact Jens Rehsack at rehsack@cpan.org for commercial support. .SH "AUTHOR AND COPYRIGHT" .IX Header "AUTHOR AND COPYRIGHT" This module is written by Jens Rehsack < rehsack \s-1AT\s0 cpan.org >. .PP .Vb 1 \& Copyright (c) 2016\- by Jens Rehsack, all rights reserved. .Ve .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1DBI\s0 for the Database interface of the Perl Programming Language. .PP SQL::Statement and DBI::SQL::Nano for the available \s-1SQL\s0 engines. .PP SQL::Statement::RAM where the implementation is shamelessly stolen from to allow \s-1DBI\s0 bundled Pure-Perl drivers increase the test coverage. .PP DBD::SQLite using \f(CW\*(C`dbname=:memory:\*(C'\fR for an incredible fast in-memory database engine. man/man3/DBI::Const::GetInfo::ANSI.3pm000044400000006447152462503210012677 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Const::GetInfo::ANSI 3" .TH DBI::Const::GetInfo::ANSI 3 "2015-05-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Const::GetInfo::ANSI \- ISO/IEC SQL/CLI Constants for GetInfo .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& The API for this module is private and subject to change. .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Information requested by \fBGetInfo()\fR. .PP See: A.1 C header file \s-1SQLCLI.H,\s0 Page 316, 317. .PP The \s-1API\s0 for this module is private and subject to change. .SH "REFERENCES" .IX Header "REFERENCES" .Vb 2 \& ISO/IEC FCD 9075\-3:200x Information technology \- Database Languages \- \& SQL \- Part 3: Call\-Level Interface (SQL/CLI) \& \& SC32 N00744 = WG3:VIE\-005 = H2\-2002\-007 \& \& Date: 2002\-01\-15 .Ve .ie n .SS "%ReturnTypes" .el .SS "\f(CW%ReturnTypes\fP" .IX Subsection "%ReturnTypes" See: Codes and data types for implementation information (Table 28), Page 85, 86. .PP Mapped to \s-1ODBC\s0 datatype names. .ie n .SS "%ReturnValues" .el .SS "\f(CW%ReturnValues\fP" .IX Subsection "%ReturnValues" See: A.1 C header file \s-1SQLCLI.H,\s0 Page 317, 318. .SH "TODO" .IX Header "TODO" Corrections, e.g.: .PP .Vb 1 \& SQL_TRANSACTION_ISOLATION_OPTION vs. SQL_TRANSACTION_ISOLATION .Ve man/man3/YAML::Syck.3pm000044400000025111152462503210010354 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "YAML::Syck 3" .TH YAML::Syck 3 "2020-10-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" YAML::Syck \- Fast, lightweight YAML loader and dumper .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use YAML::Syck; \& \& # Set this for interoperability with other YAML/Syck bindings: \& # e.g. Load(\*(AqYes\*(Aq) becomes 1 and Load(\*(AqNo\*(Aq) becomes \*(Aq\*(Aq. \& $YAML::Syck::ImplicitTyping = 1; \& \& $data = Load($yaml); \& $yaml = Dump($data); \& \& # $file can be an IO object, or a filename \& $data = LoadFile($file); \& DumpFile($file, $data); \& \& # A string with multiple YAML streams in it \& $yaml = Dump(@data); \& @data = Load($yaml); \& \& # Dumping into a pre\-existing output buffer \& my $yaml; \& DumpInto(\e$yaml, @data); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module provides a Perl interface to the \fBlibsyck\fR data serialization library. It exports the \f(CW\*(C`Dump\*(C'\fR and \f(CW\*(C`Load\*(C'\fR functions for converting Perl data structures to \s-1YAML\s0 strings, and the other way around. .PP \&\fB\s-1NOTE\s0\fR: If you are working with other language's YAML/Syck bindings (such as Ruby), please set \f(CW$YAML::Syck::ImplicitTyping\fR to \f(CW1\fR before calling the \f(CW\*(C`Load\*(C'\fR/\f(CW\*(C`Dump\*(C'\fR functions. The default setting is for preserving backward-compatibility with \f(CW\*(C`YAML.pm\*(C'\fR. .SH "Differences Between YAML::Syck and YAML" .IX Header "Differences Between YAML::Syck and YAML" .SS "Error handling" .IX Subsection "Error handling" Some calls are designed to die rather than returning \s-1YAML.\s0 You should wrap your calls in eval to assure you do not get unexpected results. .SH "FLAGS" .IX Header "FLAGS" .ie n .SS "$YAML::Syck::Headless" .el .SS "\f(CW$YAML::Syck::Headless\fP" .IX Subsection "$YAML::Syck::Headless" Defaults to false. Setting this to a true value will make \f(CW\*(C`Dump\*(C'\fR omit the leading \f(CW\*(C`\-\-\-\en\*(C'\fR marker. .ie n .SS "$YAML::Syck::SortKeys" .el .SS "\f(CW$YAML::Syck::SortKeys\fP" .IX Subsection "$YAML::Syck::SortKeys" Defaults to false. Setting this to a true value will make \f(CW\*(C`Dump\*(C'\fR sort hash keys. .ie n .SS "$YAML::Syck::SingleQuote" .el .SS "\f(CW$YAML::Syck::SingleQuote\fP" .IX Subsection "$YAML::Syck::SingleQuote" Defaults to false. Setting this to a true value will make \f(CW\*(C`Dump\*(C'\fR always emit single quotes instead of bare strings. .ie n .SS "$YAML::Syck::ImplicitTyping" .el .SS "\f(CW$YAML::Syck::ImplicitTyping\fP" .IX Subsection "$YAML::Syck::ImplicitTyping" Defaults to false. Setting this to a true value will make \f(CW\*(C`Load\*(C'\fR recognize various implicit types in \s-1YAML,\s0 such as unquoted \f(CW\*(C`true\*(C'\fR, \f(CW\*(C`false\*(C'\fR, as well as integers and floating-point numbers. Otherwise, only \f(CW\*(C`~\*(C'\fR is recognized to be \f(CW\*(C`undef\*(C'\fR. .ie n .SS "$YAML::Syck::ImplicitUnicode" .el .SS "\f(CW$YAML::Syck::ImplicitUnicode\fP" .IX Subsection "$YAML::Syck::ImplicitUnicode" Defaults to false. For Perl 5.8.0 or later, setting this to a true value will make \f(CW\*(C`Load\*(C'\fR set Unicode flag on for every string that contains valid \s-1UTF8\s0 sequences, and make \f(CW\*(C`Dump\*(C'\fR return a unicode string. .PP Regardless of this flag, Unicode strings are dumped verbatim without escaping; byte strings with high-bit set will be dumped with backslash escaping. .PP However, because \s-1YAML\s0 does not distinguish between these two kinds of strings, so this flag will affect loading of both variants of strings. .PP If you want to use LoadFile or DumpFile with unicode, you are required to open your own file in order to assure it's \s-1UTF8\s0 encoded: .PP .Vb 2 \& open(my $fh, ">:encoding(UTF\-8)", "out.yml"); \& DumpFile($fh, $hashref); .Ve .ie n .SS "$YAML::Syck::ImplicitBinary" .el .SS "\f(CW$YAML::Syck::ImplicitBinary\fP" .IX Subsection "$YAML::Syck::ImplicitBinary" Defaults to false. For Perl 5.8.0 or later, setting this to a true value will make \f(CW\*(C`Dump\*(C'\fR generate Base64\-encoded \f(CW\*(C`!!binary\*(C'\fR data for all non-Unicode scalars containing high-bit bytes. .ie n .SS "$YAML::Syck::UseCode / $YAML::Syck::LoadCode / $YAML::Syck::DumpCode" .el .SS "\f(CW$YAML::Syck::UseCode\fP / \f(CW$YAML::Syck::LoadCode\fP / \f(CW$YAML::Syck::DumpCode\fP" .IX Subsection "$YAML::Syck::UseCode / $YAML::Syck::LoadCode / $YAML::Syck::DumpCode" These flags control whether or not to try and eval/deparse perl source code; each of them defaults to false. .PP Setting \f(CW$YAML::Syck::UseCode\fR to a true value is equivalent to setting both \f(CW$YAML::Syck::LoadCode\fR and \f(CW$YAML::Syck::DumpCode\fR to true. .ie n .SS "$YAML::Syck::LoadBlessed" .el .SS "\f(CW$YAML::Syck::LoadBlessed\fP" .IX Subsection "$YAML::Syck::LoadBlessed" Defaults to false. Setting to true will allow YAML::Syck to bless objects as it imports objects. This default changed in 1.32. .PP You can create any kind of object with \s-1YAML.\s0 The creation itself is not the critical part. If the class has a \s-1DESTROY\s0 method, it will be called once the object is deleted. An example with File::Temp removing files can be found at .SH "BUGS" .IX Header "BUGS" Dumping Glob/IO values do not work yet. .PP Dumping of Tied variables is unsupported. .PP Dumping into tied (or other magic variables) with \f(CW\*(C`DumpInto\*(C'\fR might not work properly in all cases. .SH "CAVEATS" .IX Header "CAVEATS" This module implements the \s-1YAML 1.0\s0 spec. To deal with data in \s-1YAML 1.1,\s0 please use the \f(CW\*(C`YAML::XS\*(C'\fR module instead. .PP The current implementation bundles libsyck source code; if your system has a site-wide shared libsyck, it will \fInot\fR be used. .PP Tag names such as \f(CW\*(C`!!perl/hash:Foo\*(C'\fR is blessed into the package \f(CW\*(C`Foo\*(C'\fR, but the \f(CW\*(C`!hs/foo\*(C'\fR and \f(CW\*(C`!!hs/Foo\*(C'\fR tags are blessed into \f(CW\*(C`hs::Foo\*(C'\fR. Note that this holds true even if the tag contains non-word characters; for example, \&\f(CW\*(C`!haskell.org/Foo\*(C'\fR is blessed into \f(CW\*(C`haskell.org::Foo\*(C'\fR. Please use Class::Rebless to cast it into other user-defined packages. You can also set the LoadBlessed flag false to disable all blessing. .PP This module has a lot of known issues and has only been semi-actively maintained since 2007. If you encounter an issue with it probably won't be fixed unless you offer up a patch in Git that's ready for release. .PP There are still good reasons to use this module, such as better interoperability with other syck wrappers (like Ruby's), or some edge case of \s-1YAML\s0's syntax that it handles better. It'll probably work perfectly for you, but if it doesn't you may want to look at \&\s-1YAML::XS\s0, or perhaps at looking another serialization format like \&\s-1JSON\s0. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1YAML\s0, JSON::Syck .PP .SH "AUTHORS" .IX Header "AUTHORS" Audrey Tang .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2005\-2009 by Audrey Tang . .PP This software is released under the \s-1MIT\s0 license cited below. .PP The \fIlibsyck\fR code bundled with this library is released by \&\*(L"why the lucky stiff\*(R", under a BSD-style license. See the \fI\s-1COPYING\s0\fR file for details. .ie n .SS "The ""\s-1MIT""\s0 License" .el .SS "The ``\s-1MIT''\s0 License" .IX Subsection "The MIT License" Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \*(L"Software\*(R"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: .PP The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. .PP \&\s-1THE SOFTWARE IS PROVIDED \*(L"AS IS\*(R", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\s0 man/man3/LWP::RobotUA.3pm000044400000014547152462503210010671 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::RobotUA 3" .TH LWP::RobotUA 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::RobotUA \- a class for well\-behaved Web robots .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 4 \& use LWP::RobotUA; \& my $ua = LWP::RobotUA\->new(\*(Aqmy\-robot/0.1\*(Aq, \*(Aqme@foo.com\*(Aq); \& $ua\->delay(10); # be very nice \-\- max one hit every ten minutes! \& ... \& \& # Then just use it just like a normal LWP::UserAgent: \& my $response = $ua\->get(\*(Aqhttp://whatever.int/...\*(Aq); \& ... .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This class implements a user agent that is suitable for robot applications. Robots should be nice to the servers they visit. They should consult the \fI/robots.txt\fR file to ensure that they are welcomed and they should not make requests too frequently. .PP But before you consider writing a robot, take a look at . .PP When you use an \fILWP::RobotUA\fR object as your user agent, then you do not really have to think about these things yourself; \f(CW\*(C`robots.txt\*(C'\fR files are automatically consulted and obeyed, the server isn't queried too rapidly, and so on. Just send requests as you do when you are using a normal \fILWP::UserAgent\fR object (using \f(CW\*(C`$ua\->get(...)\*(C'\fR, \f(CW\*(C`$ua\->head(...)\*(C'\fR, \&\f(CW\*(C`$ua\->request(...)\*(C'\fR, etc.), and this special agent will make sure you are nice. .SH "METHODS" .IX Header "METHODS" The LWP::RobotUA is a sub-class of LWP::UserAgent and implements the same methods. In addition the following methods are provided: .SS "new" .IX Subsection "new" .Vb 3 \& my $ua = LWP::RobotUA\->new( %options ) \& my $ua = LWP::RobotUA\->new( $agent, $from ) \& my $ua = LWP::RobotUA\->new( $agent, $from, $rules ) .Ve .PP The LWP::UserAgent options \f(CW\*(C`agent\*(C'\fR and \f(CW\*(C`from\*(C'\fR are mandatory. The options \f(CW\*(C`delay\*(C'\fR, \f(CW\*(C`use_sleep\*(C'\fR and \f(CW\*(C`rules\*(C'\fR initialize attributes private to the RobotUA. If \f(CW\*(C`rules\*(C'\fR are not provided, then WWW::RobotRules is instantiated providing an internal database of \&\fIrobots.txt\fR. .PP It is also possible to just pass the value of \f(CW\*(C`agent\*(C'\fR, \f(CW\*(C`from\*(C'\fR and optionally \f(CW\*(C`rules\*(C'\fR as plain positional arguments. .SS "delay" .IX Subsection "delay" .Vb 2 \& my $delay = $ua\->delay; \& $ua\->delay( $minutes ); .Ve .PP Get/set the minimum delay between requests to the same server, in \&\fIminutes\fR. The default is \f(CW1\fR minute. Note that this number doesn't have to be an integer; for example, this sets the delay to \f(CW10\fR seconds: .PP .Vb 1 \& $ua\->delay(10/60); .Ve .SS "use_sleep" .IX Subsection "use_sleep" .Vb 2 \& my $bool = $ua\->use_sleep; \& $ua\->use_sleep( $boolean ); .Ve .PP Get/set a value indicating whether the \s-1UA\s0 should \*(L"sleep\*(R" in LWP::RobotUA if requests arrive too fast, defined as \f(CW\*(C`$ua\->delay\*(C'\fR minutes not passed since last request to the given server. The default is true. If this value is false then an internal \f(CW\*(C`SERVICE_UNAVAILABLE\*(C'\fR response will be generated. It will have a \f(CW\*(C`Retry\-After\*(C'\fR header that indicates when it is \s-1OK\s0 to send another request to this server. .SS "rules" .IX Subsection "rules" .Vb 2 \& my $rules = $ua\->rules; \& $ua\->rules( $rules ); .Ve .PP Set/get which \fIWWW::RobotRules\fR object to use. .SS "no_visits" .IX Subsection "no_visits" .Vb 1 \& my $num = $ua\->no_visits( $netloc ) .Ve .PP Returns the number of documents fetched from this server host. Yeah I know, this method should probably have been named \f(CW\*(C`num_visits\*(C'\fR or something like that. :\-( .SS "host_wait" .IX Subsection "host_wait" .Vb 1 \& my $num = $ua\->host_wait( $netloc ) .Ve .PP Returns the number of \fIseconds\fR (from now) you must wait before you can make a new request to this host. .SS "as_string" .IX Subsection "as_string" .Vb 1 \& my $string = $ua\->as_string; .Ve .PP Returns a string that describes the state of the \s-1UA.\s0 Mainly useful for debugging. .SH "SEE ALSO" .IX Header "SEE ALSO" LWP::UserAgent, WWW::RobotRules .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 1996\-2004 Gisle Aas. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/Canary::Stability.3pm000044400000010114152462503210012057 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Stability 3" .TH Stability 3 "2019-04-22" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Canary::Stability \- canary to check perl compatibility for schmorp's modules .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # in Makefile.PL \& use Canary::Stability DISTNAME => 2001, MINIMUM_PERL_VERSION; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module is used by Schmorp's modules during configuration stage to test the installed perl for compatibility with his modules. .PP It's not, at this stage, meant as a tool for other module authors, although in principle nothing prevents them from subscribing to the same ideas. .PP See the \fIMakefile.PL\fR in Coro or AnyEvent for usage examples. .SH "ENVIRONMENT VARIABLES" .IX Header "ENVIRONMENT VARIABLES" .ie n .IP """PERL_CANARY_STABILITY_NOPROMPT=1""" 4 .el .IP "\f(CWPERL_CANARY_STABILITY_NOPROMPT=1\fR" 4 .IX Item "PERL_CANARY_STABILITY_NOPROMPT=1" Do not prompt the user on alert messages. .ie n .IP """PERL_CANARY_STABILITY_COLOUR=0""" 4 .el .IP "\f(CWPERL_CANARY_STABILITY_COLOUR=0\fR" 4 .IX Item "PERL_CANARY_STABILITY_COLOUR=0" Disable use of colour. .ie n .IP """PERL_CANARY_STABILITY_COLOUR=1""" 4 .el .IP "\f(CWPERL_CANARY_STABILITY_COLOUR=1\fR" 4 .IX Item "PERL_CANARY_STABILITY_COLOUR=1" Force use of colour. .ie n .IP """PERL_CANARY_STABILITY_DISABLE=1""" 4 .el .IP "\f(CWPERL_CANARY_STABILITY_DISABLE=1\fR" 4 .IX Item "PERL_CANARY_STABILITY_DISABLE=1" Disable this modules functionality completely. .ie n .IP """AUTOMATED_TESTING=1""" 4 .el .IP "\f(CWAUTOMATED_TESTING=1\fR" 4 .IX Item "AUTOMATED_TESTING=1" When this variable is set to a true value and the perl minimum version requirement is not met, the module will exit, which should skip testing under automated testing environments. .Sp This is done to avoid false failure or success reports when the chances of success are already quite low and the failures are not supported by the author. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 2 \& Marc Lehmann \& http://software.schmorp.de/pkg/Canary\-Stability.html .Ve man/man3/DBI::PurePerl.3pm000044400000017666152462503210011055 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::PurePerl 3" .TH DBI::PurePerl 3 "2020-01-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::PurePerl \-\- a DBI emulation using pure perl (no C/XS compilation required) .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& BEGIN { $ENV{DBI_PUREPERL} = 2 } \& use DBI; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is a pure perl emulation of the \s-1DBI\s0 internals. In almost all cases you will be better off using standard \s-1DBI\s0 since the portions of the standard version written in C make it *much* faster. .PP However, if you are in a situation where it isn't possible to install a compiled version of standard \s-1DBI,\s0 and you're using pure-perl \s-1DBD\s0 drivers, then this module allows you to use most common features of \s-1DBI\s0 without needing any changes in your scripts. .SH "EXPERIMENTAL STATUS" .IX Header "EXPERIMENTAL STATUS" DBI::PurePerl is new so please treat it as experimental pending more extensive testing. So far it has passed all tests with \s-1DBD::CSV,\s0 DBD::AnyData, DBD::XBase, DBD::Sprite, DBD::mysqlPP. Please send bug reports to Jeff Zucker at with a cc to . .SH "USAGE" .IX Header "USAGE" The usage is the same as for standard \s-1DBI\s0 with the exception that you need to set the environment variable \s-1DBI_PUREPERL\s0 if you want to use the PurePerl version. .PP .Vb 2 \& DBI_PUREPERL == 0 (the default) Always use compiled DBI, die \& if it isn\*(Aqt properly compiled & installed \& \& DBI_PUREPERL == 1 Use compiled DBI if it is properly compiled \& & installed, otherwise use PurePerl \& \& DBI_PUREPERL == 2 Always use PurePerl .Ve .PP You may set the environment variable in your shell (e.g. with set or setenv or export, etc) or else set it in your script like this: .PP .Vb 1 \& BEGIN { $ENV{DBI_PUREPERL}=2 } .Ve .PP before you \f(CW\*(C`use DBI;\*(C'\fR. .SH "INSTALLATION" .IX Header "INSTALLATION" In most situations simply install \s-1DBI\s0 (see the \s-1DBI\s0 pod for details). .PP In the situation in which you can not install \s-1DBI\s0 itself, you may manually copy \s-1DBI\s0.pm and PurePerl.pm into the appropriate directories. .PP For example: .PP .Vb 2 \& cp DBI.pm /usr/jdoe/mylibs/. \& cp PurePerl.pm /usr/jdoe/mylibs/DBI/. .Ve .PP Then add this to the top of scripts: .PP .Vb 4 \& BEGIN { \& $ENV{DBI_PUREPERL} = 1; # or =2 \& unshift @INC, \*(Aq/usr/jdoe/mylibs\*(Aq; \& } .Ve .PP (Or should we perhaps patch Makefile.PL so that if \s-1DBI_PUREPERL\s0 is set to 2 prior to make, the normal compile process is skipped and the files are installed automatically?) .SH "DIFFERENCES BETWEEN DBI AND DBI::PurePerl" .IX Header "DIFFERENCES BETWEEN DBI AND DBI::PurePerl" .SS "Attributes" .IX Subsection "Attributes" Boolean attributes still return boolean values but the actual values used may be different, i.e., 0 or undef instead of an empty string. .PP Some handle attributes are either not supported or have very limited functionality: .PP .Vb 7 \& ActiveKids \& InactiveDestroy \& AutoInactiveDestroy \& Kids \& Taint \& TaintIn \& TaintOut .Ve .PP (and probably others) .SS "Tracing" .IX Subsection "Tracing" Trace functionality is more limited and the code to handle tracing is only embedded into DBI:PurePerl if the \s-1DBI_TRACE\s0 environment variable is defined. To enable total tracing you can set the \s-1DBI_TRACE\s0 environment variable as usual. But to enable individual handle tracing using the \fBtrace()\fR method you also need to set the \s-1DBI_TRACE\s0 environment variable, but set it to 0. .SS "Parameter Usage Checking" .IX Subsection "Parameter Usage Checking" The \s-1DBI\s0 does some basic parameter count checking on method calls. DBI::PurePerl doesn't. .SS "Speed" .IX Subsection "Speed" DBI::PurePerl is slower. Although, with some drivers in some contexts this may not be very significant for you. .PP By way of example... the test.pl script in the \s-1DBI\s0 source distribution has a simple benchmark that just does: .PP .Vb 3 \& my $null_dbh = DBI\->connect(\*(Aqdbi:NullP:\*(Aq,\*(Aq\*(Aq,\*(Aq\*(Aq); \& my $i = 10_000; \& $null_dbh\->prepare(\*(Aq\*(Aq) while $i\-\-; .Ve .PP In other words just prepares a statement, creating and destroying a statement handle, over and over again. Using the real \s-1DBI\s0 this runs at ~4550 handles per second whereas DBI::PurePerl manages ~2800 per second on the same machine (not too bad really). .SS "May not fully support \fBhash()\fP" .IX Subsection "May not fully support hash()" If you want to use type 1 hash, i.e., \f(CW\*(C`hash($string,1)\*(C'\fR with DBI::PurePerl, you'll need version 1.56 or higher of Math::BigInt (available on \s-1CPAN\s0). .SS "Doesn't support \fBpreparse()\fP" .IX Subsection "Doesn't support preparse()" The \s-1DBI\-\s0>\fBpreparse()\fR method isn't supported in DBI::PurePerl. .SS "Doesn't support DBD::Proxy" .IX Subsection "Doesn't support DBD::Proxy" There's a subtle problem somewhere I've not been able to identify. DBI::ProxyServer seem to work fine with DBI::PurePerl but DBD::Proxy does not work 100% (which is sad because that would be far more useful :) Try re-enabling t/80proxy.t for DBI::PurePerl to see if the problem that remains will affect you're usage. .SS "Others" .IX Subsection "Others" .Vb 1 \& can() \- doesn\*(Aqt have any special behaviour .Ve .PP Please let us know if you find any other differences between \s-1DBI\s0 and DBI::PurePerl. .SH "AUTHORS" .IX Header "AUTHORS" Tim Bunce and Jeff Zucker. .PP Tim provided the direction and basis for the code. The original idea for the module and most of the brute force porting from C to Perl was by Jeff. Tim then reworked some core parts to boost the performance and accuracy of the emulation. Thanks also to Randal Schwartz and John Tobey for patches. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2002 Tim Bunce Ireland. .PP See \s-1COPYRIGHT\s0 section in \s-1DBI\s0.pm for usage and distribution rights. man/man3/DBD::Gofer::Transport::Base.3pm000044400000015022152462503210013414 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Transport::Base 3" .TH DBD::Gofer::Transport::Base 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Transport::Base \- base class for DBD::Gofer client transports .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& my $remote_dsn = "..." \& DBI\->connect("dbi:Gofer:transport=...;url=...;timeout=...;retry_limit=...;dsn=$remote_dsn",...) .Ve .PP or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: .PP .Vb 1 \& export DBI_AUTOPROXY=\*(Aqdbi:Gofer:transport=...;url=...\*(Aq .Ve .PP which will force \fIall\fR \s-1DBI\s0 connections to be made via that Gofer server. .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is the base class for all DBD::Gofer client transports. .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" Gofer transport attributes can be specified either in the attributes parameter of the \fBconnect()\fR method call, or in the \s-1DSN\s0 string. When used in the \s-1DSN\s0 string, attribute names don't have the \f(CW\*(C`go_\*(C'\fR prefix. .SS "go_dsn" .IX Subsection "go_dsn" The full \s-1DBI DSN\s0 that the Gofer server should connect to on your behalf. .PP When used in the \s-1DSN\s0 it must be the last element in the \s-1DSN\s0 string. .SS "go_timeout" .IX Subsection "go_timeout" A time limit for sending a request and receiving a response. Some drivers may implement sending and receiving as separate steps, in which case (currently) the timeout applies to each separately. .PP If a request needs to be resent then the timeout is restarted for each sending of a request and receiving of a response. .SS "go_retry_limit" .IX Subsection "go_retry_limit" The maximum number of times an request may be retried. The default is 2. .SS "go_retry_hook" .IX Subsection "go_retry_hook" This subroutine reference is called, if defined, for each response received where \f(CW$response\fR\->err is true. .PP The subroutine is pass three parameters: the request object, the response object, and the transport object. .PP If it returns an undefined value then the default retry behaviour is used. See \*(L"\s-1RETRY ON ERROR\*(R"\s0 below. .PP If it returns a defined but false value then the request is not resent. .PP If it returns true value then the request is resent, so long as the number of retries does not exceed \f(CW\*(C`go_retry_limit\*(C'\fR. .SH "RETRY ON ERROR" .IX Header "RETRY ON ERROR" The default retry on error behaviour is: .PP .Vb 1 \& \- Retry if the error was due to DBI_GOFER_RANDOM. See L. \& \& \- Retry if $request\->is_idempotent returns true. See L. .Ve .PP A retry won't be allowed if the number of previous retries has reached \f(CW\*(C`go_retry_limit\*(C'\fR. .SH "TRACING" .IX Header "TRACING" Tracing of gofer requests and responses can be enabled by setting the \&\f(CW\*(C`DBD_GOFER_TRACE\*(C'\fR environment variable. A value of 1 gives a reasonably compact summary of each request and response. A value of 2 or more gives a detailed, and voluminous, dump. .PP The trace is written using \s-1DBI\-\s0>\fBtrace_msg()\fR and so is written to the default \&\s-1DBI\s0 trace output, which is usually \s-1STDERR.\s0 .SH "METHODS" .IX Header "METHODS" \&\fIThis section is currently far from complete.\fR .SS "response_retry_preference" .IX Subsection "response_retry_preference" .Vb 1 \& $retry = $transport\->response_retry_preference($request, $response); .Ve .PP The response_retry_preference is called by DBD::Gofer when considering if a request should be retried after an error. .PP Returns true (would like to retry), false (must not retry), undef (no preference). .PP If a true value is returned in the form of a \s-1CODE\s0 ref then, if DBD::Gofer does decide to retry the request, it calls the code ref passing \f(CW$retry_count\fR, \f(CW$retry_limit\fR. Can be used for logging and/or to implement exponential backoff behaviour. Currently the called code must return using \f(CW\*(C`return;\*(C'\fR to allow for future extensions. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007\-2008, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. .SH "SEE ALSO" .IX Header "SEE ALSO" DBD::Gofer, DBI::Gofer::Request, DBI::Gofer::Response, DBI::Gofer::Execute. .PP and some example transports: .PP DBD::Gofer::Transport::stream .PP DBD::Gofer::Transport::http .PP DBI::Gofer::Transport::mod_perl man/man3/Types::Serialiser.3pm000044400000027311152462503210012113 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Serialiser 3" .TH Serialiser 3 "2020-12-01" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Types::Serialiser \- simple data types for common serialisation formats .SH "SYNOPSIS" .IX Header "SYNOPSIS" .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module provides some extra datatypes that are used by common serialisation formats such as \s-1JSON\s0 or \s-1CBOR.\s0 The idea is to have a repository of simple/small constants and containers that can be shared by different implementations so they become interoperable between each other. .SH "SIMPLE SCALAR CONSTANTS" .IX Header "SIMPLE SCALAR CONSTANTS" Simple scalar constants are values that are overloaded to act like simple Perl values, but have (class) type to differentiate them from normal Perl scalars. This is necessary because these have different representations in the serialisation formats. .PP In the following, functions with zero or one arguments have a prototype of \&\f(CW\*(C`()\*(C'\fR and \f(CW\*(C`($)\*(C'\fR, respectively, so act as constants and unary operators. .SS "\s-1BOOLEANS\s0 (Types::Serialiser::Boolean class)" .IX Subsection "BOOLEANS (Types::Serialiser::Boolean class)" This type has only two instances, true and false. A natural representation for these in Perl is \f(CW1\fR and \f(CW0\fR, but serialisation formats need to be able to differentiate between them and mere numbers. .ie n .IP "$Types::Serialiser::true, Types::Serialiser::true" 4 .el .IP "\f(CW$Types::Serialiser::true\fR, Types::Serialiser::true" 4 .IX Item "$Types::Serialiser::true, Types::Serialiser::true" This value represents the \*(L"true\*(R" value. In most contexts is acts like the number \f(CW1\fR. It is up to you whether you use the variable form (\f(CW$Types::Serialiser::true\fR) or the constant form (\f(CW\*(C`Types::Serialiser::true\*(C'\fR). .Sp The constant is represented as a reference to a scalar containing \f(CW1\fR \- implementations are allowed to directly test for this. .ie n .IP "$Types::Serialiser::false, Types::Serialiser::false" 4 .el .IP "\f(CW$Types::Serialiser::false\fR, Types::Serialiser::false" 4 .IX Item "$Types::Serialiser::false, Types::Serialiser::false" This value represents the \*(L"false\*(R" value. In most contexts is acts like the number \f(CW0\fR. It is up to you whether you use the variable form (\f(CW$Types::Serialiser::false\fR) or the constant form (\f(CW\*(C`Types::Serialiser::false\*(C'\fR). .Sp The constant is represented as a reference to a scalar containing \f(CW0\fR \- implementations are allowed to directly test for this. .ie n .IP "Types::Serialiser::as_bool $value" 4 .el .IP "Types::Serialiser::as_bool \f(CW$value\fR" 4 .IX Item "Types::Serialiser::as_bool $value" Converts a Perl scalar into a boolean, which is useful syntactic sugar. Strictly equivalent to: .Sp .Vb 1 \& $value ? $Types::Serialiser::true : $Types::Serialiser::false .Ve .ie n .IP "$is_bool = Types::Serialiser::is_bool $value" 4 .el .IP "\f(CW$is_bool\fR = Types::Serialiser::is_bool \f(CW$value\fR" 4 .IX Item "$is_bool = Types::Serialiser::is_bool $value" Returns true iff the \f(CW$value\fR is either \f(CW$Types::Serialiser::true\fR or \&\f(CW$Types::Serialiser::false\fR. .Sp For example, you could differentiate between a perl true value and a \&\f(CW\*(C`Types::Serialiser::true\*(C'\fR by using this: .Sp .Vb 1 \& $value && Types::Serialiser::is_bool $value .Ve .ie n .IP "$is_true = Types::Serialiser::is_true $value" 4 .el .IP "\f(CW$is_true\fR = Types::Serialiser::is_true \f(CW$value\fR" 4 .IX Item "$is_true = Types::Serialiser::is_true $value" Returns true iff \f(CW$value\fR is \f(CW$Types::Serialiser::true\fR. .ie n .IP "$is_false = Types::Serialiser::is_false $value" 4 .el .IP "\f(CW$is_false\fR = Types::Serialiser::is_false \f(CW$value\fR" 4 .IX Item "$is_false = Types::Serialiser::is_false $value" Returns false iff \f(CW$value\fR is \f(CW$Types::Serialiser::false\fR. .SS "\s-1ERROR\s0 (Types::Serialiser::Error class)" .IX Subsection "ERROR (Types::Serialiser::Error class)" This class has only a single instance, \f(CW\*(C`error\*(C'\fR. It is used to signal an encoding or decoding error. In \s-1CBOR\s0 for example, and object that couldn't be encoded will be represented by a \s-1CBOR\s0 undefined value, which is represented by the error value in Perl. .ie n .IP "$Types::Serialiser::error, Types::Serialiser::error" 4 .el .IP "\f(CW$Types::Serialiser::error\fR, Types::Serialiser::error" 4 .IX Item "$Types::Serialiser::error, Types::Serialiser::error" This value represents the \*(L"error\*(R" value. Accessing values of this type will throw an exception. .Sp The constant is represented as a reference to a scalar containing \f(CW\*(C`undef\*(C'\fR \&\- implementations are allowed to directly test for this. .ie n .IP "$is_error = Types::Serialiser::is_error $value" 4 .el .IP "\f(CW$is_error\fR = Types::Serialiser::is_error \f(CW$value\fR" 4 .IX Item "$is_error = Types::Serialiser::is_error $value" Returns false iff \f(CW$value\fR is \f(CW$Types::Serialiser::error\fR. .SH "NOTES FOR XS USERS" .IX Header "NOTES FOR XS USERS" The recommended way to detect whether a scalar is one of these objects is to check whether the stash is the \f(CW\*(C`Types::Serialiser::Boolean\*(C'\fR or \&\f(CW\*(C`Types::Serialiser::Error\*(C'\fR stash, and then follow the scalar reference to see if it's \f(CW1\fR (true), \f(CW0\fR (false) or \f(CW\*(C`undef\*(C'\fR (error). .PP While it is possible to use an isa test, directly comparing stash pointers is faster and guaranteed to work. .PP For historical reasons, the \f(CW\*(C`Types::Serialiser::Boolean\*(C'\fR stash is just an alias for \f(CW\*(C`JSON::PP::Boolean\*(C'\fR. When printed, the classname with usually be \f(CW\*(C`JSON::PP::Boolean\*(C'\fR, but isa tests and stash pointer comparison will normally work correctly (i.e. Types::Serialiser::true \s-1ISA\s0 JSON::PP::Boolean, but also \s-1ISA\s0 Types::Serialiser::Boolean). .SH "A GENERIC OBJECT SERIALIATION PROTOCOL" .IX Header "A GENERIC OBJECT SERIALIATION PROTOCOL" This section explains the object serialisation protocol used by \&\s-1CBOR::XS\s0. It is meant to be generic enough to support any kind of generic object serialiser. .PP This protocol is called \*(L"the Types::Serialiser object serialisation protocol\*(R". .SS "\s-1ENCODING\s0" .IX Subsection "ENCODING" When the encoder encounters an object that it cannot otherwise encode (for example, \s-1CBOR::XS\s0 can encode a few special types itself, and will first attempt to use the special \f(CW\*(C`TO_CBOR\*(C'\fR serialisation protocol), it will look up the \f(CW\*(C`FREEZE\*(C'\fR method on the object. .PP Note that the \f(CW\*(C`FREEZE\*(C'\fR method will normally be called \fIduring\fR encoding, and \fI\s-1MUST NOT\s0\fR change the data structure that is being encoded in any way, or it might cause memory corruption or worse. .PP If it exists, it will call it with two arguments: the object to serialise, and a constant string that indicates the name of the data model. For example \s-1CBOR::XS\s0 uses \f(CW\*(C`CBOR\*(C'\fR, and the \s-1JSON\s0 and \s-1JSON::XS\s0 modules (or any other \s-1JSON\s0 serialiser), would use \f(CW\*(C`JSON\*(C'\fR as second argument. .PP The \f(CW\*(C`FREEZE\*(C'\fR method can then return zero or more values to identify the object instance. The serialiser is then supposed to encode the class name and all of these return values (which must be encodable in the format) using the relevant form for Perl objects. In \s-1CBOR\s0 for example, there is a registered tag number for encoded perl objects. .PP The values that \f(CW\*(C`FREEZE\*(C'\fR returns must be serialisable with the serialiser that calls it. Therefore, it is recommended to use simple types such as strings and numbers, and maybe array references and hashes (basically, the \&\s-1JSON\s0 data model). You can always use a more complex format for a specific data model by checking the second argument, the data model. .PP The \*(L"data model\*(R" is not the same as the \*(L"data format\*(R" \- the data model indicates what types and kinds of return values can be returned from \&\f(CW\*(C`FREEZE\*(C'\fR. For example, in \f(CW\*(C`CBOR\*(C'\fR it is permissible to return tagged \s-1CBOR\s0 values, while \s-1JSON\s0 does not support these at all, so \f(CW\*(C`JSON\*(C'\fR would be a valid (but too limited) data model name for \f(CW\*(C`CBOR::XS\*(C'\fR. similarly, a serialising format that supports more or less the same data model as \s-1JSON\s0 could use \f(CW\*(C`JSON\*(C'\fR as data model without losing anything. .SS "\s-1DECODING\s0" .IX Subsection "DECODING" When the decoder then encounters such an encoded perl object, it should look up the \f(CW\*(C`THAW\*(C'\fR method on the stored classname, and invoke it with the classname, the constant string to identify the data model/data format, and all the return values returned by \f(CW\*(C`FREEZE\*(C'\fR. .SS "\s-1EXAMPLES\s0" .IX Subsection "EXAMPLES" See the \f(CW\*(C`OBJECT SERIALISATION\*(C'\fR section in the \s-1CBOR::XS\s0 manpage for more details, an example implementation, and code examples. .PP Here is an example \f(CW\*(C`FREEZE\*(C'\fR/\f(CW\*(C`THAW\*(C'\fR method pair: .PP .Vb 2 \& sub My::Object::FREEZE { \& my ($self, $model) = @_; \& \& ($self\->{type}, $self\->{id}, $self\->{variant}) \& } \& \& sub My::Object::THAW { \& my ($class, $model, $type, $id, $variant) = @_; \& \& $class\->new (type => $type, id => $id, variant => $variant) \& } .Ve .SH "BUGS" .IX Header "BUGS" The use of overload makes this module much heavier than it should be (on my system, this module: 4kB \s-1RSS,\s0 overload: 260kB \s-1RSS\s0). .SH "SEE ALSO" .IX Header "SEE ALSO" Currently, \s-1JSON::XS\s0 and \s-1CBOR::XS\s0 use these types. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 2 \& Marc Lehmann \& http://home.schmorp.de/ .Ve man/man3/Net::HTTP::NB.3pm000044400000012725152462503210010621 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Net::HTTP::NB 3pm" .TH Net::HTTP::NB 3pm "2021-03-18" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::HTTP::NB \- Non\-blocking HTTP client .SH "VERSION" .IX Header "VERSION" version 6.21 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use Net::HTTP::NB; \& my $s = Net::HTTP::NB\->new(Host => "www.perl.com") || die $@; \& $s\->write_request(GET => "/"); \& \& use IO::Select; \& my $sel = IO::Select\->new($s); \& \& READ_HEADER: { \& die "Header timeout" unless $sel\->can_read(10); \& my($code, $mess, %h) = $s\->read_response_headers; \& redo READ_HEADER unless $code; \& } \& \& while (1) { \& die "Body timeout" unless $sel\->can_read(10); \& my $buf; \& my $n = $s\->read_entity_body($buf, 1024); \& last unless $n; \& print $buf; \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Same interface as \f(CW\*(C`Net::HTTP\*(C'\fR but it will never try multiple reads when the \fBread_response_headers()\fR or \fBread_entity_body()\fR methods are invoked. This make it possible to multiplex multiple Net::HTTP::NB using select without risk blocking. .PP If \fBread_response_headers()\fR did not see enough data to complete the headers an empty list is returned. .PP If \fBread_entity_body()\fR did not see new entity data in its read the value \-1 is returned. .SH "SEE ALSO" .IX Header "SEE ALSO" Net::HTTP .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2001\-2017 by Gisle Aas. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. man/man3/DBI::Gofer::Transport::pipeone.3pm000044400000005251152462503210014211 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Transport::pipeone 3" .TH DBI::Gofer::Transport::pipeone 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Transport::pipeone \- DBD::Gofer server\-side transport for pipeone .SH "SYNOPSIS" .IX Header "SYNOPSIS" See DBD::Gofer::Transport::pipeone. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/DBD::File.3pm000044400000044711152462503210010160 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::File 3" .TH DBD::File 3 "2016-11-09" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::File \- Base class for writing file based DBI drivers .SH "SYNOPSIS" .IX Header "SYNOPSIS" This module is a base class for writing other \s-1DBD\s0s. It is not intended to function as a \s-1DBD\s0 itself (though it is possible). If you want to access flat files, use DBD::AnyData, or \&\s-1DBD::CSV\s0 (both of which are subclasses of DBD::File). .SH "DESCRIPTION" .IX Header "DESCRIPTION" The DBD::File module is not a true \s-1DBI\s0 driver, but an abstract base class for deriving concrete \s-1DBI\s0 drivers from it. The implication is, that these drivers work with plain files, for example \s-1CSV\s0 files or \&\s-1INI\s0 files. The module is based on the SQL::Statement module, a simple \s-1SQL\s0 engine. .PP See \s-1DBI\s0 for details on \s-1DBI,\s0 SQL::Statement for details on SQL::Statement and \s-1DBD::CSV\s0, \s-1DBD::DBM\s0 or DBD::AnyData for example drivers. .SS "Metadata" .IX Subsection "Metadata" The following attributes are handled by \s-1DBI\s0 itself and not by DBD::File, thus they all work as expected: .PP .Vb 10 \& Active \& ActiveKids \& CachedKids \& CompatMode (Not used) \& InactiveDestroy \& AutoInactiveDestroy \& Kids \& PrintError \& RaiseError \& Warn (Not used) .Ve .PP \fIThe following \s-1DBI\s0 attributes are handled by DBD::File:\fR .IX Subsection "The following DBI attributes are handled by DBD::File:" .PP AutoCommit .IX Subsection "AutoCommit" .PP Always on. .PP ChopBlanks .IX Subsection "ChopBlanks" .PP Works. .PP \s-1NUM_OF_FIELDS\s0 .IX Subsection "NUM_OF_FIELDS" .PP Valid after \f(CW\*(C`$sth\->execute\*(C'\fR. .PP \s-1NUM_OF_PARAMS\s0 .IX Subsection "NUM_OF_PARAMS" .PP Valid after \f(CW\*(C`$sth\->prepare\*(C'\fR. .PP \s-1NAME\s0 .IX Subsection "NAME" .PP Valid after \f(CW\*(C`$sth\->execute\*(C'\fR; undef for Non-Select statements. .PP \s-1NULLABLE\s0 .IX Subsection "NULLABLE" .PP Not really working, always returns an array ref of ones, except the affected table has been created in this session. Valid after \&\f(CW\*(C`$sth\->execute\*(C'\fR; undef for non-select statements. .PP \fIUnsupported \s-1DBI\s0 attributes and methods\fR .IX Subsection "Unsupported DBI attributes and methods" .PP bind_param_inout .IX Subsection "bind_param_inout" .PP CursorName .IX Subsection "CursorName" .PP LongReadLen .IX Subsection "LongReadLen" .PP LongTruncOk .IX Subsection "LongTruncOk" .PP \fIDBD::File specific attributes\fR .IX Subsection "DBD::File specific attributes" .PP In addition to the \s-1DBI\s0 attributes, you can use the following dbh attributes: .PP f_dir .IX Subsection "f_dir" .PP This attribute is used for setting the directory where the files are opened and it defaults to the current directory (\fI.\fR). Usually you set it on the dbh but it may be overridden per table (see f_meta). .PP When the value for \f(CW\*(C`f_dir\*(C'\fR is a relative path, it is converted into the appropriate absolute path name (based on the current working directory) when the dbh attribute is set. .PP .Vb 1 \& f_dir => "/data/foo/csv", .Ve .PP See \*(L"\s-1KNOWN BUGS AND LIMITATIONS\*(R"\s0. .PP f_dir_search .IX Subsection "f_dir_search" .PP This optional attribute can be set to pass a list of folders to also find existing tables. It will \fBnot\fR be used to create new files. .PP .Vb 1 \& f_dir_search => [ "/data/bar/csv", "/dump/blargh/data" ], .Ve .PP f_ext .IX Subsection "f_ext" .PP This attribute is used for setting the file extension. The format is: .PP .Vb 1 \& extension{/flag} .Ve .PP where the /flag is optional and the extension is case-insensitive. \&\f(CW\*(C`f_ext\*(C'\fR allows you to specify an extension which: .PP .Vb 1 \& f_ext => ".csv/r", .Ve .IP "\(bu" 4 makes DBD::File prefer \fItable.extension\fR over \fItable\fR. .IP "\(bu" 4 makes the table name the filename minus the extension. .PP .Vb 1 \& DBI:CSV:f_dir=data;f_ext=.csv .Ve .PP In the above example and when \f(CW\*(C`f_dir\*(C'\fR contains both \fItable.csv\fR and \&\fItable\fR, DBD::File will open \fItable.csv\fR and the table will be named \*(L"table\*(R". If \fItable.csv\fR does not exist but \fItable\fR does that file is opened and the table is also called \*(L"table\*(R". .PP If \f(CW\*(C`f_ext\*(C'\fR is not specified and \fItable.csv\fR exists it will be opened and the table will be called \*(L"table.csv\*(R" which is probably not what you want. .PP \&\s-1NOTE:\s0 even though extensions are case-insensitive, table names are not. .PP .Vb 1 \& DBI:CSV:f_dir=data;f_ext=.csv/r .Ve .PP The \f(CW\*(C`r\*(C'\fR flag means the file extension is required and any filename that does not match the extension is ignored. .PP Usually you set it on the dbh but it may be overridden per table (see f_meta). .PP f_schema .IX Subsection "f_schema" .PP This will set the schema name and defaults to the owner of the directory in which the table file resides. You can set \f(CW\*(C`f_schema\*(C'\fR to \&\f(CW\*(C`undef\*(C'\fR. .PP .Vb 5 \& my $dbh = DBI\->connect ("dbi:CSV:", "", "", { \& f_schema => undef, \& f_dir => "data", \& f_ext => ".csv/r", \& }) or die $DBI::errstr; .Ve .PP By setting the schema you affect the results from the tables call: .PP .Vb 1 \& my @tables = $dbh\->tables (); \& \& # no f_schema \& "merijn".foo \& "merijn".bar \& \& # f_schema => "dbi" \& "dbi".foo \& "dbi".bar \& \& # f_schema => undef \& foo \& bar .Ve .PP Defining \f(CW\*(C`f_schema\*(C'\fR to the empty string is equal to setting it to \f(CW\*(C`undef\*(C'\fR so the \s-1DSN\s0 can be \f(CW"dbi:CSV:f_schema=;f_dir=."\fR. .PP f_lock .IX Subsection "f_lock" .PP The \f(CW\*(C`f_lock\*(C'\fR attribute is used to set the locking mode on the opened table files. Note that not all platforms support locking. By default, tables are opened with a shared lock for reading, and with an exclusive lock for writing. The supported modes are: .PP .Vb 1 \& 0: No locking at all. \& \& 1: Shared locks will be used. \& \& 2: Exclusive locks will be used. .Ve .PP But see \s-1KNOWN BUGS\s0 below. .PP f_lockfile .IX Subsection "f_lockfile" .PP If you wish to use a lockfile extension other than \f(CW\*(C`.lck\*(C'\fR, simply specify the \f(CW\*(C`f_lockfile\*(C'\fR attribute: .PP .Vb 3 \& $dbh = DBI\->connect ("dbi:DBM:f_lockfile=.foo"); \& $dbh\->{f_lockfile} = ".foo"; \& $dbh\->{dbm_tables}{qux}{f_lockfile} = ".foo"; .Ve .PP If you wish to disable locking, set the \f(CW\*(C`f_lockfile\*(C'\fR to \f(CW0\fR. .PP .Vb 3 \& $dbh = DBI\->connect ("dbi:DBM:f_lockfile=0"); \& $dbh\->{f_lockfile} = 0; \& $dbh\->{dbm_tables}{qux}{f_lockfile} = 0; .Ve .PP f_encoding .IX Subsection "f_encoding" .PP With this attribute, you can set the encoding in which the file is opened. This is implemented using \f(CW\*(C`binmode $fh, ":encoding()"\*(C'\fR. .PP f_meta .IX Subsection "f_meta" .PP Private data area aliasing \*(L"sql_meta\*(R" in DBI::DBD::SqlEngine which contains information about the tables this module handles. Table meta data might not be available until the table has been accessed for the first time e.g., by issuing a select on it however it is possible to pre-initialize attributes for each table you use. .PP DBD::File recognizes the (public) attributes \f(CW\*(C`f_ext\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \&\f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_encoding\*(C'\fR, \f(CW\*(C`f_lock\*(C'\fR, \f(CW\*(C`f_lockfile\*(C'\fR, \f(CW\*(C`f_schema\*(C'\fR, in addition to the attributes \*(L"sql_meta\*(R" in DBI::DBD::SqlEngine already supports. Be very careful when modifying attributes you do not know, the consequence might be a destroyed or corrupted table. .PP \&\f(CW\*(C`f_file\*(C'\fR is an attribute applicable to table meta data only and you will not find a corresponding attribute in the dbh. Whilst it may be reasonable to have several tables with the same column names, it is not for the same file name. If you need access to the same file using different table names, use \f(CW\*(C`SQL::Statement\*(C'\fR as the \s-1SQL\s0 engine and the \&\f(CW\*(C`AS\*(C'\fR keyword: .PP .Vb 1 \& SELECT * FROM tbl AS t1, tbl AS t2 WHERE t1.id = t2.id .Ve .PP \&\f(CW\*(C`f_file\*(C'\fR can be an absolute path name or a relative path name but if it is relative, it is interpreted as being relative to the \f(CW\*(C`f_dir\*(C'\fR attribute of the table meta data. When \f(CW\*(C`f_file\*(C'\fR is set DBD::File will use \f(CW\*(C`f_file\*(C'\fR as specified and will not attempt to work out an alternative for \f(CW\*(C`f_file\*(C'\fR using the \f(CW\*(C`table name\*(C'\fR and \f(CW\*(C`f_ext\*(C'\fR attribute. .PP While \f(CW\*(C`f_meta\*(C'\fR is a private and readonly attribute (which means, you cannot modify it's values), derived drivers might provide restricted write access through another attribute. Well known accessors are \&\f(CW\*(C`csv_tables\*(C'\fR for \s-1DBD::CSV\s0, \f(CW\*(C`ad_tables\*(C'\fR for DBD::AnyData and \&\f(CW\*(C`dbm_tables\*(C'\fR for \s-1DBD::DBM\s0. .PP \fINew opportunities for attributes from DBI::DBD::SqlEngine\fR .IX Subsection "New opportunities for attributes from DBI::DBD::SqlEngine" .PP sql_table_source .IX Subsection "sql_table_source" .PP \&\f(CW\*(C`$dbh\->{sql_table_source}\*(C'\fR can be set to \&\fIDBD::File::TableSource::FileSystem\fR (and is the default setting of DBD::File). This provides usual behaviour of previous DBD::File releases on .PP .Vb 2 \& @ary = DBI\->data_sources ($driver); \& @ary = DBI\->data_sources ($driver, \e%attr); \& \& @ary = $dbh\->data_sources (); \& @ary = $dbh\->data_sources (\e%attr); \& \& @names = $dbh\->tables ($catalog, $schema, $table, $type); \& \& $sth = $dbh\->table_info ($catalog, $schema, $table, $type); \& $sth = $dbh\->table_info ($catalog, $schema, $table, $type, \e%attr); \& \& $dbh\->func ("list_tables"); .Ve .PP sql_data_source .IX Subsection "sql_data_source" .PP \&\f(CW\*(C`$dbh\->{sql_data_source}\*(C'\fR can be set to either \&\fIDBD::File::DataSource::File\fR, which is default and provides the well known behavior of DBD::File releases prior to 0.41, or \&\fIDBD::File::DataSource::Stream\fR, which reuses already opened file-handle for operations. .PP \fIInternally private attributes to deal with \s-1SQL\s0 backends\fR .IX Subsection "Internally private attributes to deal with SQL backends" .PP Do not modify any of these private attributes unless you understand the implications of doing so. The behavior of DBD::File and derived DBDs might be unpredictable when one or more of those attributes are modified. .PP sql_nano_version .IX Subsection "sql_nano_version" .PP Contains the version of loaded DBI::SQL::Nano. .PP sql_statement_version .IX Subsection "sql_statement_version" .PP Contains the version of loaded SQL::Statement. .PP sql_handler .IX Subsection "sql_handler" .PP Contains either the text 'SQL::Statement' or 'DBI::SQL::Nano'. .PP sql_ram_tables .IX Subsection "sql_ram_tables" .PP Contains optionally temporary tables. .PP sql_flags .IX Subsection "sql_flags" .PP Contains optional flags to instantiate the SQL::Parser parsing engine when SQL::Statement is used as \s-1SQL\s0 engine. See SQL::Parser for valid flags. .SS "Driver private methods" .IX Subsection "Driver private methods" \fIDefault \s-1DBI\s0 methods\fR .IX Subsection "Default DBI methods" .PP data_sources .IX Subsection "data_sources" .PP The \f(CW\*(C`data_sources\*(C'\fR method returns a list of subdirectories of the current directory in the form \*(L"dbi:CSV:f_dir=$dirname\*(R". .PP If you want to read the subdirectories of another directory, use .PP .Vb 2 \& my ($drh) = DBI\->install_driver ("CSV"); \& my (@list) = $drh\->data_sources (f_dir => "/usr/local/csv_data"); .Ve .PP \fIAdditional methods\fR .IX Subsection "Additional methods" .PP The following methods are only available via their documented name when DBD::File is used directly. Because this is only reasonable for testing purposes, the real names must be used instead. Those names can be computed by replacing the \f(CW\*(C`f_\*(C'\fR in the method name with the driver prefix. .PP f_versions .IX Subsection "f_versions" .PP Signature: .PP .Vb 6 \& sub f_versions (;$) \& { \& my ($table_name) = @_; \& $table_name ||= "."; \& ... \& } .Ve .PP Returns the versions of the driver, including the \s-1DBI\s0 version, the Perl version, DBI::PurePerl version (if DBI::PurePerl is active) and the version of the \s-1SQL\s0 engine in use. .PP .Vb 9 \& my $dbh = DBI\->connect ("dbi:File:"); \& my $f_versions = $dbh\->func ("f_versions"); \& print "$f_versions\en"; \& _\|_END_\|_ \& # DBD::File 0.41 using IO::File (1.16) \& # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.406 \& # DBI 1.623 \& # OS darwin (12.2.1) \& # Perl 5.017006 (darwin\-thread\-multi\-ld\-2level) .Ve .PP Called in list context, f_versions will return an array containing each line as single entry. .PP Some drivers might use the optional (table name) argument and modify version information related to the table (e.g. \s-1DBD::DBM\s0 provides storage backend information for the requested table, when it has a table name). .SH "KNOWN BUGS AND LIMITATIONS" .IX Header "KNOWN BUGS AND LIMITATIONS" .IP "\(bu" 4 This module uses flock () internally but flock is not available on all platforms. On MacOS and Windows 95 there is no locking at all (perhaps not so important on MacOS and Windows 95, as there is only a single user). .IP "\(bu" 4 The module stores details about the handled tables in a private area of the driver handle (\f(CW$drh\fR). This data area is not shared between different driver instances, so several \f(CW\*(C`DBI\->connect ()\*(C'\fR calls will cause different table instances and private data areas. .Sp This data area is filled for the first time when a table is accessed, either via an \s-1SQL\s0 statement or via \f(CW\*(C`table_info\*(C'\fR and is not destroyed until the table is dropped or the driver handle is released. Manual destruction is possible via f_clear_meta. .Sp The following attributes are preserved in the data area and will evaluated instead of driver globals: .RS 4 .IP "f_ext" 8 .IX Item "f_ext" .PD 0 .IP "f_dir" 8 .IX Item "f_dir" .IP "f_dir_search" 8 .IX Item "f_dir_search" .IP "f_lock" 8 .IX Item "f_lock" .IP "f_lockfile" 8 .IX Item "f_lockfile" .IP "f_encoding" 8 .IX Item "f_encoding" .IP "f_schema" 8 .IX Item "f_schema" .IP "col_names" 8 .IX Item "col_names" .IP "sql_identifier_case" 8 .IX Item "sql_identifier_case" .RE .RS 4 .PD .Sp The following attributes are preserved in the data area only and cannot be set globally. .IP "f_file" 8 .IX Item "f_file" .RE .RS 4 .Sp The following attributes are preserved in the data area only and are computed when initializing the data area: .IP "f_fqfn" 8 .IX Item "f_fqfn" .PD 0 .IP "f_fqbn" 8 .IX Item "f_fqbn" .IP "f_fqln" 8 .IX Item "f_fqln" .IP "table_name" 8 .IX Item "table_name" .RE .RS 4 .PD .Sp For \s-1DBD::CSV\s0 tables this means, once opened \*(L"foo.csv\*(R" as table named \*(L"foo\*(R", another table named \*(L"foo\*(R" accessing the file \*(L"foo.txt\*(R" cannot be opened. Accessing \*(L"foo\*(R" will always access the file \*(L"foo.csv\*(R" in memorized \&\f(CW\*(C`f_dir\*(C'\fR, locking \f(CW\*(C`f_lockfile\*(C'\fR via memorized \f(CW\*(C`f_lock\*(C'\fR. .Sp You can use f_clear_meta or the \f(CW\*(C`f_file\*(C'\fR attribute for a specific table to work around this. .RE .IP "\(bu" 4 When used with SQL::Statement and temporary tables e.g., .Sp .Vb 1 \& CREATE TEMP TABLE ... .Ve .Sp the table data processing bypasses DBD::File::Table. No file system calls will be made and there are no clashes with existing (file based) tables with the same name. Temporary tables are chosen over file tables, but they will not covered by \f(CW\*(C`table_info\*(C'\fR. .SH "AUTHOR" .IX Header "AUTHOR" This module is currently maintained by .PP H.Merijn Brand < h.m.brand at xs4all.nl > and Jens Rehsack < rehsack at googlemail.com > .PP The original author is Jochen Wiedmann. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" .Vb 3 \& Copyright (C) 2009\-2013 by H.Merijn Brand & Jens Rehsack \& Copyright (C) 2004\-2009 by Jeff Zucker \& Copyright (C) 1998\-2004 by Jochen Wiedmann .Ve .PP All rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1DBI\s0, \s-1DBD::DBM\s0, \s-1DBD::CSV\s0, Text::CSV, Text::CSV_XS, SQL::Statement, and DBI::SQL::Nano man/man3/Win32::DBIODBC.3pm000044400000005601152462503210010633 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Win32::DBIODBC 3" .TH Win32::DBIODBC 3 "2015-05-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Win32::DBIODBC \- Win32::ODBC emulation layer for the DBI .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Win32::DBIODBC; # instead of use Win32::ODBC .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is a \fIvery\fR basic \fIvery\fR alpha quality Win32::ODBC emulation for the \s-1DBI.\s0 To use it just replace .PP .Vb 1 \& use Win32::ODBC; .Ve .PP in your scripts with .PP .Vb 1 \& use Win32::DBIODBC; .Ve .PP or, while experimenting, you can pre-load this module without changing your scripts by doing .PP .Vb 1 \& perl \-MWin32::DBIODBC your_script_name .Ve .SH "TO DO" .IX Header "TO DO" Error handling is virtually non-existent. .SH "AUTHOR" .IX Header "AUTHOR" Tom Horen man/man3/libwww::lwpcook.3pm000044400000031305152462503210011674 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "lwpcook 3" .TH lwpcook 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" lwpcook \- The libwww\-perl cookbook .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document contain some examples that show typical usage of the libwww-perl library. You should consult the documentation for the individual modules for more detail. .PP All examples should be runnable programs. You can, in most cases, test the code sections by piping the program text directly to perl. .SH "GET" .IX Header "GET" It is very easy to use this library to just fetch documents from the net. The LWP::Simple module provides the \fBget()\fR function that return the document specified by its \s-1URL\s0 argument: .PP .Vb 2 \& use LWP::Simple; \& $doc = get \*(Aqhttp://search.cpan.org/dist/libwww\-perl/\*(Aq; .Ve .PP or, as a perl one-liner using the \fBgetprint()\fR function: .PP .Vb 1 \& perl \-MLWP::Simple \-e \*(Aqgetprint "http://search.cpan.org/dist/libwww\-perl/"\*(Aq .Ve .PP or, how about fetching the latest perl by running this command: .PP .Vb 3 \& perl \-MLWP::Simple \-e \*(Aq \& getstore "ftp://ftp.sunet.se/pub/lang/perl/CPAN/src/latest.tar.gz", \& "perl.tar.gz"\*(Aq .Ve .PP You will probably first want to find a \s-1CPAN\s0 site closer to you by running something like the following command: .PP .Vb 1 \& perl \-MLWP::Simple \-e \*(Aqgetprint "http://www.cpan.org/SITES.html"\*(Aq .Ve .PP Enough of this simple stuff! The \s-1LWP\s0 object oriented interface gives you more control over the request sent to the server. Using this interface you have full control over headers sent and how you want to handle the response returned. .PP .Vb 4 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& $ua\->agent("$0/0.1 " . $ua\->agent); \& # $ua\->agent("Mozilla/8.0") # pretend we are very capable browser \& \& $req = HTTP::Request\->new( \& GET => \*(Aqhttp://search.cpan.org/dist/libwww\-perl/\*(Aq); \& $req\->header(\*(AqAccept\*(Aq => \*(Aqtext/html\*(Aq); \& \& # send request \& $res = $ua\->request($req); \& \& # check the outcome \& if ($res\->is_success) { \& print $res\->decoded_content; \& } \& else { \& print "Error: " . $res\->status_line . "\en"; \& } .Ve .PP The lwp-request program (alias \s-1GET\s0) that is distributed with the library can also be used to fetch documents from \s-1WWW\s0 servers. .SH "HEAD" .IX Header "HEAD" If you just want to check if a document is present (i.e. the \s-1URL\s0 is valid) try to run code that looks like this: .PP .Vb 1 \& use LWP::Simple; \& \& if (head($url)) { \& # ok document exists \& } .Ve .PP The \fBhead()\fR function really returns a list of meta-information about the document. The first three values of the list returned are the document type, the size of the document, and the age of the document. .PP More control over the request or access to all header values returned require that you use the object oriented interface described for \s-1GET\s0 above. Just s/GET/HEAD/g. .SH "POST" .IX Header "POST" There is no simple procedural interface for posting data to a \s-1WWW\s0 server. You must use the object oriented interface for this. The most common \s-1POST\s0 operation is to access a \s-1WWW\s0 form application: .PP .Vb 2 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& \& my $req = HTTP::Request\->new( \& POST => \*(Aqhttps://rt.cpan.org/Public/Dist/Display.html\*(Aq); \& $req\->content_type(\*(Aqapplication/x\-www\-form\-urlencoded\*(Aq); \& $req\->content(\*(AqStatus=Active&Name=libwww\-perl\*(Aq); \& \& my $res = $ua\->request($req); \& print $res\->as_string; .Ve .PP Lazy people use the HTTP::Request::Common module to set up a suitable \&\s-1POST\s0 request message (it handles all the escaping issues) and has a suitable default for the content_type: .PP .Vb 3 \& use HTTP::Request::Common qw(POST); \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& \& my $req = POST \*(Aqhttps://rt.cpan.org/Public/Dist/Display.html\*(Aq, \& [ Status => \*(AqActive\*(Aq, Name => \*(Aqlibwww\-perl\*(Aq ]; \& \& print $ua\->request($req)\->as_string; .Ve .PP The lwp-request program (alias \s-1POST\s0) that is distributed with the library can also be used for posting data. .SH "PROXIES" .IX Header "PROXIES" Some sites use proxies to go through fire wall machines, or just as cache in order to improve performance. Proxies can also be used for accessing resources through protocols not supported directly (or supported badly :\-) by the libwww-perl library. .PP You should initialize your proxy setting before you start sending requests: .PP .Vb 7 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& $ua\->env_proxy; # initialize from environment variables \& # or \& $ua\->proxy(ftp => \*(Aqhttp://proxy.myorg.com\*(Aq); \& $ua\->proxy(wais => \*(Aqhttp://proxy.myorg.com\*(Aq); \& $ua\->no_proxy(qw(no se fi)); \& \& my $req = HTTP::Request\->new(GET => \*(Aqwais://xxx.com/\*(Aq); \& print $ua\->request($req)\->as_string; .Ve .PP The LWP::Simple interface will call \fBenv_proxy()\fR for you automatically. Applications that use the \f(CW$ua\fR\->\fBenv_proxy()\fR method will normally not use the \f(CW$ua\fR\->\fBproxy()\fR and \f(CW$ua\fR\->\fBno_proxy()\fR methods. .PP Some proxies also require that you send it a username/password in order to let requests through. You should be able to add the required header, with something like this: .PP .Vb 1 \& use LWP::UserAgent; \& \& $ua = LWP::UserAgent\->new; \& $ua\->proxy([\*(Aqhttp\*(Aq, \*(Aqftp\*(Aq] => \*(Aqhttp://username:password@proxy.myorg.com\*(Aq); \& \& $req = HTTP::Request\->new(\*(AqGET\*(Aq,"http://www.perl.com"); \& \& $res = $ua\->request($req); \& print $res\->decoded_content if $res\->is_success; .Ve .PP Replace \f(CW\*(C`proxy.myorg.com\*(C'\fR, \f(CW\*(C`username\*(C'\fR and \&\f(CW\*(C`password\*(C'\fR with something suitable for your site. .SH "ACCESS TO PROTECTED DOCUMENTS" .IX Header "ACCESS TO PROTECTED DOCUMENTS" Documents protected by basic authorization can easily be accessed like this: .PP .Vb 5 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& $req = HTTP::Request\->new(GET => \*(Aqhttp://www.linpro.no/secret/\*(Aq); \& $req\->authorization_basic(\*(Aqaas\*(Aq, \*(Aqmypassword\*(Aq); \& print $ua\->request($req)\->as_string; .Ve .PP The other alternative is to provide a subclass of \fILWP::UserAgent\fR that overrides the \fBget_basic_credentials()\fR method. Study the \fIlwp-request\fR program for an example of this. .SH "COOKIES" .IX Header "COOKIES" Some sites like to play games with cookies. By default \s-1LWP\s0 ignores cookies provided by the servers it visits. \s-1LWP\s0 will collect cookies and respond to cookie requests if you set up a cookie jar. \s-1LWP\s0 doesn't provide a cookie jar itself, but if you install HTTP::CookieJar::LWP, it can be used like this: .PP .Vb 2 \& use LWP::UserAgent; \& use HTTP::CookieJar::LWP; \& \& $ua = LWP::UserAgent\->new( \& cookie_jar => HTTP::CookieJar::LWP\->new, \& ); \& \& # and then send requests just as you used to do \& $res = $ua\->request(HTTP::Request\->new(GET => "http://no.yahoo.com/")); \& print $res\->status_line, "\en"; .Ve .SH "HTTPS" .IX Header "HTTPS" URLs with https scheme are accessed in exactly the same way as with http scheme, provided that an \s-1SSL\s0 interface module for \s-1LWP\s0 has been properly installed (see the \fI\s-1README.SSL\s0\fR file found in the libwww-perl distribution for more details). If no \s-1SSL\s0 interface is installed for \s-1LWP\s0 to use, then you will get \*(L"501 Protocol scheme \&'https' is not supported\*(R" errors when accessing such URLs. .PP Here's an example of fetching and printing a \s-1WWW\s0 page using \s-1SSL:\s0 .PP .Vb 1 \& use LWP::UserAgent; \& \& my $ua = LWP::UserAgent\->new; \& my $req = HTTP::Request\->new(GET => \*(Aqhttps://www.helsinki.fi/\*(Aq); \& my $res = $ua\->request($req); \& if ($res\->is_success) { \& print $res\->as_string; \& } \& else { \& print "Failed: ", $res\->status_line, "\en"; \& } .Ve .SH "MIRRORING" .IX Header "MIRRORING" If you want to mirror documents from a \s-1WWW\s0 server, then try to run code similar to this at regular intervals: .PP .Vb 1 \& use LWP::Simple; \& \& %mirrors = ( \& \*(Aqhttp://www.sn.no/\*(Aq => \*(Aqsn.html\*(Aq, \& \*(Aqhttp://www.perl.com/\*(Aq => \*(Aqperl.html\*(Aq, \& \*(Aqhttp://search.cpan.org/distlibwww\-perl/\*(Aq => \*(Aqlwp.html\*(Aq, \& \*(Aqgopher://gopher.sn.no/\*(Aq => \*(Aqgopher.html\*(Aq, \& ); \& \& while (($url, $localfile) = each(%mirrors)) { \& mirror($url, $localfile); \& } .Ve .PP Or, as a perl one-liner: .PP .Vb 1 \& perl \-MLWP::Simple \-e \*(Aqmirror("http://www.perl.com/", "perl.html")\*(Aq; .Ve .PP The document will not be transferred unless it has been updated. .SH "LARGE DOCUMENTS" .IX Header "LARGE DOCUMENTS" If the document you want to fetch is too large to be kept in memory, then you have two alternatives. You can instruct the library to write the document content to a file (second \f(CW$ua\fR\->\fBrequest()\fR argument is a file name): .PP .Vb 2 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& \& my $req = HTTP::Request\->new(GET => \& \*(Aqhttp://www.cpan.org/CPAN/authors/id/O/OA/OALDERS/libwww\-perl\-6.26.tar.gz\*(Aq); \& $res = $ua\->request($req, "libwww\-perl.tar.gz"); \& if ($res\->is_success) { \& print "ok\en"; \& } \& else { \& print $res\->status_line, "\en"; \& } .Ve .PP Or you can process the document as it arrives (second \f(CW$ua\fR\->\fBrequest()\fR argument is a code reference): .PP .Vb 3 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& $URL = \*(Aqftp://ftp.isc.org/pub/rfc/rfc\-index.txt\*(Aq; \& \& my $expected_length; \& my $bytes_received = 0; \& my $res = \& $ua\->request(HTTP::Request\->new(GET => $URL), \& sub { \& my($chunk, $res) = @_; \& $bytes_received += length($chunk); \& unless (defined $expected_length) { \& $expected_length = $res\->content_length || 0; \& } \& if ($expected_length) { \& printf STDERR "%d%% \- ", \& 100 * $bytes_received / $expected_length; \& } \& print STDERR "$bytes_received bytes received\en"; \& \& # XXX Should really do something with the chunk itself \& # print $chunk; \& }); \& print $res\->status_line, "\en"; .Ve .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 1996\-2001, Gisle Aas .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::Gofer::Request.3pm000044400000005224152462503210012101 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Request 3" .TH DBI::Gofer::Request 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Request \- Encapsulate a request from DBD::Gofer to DBI::Gofer::Execute .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is an internal class. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/JSON::backportPP::Compat5006.3pm000044400000005200152462503210013357 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::backportPP::Compat5006 3" .TH JSON::backportPP::Compat5006 3 "2021-01-17" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::PP56 \- Helper module in using JSON::PP in Perl 5.6 .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1JSON::PP\s0 calls internally. .SH "AUTHOR" .IX Header "AUTHOR" Makamaka Hannyaharamitu, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2007\-2012 by Makamaka Hannyaharamitu .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::DBD::SqlEngine.3pm000044400000051402152462503210011664 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::DBD::SqlEngine 3" .TH DBI::DBD::SqlEngine 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::DBD::SqlEngine \- Base class for DBI drivers without their own SQL engine .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& package DBD::myDriver; \& \& use base qw(DBI::DBD::SqlEngine); \& \& sub driver \& { \& ... \& my $drh = $proto\->SUPER::driver($attr); \& ... \& return $drh\->{class}; \& } \& \& package DBD::myDriver::dr; \& \& @ISA = qw(DBI::DBD::SqlEngine::dr); \& \& sub data_sources { ... } \& ... \& \& package DBD::myDriver::db; \& \& @ISA = qw(DBI::DBD::SqlEngine::db); \& \& sub init_valid_attributes { ... } \& sub init_default_attributes { ... } \& sub set_versions { ... } \& sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } \& sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } \& sub get_myd_versions { ... } \& sub get_avail_tables { ... } \& \& package DBD::myDriver::st; \& \& @ISA = qw(DBI::DBD::SqlEngine::st); \& \& sub FETCH { ... } \& sub STORE { ... } \& \& package DBD::myDriver::Statement; \& \& @ISA = qw(DBI::DBD::SqlEngine::Statement); \& \& sub open_table { ... } \& \& package DBD::myDriver::Table; \& \& @ISA = qw(DBI::DBD::SqlEngine::Table); \& \& sub new { ... } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBI::DBD::SqlEngine abstracts the usage of \s-1SQL\s0 engines from the \&\s-1DBD. DBD\s0 authors can concentrate on the data retrieval they want to provide. .PP It is strongly recommended that you read DBD::File::Developers and DBD::File::Roadmap, because many of the DBD::File \s-1API\s0 is provided by DBI::DBD::SqlEngine. .PP Currently the \s-1API\s0 of DBI::DBD::SqlEngine is experimental and will likely change in the near future to provide the table meta data basics like DBD::File. .PP DBI::DBD::SqlEngine expects that any driver in inheritance chain has a \s-1DBI\s0 prefix. .SS "Metadata" .IX Subsection "Metadata" The following attributes are handled by \s-1DBI\s0 itself and not by DBI::DBD::SqlEngine, thus they all work as expected: .PP .Vb 10 \& Active \& ActiveKids \& CachedKids \& CompatMode (Not used) \& InactiveDestroy \& AutoInactiveDestroy \& Kids \& PrintError \& RaiseError \& Warn (Not used) .Ve .PP \fIThe following \s-1DBI\s0 attributes are handled by DBI::DBD::SqlEngine:\fR .IX Subsection "The following DBI attributes are handled by DBI::DBD::SqlEngine:" .PP AutoCommit .IX Subsection "AutoCommit" .PP Always on. .PP ChopBlanks .IX Subsection "ChopBlanks" .PP Works. .PP \s-1NUM_OF_FIELDS\s0 .IX Subsection "NUM_OF_FIELDS" .PP Valid after \f(CW\*(C`$sth\->execute\*(C'\fR. .PP \s-1NUM_OF_PARAMS\s0 .IX Subsection "NUM_OF_PARAMS" .PP Valid after \f(CW\*(C`$sth\->prepare\*(C'\fR. .PP \s-1NAME\s0 .IX Subsection "NAME" .PP Valid after \f(CW\*(C`$sth\->execute\*(C'\fR; probably undef for Non-Select statements. .PP \s-1NULLABLE\s0 .IX Subsection "NULLABLE" .PP Not really working, always returns an array ref of ones, as \s-1DBD::CSV\s0 does not verify input data. Valid after \f(CW\*(C`$sth\->execute\*(C'\fR; undef for non-select statements. .PP \fIThe following \s-1DBI\s0 attributes and methods are not supported:\fR .IX Subsection "The following DBI attributes and methods are not supported:" .IP "bind_param_inout" 4 .IX Item "bind_param_inout" .PD 0 .IP "CursorName" 4 .IX Item "CursorName" .IP "LongReadLen" 4 .IX Item "LongReadLen" .IP "LongTruncOk" 4 .IX Item "LongTruncOk" .PD .PP \fIDBI::DBD::SqlEngine specific attributes\fR .IX Subsection "DBI::DBD::SqlEngine specific attributes" .PP In addition to the \s-1DBI\s0 attributes, you can use the following dbh attributes: .PP sql_engine_version .IX Subsection "sql_engine_version" .PP Contains the module version of this driver (\fBreadonly\fR) .PP sql_nano_version .IX Subsection "sql_nano_version" .PP Contains the module version of DBI::SQL::Nano (\fBreadonly\fR) .PP sql_statement_version .IX Subsection "sql_statement_version" .PP Contains the module version of SQL::Statement, if available (\fBreadonly\fR) .PP sql_handler .IX Subsection "sql_handler" .PP Contains the \s-1SQL\s0 Statement engine, either DBI::SQL::Nano or SQL::Statement (\fBreadonly\fR). .PP sql_parser_object .IX Subsection "sql_parser_object" .PP Contains an instantiated instance of SQL::Parser (\fBreadonly\fR). This is filled when used first time (only when used with SQL::Statement). .PP sql_sponge_driver .IX Subsection "sql_sponge_driver" .PP Contains an internally used DBD::Sponge handle (\fBreadonly\fR). .PP sql_valid_attrs .IX Subsection "sql_valid_attrs" .PP Contains the list of valid attributes for each DBI::DBD::SqlEngine based driver (\fBreadonly\fR). .PP sql_readonly_attrs .IX Subsection "sql_readonly_attrs" .PP Contains the list of those attributes which are readonly (\fBreadonly\fR). .PP sql_identifier_case .IX Subsection "sql_identifier_case" .PP Contains how DBI::DBD::SqlEngine deals with non-quoted \s-1SQL\s0 identifiers: .PP .Vb 5 \& * SQL_IC_UPPER (1) means all identifiers are internally converted \& into upper\-cased pendants \& * SQL_IC_LOWER (2) means all identifiers are internally converted \& into lower\-cased pendants \& * SQL_IC_MIXED (4) means all identifiers are taken as they are .Ve .PP These conversions happen if (and only if) no existing identifier matches. Once existing identifier is used as known. .PP The \s-1SQL\s0 statement execution classes doesn't have to care, so don't expect \&\f(CW\*(C`sql_identifier_case\*(C'\fR affects column names in statements like .PP .Vb 1 \& SELECT * FROM foo .Ve .PP sql_quoted_identifier_case .IX Subsection "sql_quoted_identifier_case" .PP Contains how DBI::DBD::SqlEngine deals with quoted \s-1SQL\s0 identifiers (\fBreadonly\fR). It's fixated to \s-1SQL_IC_SENSITIVE\s0 (3), which is interpreted as \s-1SQL_IC_MIXED.\s0 .PP sql_flags .IX Subsection "sql_flags" .PP Contains additional flags to instantiate an SQL::Parser. Because an SQL::Parser is instantiated only once, it's recommended to set this flag before any statement is executed. .PP sql_dialect .IX Subsection "sql_dialect" .PP Controls the dialect understood by SQL::Parser. Possible values (delivery state of SQL::Statement): .PP .Vb 3 \& * ANSI \& * CSV \& * AnyData .Ve .PP Defaults to \*(L"\s-1CSV\*(R".\s0 Because an SQL::Parser is instantiated only once and SQL::Parser doesn't allow one to modify the dialect once instantiated, it's strongly recommended to set this flag before any statement is executed (best place is connect attribute hash). .PP sql_engine_in_gofer .IX Subsection "sql_engine_in_gofer" .PP This value has a true value in case of this driver is operated via DBD::Gofer. The impact of being operated via Gofer is a read-only driver (not read-only databases!), so you cannot modify any attributes later \- neither any table settings. \fBBut\fR you won't get an error in cases you modify table attributes, so please carefully watch \&\f(CW\*(C`sql_engine_in_gofer\*(C'\fR. .PP sql_meta .IX Subsection "sql_meta" .PP Private data area which contains information about the tables this module handles. Table meta data might not be available until the table has been accessed for the first time e.g., by issuing a select on it however it is possible to pre-initialize attributes for each table you use. .PP DBI::DBD::SqlEngine recognizes the (public) attributes \f(CW\*(C`col_names\*(C'\fR, \&\f(CW\*(C`table_name\*(C'\fR, \f(CW\*(C`readonly\*(C'\fR, \f(CW\*(C`sql_data_source\*(C'\fR and \f(CW\*(C`sql_identifier_case\*(C'\fR. Be very careful when modifying attributes you do not know, the consequence might be a destroyed or corrupted table. .PP While \f(CW\*(C`sql_meta\*(C'\fR is a private and readonly attribute (which means, you cannot modify it's values), derived drivers might provide restricted write access through another attribute. Well known accessors are \&\f(CW\*(C`csv_tables\*(C'\fR for \s-1DBD::CSV\s0, \f(CW\*(C`ad_tables\*(C'\fR for DBD::AnyData and \&\f(CW\*(C`dbm_tables\*(C'\fR for \s-1DBD::DBM\s0. .PP sql_table_source .IX Subsection "sql_table_source" .PP Controls the class which will be used for fetching available tables. .PP See \*(L"DBI::DBD::SqlEngine::TableSource\*(R" for details. .PP sql_data_source .IX Subsection "sql_data_source" .PP Contains the class name to be used for opening tables. .PP See \*(L"DBI::DBD::SqlEngine::DataSource\*(R" for details. .SS "Driver private methods" .IX Subsection "Driver private methods" \fIDefault \s-1DBI\s0 methods\fR .IX Subsection "Default DBI methods" .PP data_sources .IX Subsection "data_sources" .PP The \f(CW\*(C`data_sources\*(C'\fR method returns a list of subdirectories of the current directory in the form \*(L"dbi:CSV:f_dir=$dirname\*(R". .PP If you want to read the subdirectories of another directory, use .PP .Vb 2 \& my ($drh) = DBI\->install_driver ("CSV"); \& my (@list) = $drh\->data_sources (f_dir => "/usr/local/csv_data"); .Ve .PP list_tables .IX Subsection "list_tables" .PP This method returns a list of file names inside \f(CW$dbh\fR\->{f_dir}. Example: .PP .Vb 2 \& my ($dbh) = DBI\->connect ("dbi:CSV:f_dir=/usr/local/csv_data"); \& my (@list) = $dbh\->func ("list_tables"); .Ve .PP Note that the list includes all files contained in the directory, even those that have non-valid table names, from the view of \s-1SQL.\s0 .PP \fIAdditional methods\fR .IX Subsection "Additional methods" .PP The following methods are only available via their documented name when DBI::DBD::SQlEngine is used directly. Because this is only reasonable for testing purposes, the real names must be used instead. Those names can be computed by replacing the \f(CW\*(C`sql_\*(C'\fR in the method name with the driver prefix. .PP sql_versions .IX Subsection "sql_versions" .PP Signature: .PP .Vb 5 \& sub sql_versions (;$) { \& my ($table_name) = @_; \& $table_name ||= "."; \& ... \& } .Ve .PP Returns the versions of the driver, including the \s-1DBI\s0 version, the Perl version, DBI::PurePerl version (if DBI::PurePerl is active) and the version of the \s-1SQL\s0 engine in use. .PP .Vb 8 \& my $dbh = DBI\->connect ("dbi:File:"); \& my $sql_versions = $dbh\->func( "sql_versions" ); \& print "$sql_versions\en"; \& _\|_END_\|_ \& # DBI::DBD::SqlEngine 0.05 using SQL::Statement 1.402 \& # DBI 1.623 \& # OS netbsd (6.99.12) \& # Perl 5.016002 (x86_64\-netbsd\-thread\-multi) .Ve .PP Called in list context, sql_versions will return an array containing each line as single entry. .PP Some drivers might use the optional (table name) argument and modify version information related to the table (e.g. \s-1DBD::DBM\s0 provides storage backend information for the requested table, when it has a table name). .PP sql_get_meta .IX Subsection "sql_get_meta" .PP Signature: .PP .Vb 5 \& sub sql_get_meta ($$) \& { \& my ($table_name, $attrib) = @_; \& ... \& } .Ve .PP Returns the value of a meta attribute set for a specific table, if any. See sql_meta for the possible attributes. .PP A table name of \f(CW"."\fR (single dot) is interpreted as the default table. This will retrieve the appropriate attribute globally from the dbh. This has the same restrictions as \f(CW\*(C`$dbh\->{$attrib}\*(C'\fR. .PP sql_set_meta .IX Subsection "sql_set_meta" .PP Signature: .PP .Vb 5 \& sub sql_set_meta ($$$) \& { \& my ($table_name, $attrib, $value) = @_; \& ... \& } .Ve .PP Sets the value of a meta attribute set for a specific table. See sql_meta for the possible attributes. .PP A table name of \f(CW"."\fR (single dot) is interpreted as the default table which will set the specified attribute globally for the dbh. This has the same restrictions as \f(CW\*(C`$dbh\->{$attrib} = $value\*(C'\fR. .PP sql_clear_meta .IX Subsection "sql_clear_meta" .PP Signature: .PP .Vb 5 \& sub sql_clear_meta ($) \& { \& my ($table_name) = @_; \& ... \& } .Ve .PP Clears the table specific meta information in the private storage of the dbh. .SS "Extensibility" .IX Subsection "Extensibility" \fIDBI::DBD::SqlEngine::TableSource\fR .IX Subsection "DBI::DBD::SqlEngine::TableSource" .PP Provides data sources and table information on database driver and database handle level. .PP .Vb 1 \& package DBI::DBD::SqlEngine::TableSource; \& \& sub data_sources ($;$) \& { \& my ( $class, $drh, $attrs ) = @_; \& ... \& } \& \& sub avail_tables \& { \& my ( $class, $drh ) = @_; \& ... \& } .Ve .PP The \f(CW\*(C`data_sources\*(C'\fR method is called when the user invokes any of the following: .PP .Vb 2 \& @ary = DBI\->data_sources($driver); \& @ary = DBI\->data_sources($driver, \e%attr); \& \& @ary = $dbh\->data_sources(); \& @ary = $dbh\->data_sources(\e%attr); .Ve .PP The \f(CW\*(C`avail_tables\*(C'\fR method is called when the user invokes any of the following: .PP .Vb 1 \& @names = $dbh\->tables( $catalog, $schema, $table, $type ); \& \& $sth = $dbh\->table_info( $catalog, $schema, $table, $type ); \& $sth = $dbh\->table_info( $catalog, $schema, $table, $type, \e%attr ); \& \& $dbh\->func( "list_tables" ); .Ve .PP Every time where an \f(CW\*(C`\e%attr\*(C'\fR argument can be specified, this \f(CW\*(C`\e%attr\*(C'\fR object's \f(CW\*(C`sql_table_source\*(C'\fR attribute is preferred over the \f(CW$dbh\fR attribute or the driver default, eg. .PP .Vb 6 \& @ary = DBI\->data_sources("dbi:CSV:", { \& f_dir => "/your/csv/tables", \& # note: this class doesn\*(Aqt comes with DBI \& sql_table_source => "DBD::File::Archive::Tar::TableSource", \& # scan tarballs instead of directories \& }); .Ve .PP When you're going to implement such a DBD::File::Archive::Tar::TableSource class, remember to add correct attributes (including \f(CW\*(C`sql_table_source\*(C'\fR and \f(CW\*(C`sql_data_source\*(C'\fR) to the returned \s-1DSN\s0's. .PP \fIDBI::DBD::SqlEngine::DataSource\fR .IX Subsection "DBI::DBD::SqlEngine::DataSource" .PP Provides base functionality for dealing with tables. It is primarily designed for allowing transparent access to files on disk or already opened (file\-)streams (eg. for \s-1DBD::CSV\s0). .PP Derived classes shall be restricted to similar functionality, too (eg. opening streams from an archive, transparently compress/uncompress log files before parsing them, .PP .Vb 1 \& package DBI::DBD::SqlEngine::DataSource; \& \& sub complete_table_name ($$;$) \& { \& my ( $self, $meta, $table, $respect_case ) = @_; \& ... \& } .Ve .PP The method \f(CW\*(C`complete_table_name\*(C'\fR is called when first setting up the \&\fImeta information\fR for a table: .PP .Vb 1 \& "SELECT user.id, user.name, user.shell FROM user WHERE ..." .Ve .PP results in opening the table \f(CW\*(C`user\*(C'\fR. First step of the table open process is completing the name. Let's imagine you're having a \s-1DBD::CSV\s0 handle with following settings: .PP .Vb 3 \& $dbh\->{sql_identifier_case} = SQL_IC_LOWER; \& $dbh\->{f_ext} = \*(Aq.lst\*(Aq; \& $dbh\->{f_dir} = \*(Aq/data/web/adrmgr\*(Aq; .Ve .PP Those settings will result in looking for files matching \&\f(CW\*(C`[Uu][Ss][Ee][Rr](\e.lst)?$\*(C'\fR in \f(CW\*(C`/data/web/adrmgr/\*(C'\fR. The scanning of the directory \f(CW\*(C`/data/web/adrmgr/\*(C'\fR and the pattern match check will be done in \f(CW\*(C`DBD::File::DataSource::File\*(C'\fR by the \f(CW\*(C`complete_table_name\*(C'\fR method. .PP If you intend to provide other sources of data streams than files, in addition to provide an appropriate \f(CW\*(C`complete_table_name\*(C'\fR method, a method to open the resource is required: .PP .Vb 1 \& package DBI::DBD::SqlEngine::DataSource; \& \& sub open_data ($) \& { \& my ( $self, $meta, $attrs, $flags ) = @_; \& ... \& } .Ve .PP After the method \f(CW\*(C`open_data\*(C'\fR has been run successfully, the table's meta information are in a state which allowes the table's data accessor methods will be able to fetch/store row information. Implementation details heavily depends on the table implementation, whereby the most famous is surely DBD::File::Table. .SH "SQL ENGINES" .IX Header "SQL ENGINES" DBI::DBD::SqlEngine currently supports two \s-1SQL\s0 engines: SQL::Statement and DBI::SQL::Nano::Statement_. DBI::SQL::Nano supports a \&\fIvery\fR limited subset of \s-1SQL\s0 statements, but it might be faster for some very simple tasks. SQL::Statement in contrast supports a much larger subset of \s-1ANSI SQL.\s0 .PP To use SQL::Statement, you need at least version 1.401 of SQL::Statement and the environment variable \f(CW\*(C`DBI_SQL_NANO\*(C'\fR must not be set to a true value. .SH "SUPPORT" .IX Header "SUPPORT" You can find documentation for this module with the perldoc command. .PP .Vb 1 \& perldoc DBI::DBD::SqlEngine .Ve .PP You can also look for information at: .IP "\(bu" 4 \&\s-1RT: CPAN\s0's request tracker .Sp .IP "\(bu" 4 AnnoCPAN: Annotated \s-1CPAN\s0 documentation .Sp .IP "\(bu" 4 \&\s-1CPAN\s0 Ratings .Sp .IP "\(bu" 4 Search \s-1CPAN\s0 .Sp .SS "Where can I go for more help?" .IX Subsection "Where can I go for more help?" For questions about installation or usage, please ask on the dbi\-dev@perl.org mailing list. .PP If you have a bug report, patch or suggestion, please open a new report ticket on \s-1CPAN,\s0 if there is not already one for the issue you want to report. Of course, you can mail any of the module maintainers, but it is less likely to be missed if it is reported on \s-1RT.\s0 .PP Report tickets should contain a detailed description of the bug or enhancement request you want to report and at least an easy way to verify/reproduce the issue and any supplied fix. Patches are always welcome, too. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" Thanks to Tim Bunce, Martin Evans and H.Merijn Brand for their continued support while developing DBD::File, \s-1DBD::DBM\s0 and DBD::AnyData. Their support, hints and feedback helped to design and implement this module. .SH "AUTHOR" .IX Header "AUTHOR" This module is currently maintained by .PP H.Merijn Brand < h.m.brand at xs4all.nl > and Jens Rehsack < rehsack at googlemail.com > .PP The original authors are Jochen Wiedmann and Jeff Zucker. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" .Vb 3 \& Copyright (C) 2009\-2013 by H.Merijn Brand & Jens Rehsack \& Copyright (C) 2004\-2009 by Jeff Zucker \& Copyright (C) 1998\-2004 by Jochen Wiedmann .Ve .PP All rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1DBI\s0, DBD::File, DBD::AnyData and DBD::Sys. man/man3/LWP::Authen::Ntlm.3pm000044400000013120152462503210011603 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::Authen::Ntlm 3" .TH LWP::Authen::Ntlm 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::Authen::Ntlm \- Library for enabling NTLM authentication (Microsoft) in LWP .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use LWP::UserAgent; \& use HTTP::Request::Common; \& my $url = \*(Aqhttp://www.company.com/protected_page.html\*(Aq; \& \& # Set up the ntlm client and then the base64 encoded ntlm handshake message \& my $ua = LWP::UserAgent\->new(keep_alive=>1); \& $ua\->credentials(\*(Aqwww.company.com:80\*(Aq, \*(Aq\*(Aq, "MyDomain\e\eMyUserCode", \*(AqMyPassword\*(Aq); \& \& $request = GET $url; \& print "\-\-Performing request now...\-\-\-\-\-\-\-\-\-\-\-\en"; \& $response = $ua\->request($request); \& print "\-\-Done with request\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\en"; \& \& if ($response\->is_success) {print "It worked!\->" . $response\->code . "\en"} \& else {print "It didn\*(Aqt work!\->" . $response\->code . "\en"} .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" LWP::Authen::Ntlm allows \s-1LWP\s0 to authenticate against servers that are using the \&\s-1NTLM\s0 authentication scheme popularized by Microsoft. This type of authentication is common on intranets of Microsoft-centric organizations. .PP The module takes advantage of the Authen::NTLM module by Mark Bush. Since there is also another Authen::NTLM module available from \s-1CPAN\s0 by Yee Man Chan with an entirely different interface, it is necessary to ensure that you have the correct \&\s-1NTLM\s0 module. .PP In addition, there have been problems with incompatibilities between different versions of Mime::Base64, which Bush's Authen::NTLM makes use of. Therefore, it is necessary to ensure that your Mime::Base64 module supports exporting of the \&\f(CW\*(C`encode_base64\*(C'\fR and \f(CW\*(C`decode_base64\*(C'\fR functions. .SH "USAGE" .IX Header "USAGE" The module is used indirectly through \s-1LWP,\s0 rather than including it directly in your code. The \s-1LWP\s0 system will invoke the \s-1NTLM\s0 authentication when it encounters the authentication scheme while attempting to retrieve a \s-1URL\s0 from a server. In order for the \s-1NTLM\s0 authentication to work, you must have a few things set up in your code prior to attempting to retrieve the \s-1URL:\s0 .IP "\(bu" 4 Enable persistent \s-1HTTP\s0 connections .Sp To do this, pass the \f(CW"keep_alive=>1"\fR option to the LWP::UserAgent when creating it, like this: .Sp .Vb 1 \& my $ua = LWP::UserAgent\->new(keep_alive=>1); .Ve .IP "\(bu" 4 Set the credentials on the UserAgent object .Sp The credentials must be set like this: .Sp .Vb 1 \& $ua\->credentials(\*(Aqwww.company.com:80\*(Aq, \*(Aq\*(Aq, "MyDomain\e\eMyUserCode", \*(AqMyPassword\*(Aq); .Ve .Sp Note that you cannot use the HTTP::Request object's \f(CW\*(C`authorization_basic()\*(C'\fR method to set the credentials. Note, too, that the \f(CW\*(Aqwww.company.com:80\*(Aq\fR portion only sets credentials on the specified port \s-1AND\s0 it is case-sensitive (this is due to the way \s-1LWP\s0 is coded, and has nothing to do with LWP::Authen::Ntlm) .SH "AVAILABILITY" .IX Header "AVAILABILITY" General queries regarding \s-1LWP\s0 should be made to the \s-1LWP\s0 Mailing List. .PP Questions specific to LWP::Authen::Ntlm can be forwarded to jtillman@bigfoot.com .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2002 James Tillman. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1LWP\s0, LWP::UserAgent, lwpcook. man/man3/DBD::mysql::INSTALL.3pm000044400000070571152462503210011664 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::mysql::INSTALL 3" .TH DBD::mysql::INSTALL 3 "2018-10-07" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::mysql::INSTALL \- How to install and configure DBD::mysql .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 4 \& perl Makefile.PL [options] \& make \& make test \& make install .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document describes the installation and configuration of DBD::mysql, the Perl \s-1DBI\s0 driver for the MySQL database. Before reading on, make sure that you have the prerequisites available: Perl, MySQL and \s-1DBI.\s0 For details see the separate section \&\*(L"\s-1PREREQUISITES\*(R"\s0. .PP Depending on your version of Perl, it might be possible to use a binary distribution of DBD::mysql. If possible, this is recommended. Otherwise you need to install from the sources. If so, you will definitely need a C compiler. Installation from binaries and sources are both described in separate sections. \*(L"\s-1BINARY INSTALLATION\*(R"\s0. \*(L"\s-1SOURCE INSTALLATION\*(R"\s0. .PP Finally, if you encounter any problems, do not forget to read the section on known problems \*(L"\s-1KNOWN PROBLEMS\*(R"\s0. If that doesn't help, you should check the section on \*(L"\s-1SUPPORT\*(R"\s0. .SH "PREREQUISITES" .IX Header "PREREQUISITES" .IP "Perl" 4 .IX Item "Perl" Preferably a version of Perl, that comes preconfigured with your system. For example, all Linux and FreeBSD distributions come with Perl. For Windows, use ActivePerl or Strawberry Perl . .IP "MySQL" 4 .IX Item "MySQL" You need not install the actual MySQL database server, the client files and the development files are sufficient. For example, Fedora Linux distribution comes with \s-1RPM\s0 files (using \s-1YUM\s0) \fBmysql\fR and \fBmysql-server\fR (use \*(L"yum search\*(R" to find exact package names). These are sufficient, if the MySQL server is located on a foreign machine. You may also create client files by compiling from the MySQL source distribution and using .Sp .Vb 1 \& configure \-\-without\-server .Ve .Sp If you are using Windows and need to compile from sources (which is only the case if you are not using ActivePerl or Strawberry Perl), then you must ensure that the header and library files are installed. This may require choosing a \*(L"Custom installation\*(R" and selecting the appropriate option when running the MySQL setup program. .IP "\s-1DBI\s0" 4 .IX Item "DBI" DBD::mysql is a \s-1DBI\s0 driver, hence you need \s-1DBI.\s0 It is available from the same source where you got the DBD::mysql distribution from. .IP "C compiler" 4 .IX Item "C compiler" A C compiler is only required if you install from source. In most cases there are binary distributions of DBD::mysql available. However, if you need a C compiler, make sure, that it is the same C compiler that was used for compiling Perl and MySQL! Otherwise you will almost definitely encounter problems because of differences in the underlying C runtime libraries. .Sp In the worst case, this might mean to compile Perl and MySQL yourself. But believe me, experience shows that a lot of problems are fixed this way. .IP "Gzip libraries" 4 .IX Item "Gzip libraries" Late versions of MySQL come with support for compression. Thus it \fBmay\fR be required that you have install an \s-1RPM\s0 package like libz-devel, libgz-devel or something similar. .SH "BINARY INSTALLATION" .IX Header "BINARY INSTALLATION" Binary installation is possible in the most cases, depending on your system. .SS "Windows" .IX Subsection "Windows" \fIStrawberry Perl\fR .IX Subsection "Strawberry Perl" .PP Strawberry Perl comes bundled with DBD::mysql and the needed client libraries. .PP \fIActiveState Perl\fR .IX Subsection "ActiveState Perl" .PP ActivePerl offers a \s-1PPM\s0 archive of DBD::mysql. All you need to do is typing in a cmd.exe window: .PP .Vb 1 \& ppm install DBD\-mysql .Ve .PP This will fetch the module via \s-1HTTP\s0 and install them. If you need to use a \s-1WWW\s0 proxy server, the environment variable HTTP_proxy must be set: .PP .Vb 2 \& set HTTP_proxy=http://myproxy.example.com:8080/ \& ppm install DBD\-mysql .Ve .PP Of course you need to replace the host name \f(CW\*(C`myproxy.example.com\*(C'\fR and the port number \f(CW8080\fR with your local values. .PP If the above procedure doesn't work, please upgrade to the latest version of ActivePerl. ActiveState has a policy where it only provides access free-of-charge for the \s-1PPM\s0 mirrors of the last few stable Perl releases. If you have an older perl, you'd either need to upgrade your perl or contact ActiveState about a subscription. .SS "Red Hat Enterprise Linux (\s-1RHEL\s0), CentOS and Fedora" .IX Subsection "Red Hat Enterprise Linux (RHEL), CentOS and Fedora" Red Hat Enterprise Linux, its community derivatives such as CentOS, and Fedora come with MySQL and DBD::mysql. .PP Use the following command to install DBD::mysql: .PP .Vb 1 \& yum install "perl(DBD::mysql)" .Ve .SS "Debian and Ubuntu" .IX Subsection "Debian and Ubuntu" On Debian, Ubuntu and derivatives you can install DBD::mysql from the repositories with the following command: .PP .Vb 1 \& sudo apt\-get install libdbd\-mysql\-perl .Ve .SS "\s-1SLES\s0 and openSUSE" .IX Subsection "SLES and openSUSE" On \s-1SUSE\s0 Linux Enterprise and the community version openSUSE, you can install DBD::mysql from the repositories with the following command: .PP .Vb 1 \& zypper install perl\-DBD\-mysql .Ve .SS "Other systems" .IX Subsection "Other systems" In the case of other Linux or FreeBSD distributions it is very likely that all you need comes with your distribution. I just cannot give you names, as I am not using these systems. .PP Please let me know if you find the files in your favorite Linux or FreeBSD distribution so that I can extend the above list. .SH "SOURCE INSTALLATION" .IX Header "SOURCE INSTALLATION" So you need to install from sources. If you are lucky, the Perl module \f(CW\*(C`CPAN\*(C'\fR will do all for you, thanks to the excellent work of Andreas König. Otherwise you will need to do a manual installation. All of these installation types have their own section: \&\*(L"\s-1CPAN\s0 installation\*(R", \*(L"Manual installation\*(R" and \*(L"Configuration\*(R". .PP The DBD::mysql Makefile.PL needs to know where to find your MySQL installation. This may be achieved using command line switches (see \*(L"Configuration\*(R") or automatically using the mysql_config binary which comes with most MySQL distributions. If your MySQL distribution contains mysql_config the easiest method is to ensure this binary is on your path. .PP Typically, this is the case if you've installed the mysql library from your systems' package manager. .PP e.g. .PP .Vb 2 \& PATH=$PATH:/usr/local/mysql/bin \& export PATH .Ve .PP As stated, to compile DBD::mysql you'll need a C compiler. This should be the same compiler as the one used to build perl \s-1AND\s0 the mysql client libraries. If you're on linux, this is most typically the case and you need not worry. If you're on \s-1UNIX\s0 systems, you might want to pay attention. .PP Also you'll need to get the MySQL client and development headers on your system. The easiest is to get these from your package manager. .PP To run the tests that ship with the module, you'll need access to a running MySQL server. This can be running on localhost, but it can also be on a remote machine. .PP On Fedora the process is as follows. Please note that Fedora actually ships with MariaDB but not with MySQL. This is not a problem, it will work just as well. In this example we install and start a local server for running the tests against. .PP .Vb 3 \& yum \-y install make gcc mariadb\-devel mariadb\-libs mariadb\-server \& yum \-y install "perl(Test::Deep)" "perl(Test::More)" \& systemctl start mariadb.service .Ve .SS "Environment Variables" .IX Subsection "Environment Variables" For ease of use, you can set environment variables for DBD::mysql installation. You can set any or all of the options, and export them by putting them in your .bashrc or the like: .PP .Vb 12 \& export DBD_MYSQL_CFLAGS=\-I/usr/local/mysql/include/mysql \& export DBD_MYSQL_LIBS="\-L/usr/local/mysql/lib/mysql \-lmysqlclient" \& export DBD_MYSQL_EMBEDDED= \& export DBD_MYSQL_CONFIG=mysql_config \& export DBD_MYSQL_NOCATCHSTDERR=0 \& export DBD_MYSQL_NOFOUNDROWS=0 \& export DBD_MYSQL_NOSSL= \& export DBD_MYSQL_TESTDB=test \& export DBD_MYSQL_TESTHOST=localhost \& export DBD_MYSQL_TESTPASSWORD=s3kr1+ \& export DBD_MYSQL_TESTPORT=3306 \& export DBD_MYSQL_TESTUSER=me .Ve .PP The most useful may be the host, database, port, socket, user, and password. .PP Installation will first look to your mysql_config, and then your environment variables, and then it will guess with intelligent defaults. .SS "\s-1CPAN\s0 installation" .IX Subsection "CPAN installation" Installation of DBD::mysql can be incredibly easy: .PP .Vb 1 \& cpan DBD::mysql .Ve .PP Please note that this will only work if the prerequisites are fulfilled, which means you have a C\-compiler installed, and you have the development headers and mysql client libraries available on your system. .PP If you are using the \s-1CPAN\s0 module for the first time, just answer the questions by accepting the defaults which are fine in most cases. .PP If you cannot get the \s-1CPAN\s0 module working, you might try manual installation. If installation with \s-1CPAN\s0 fails because the your local settings have been guessed wrong, you need to ensure MySQL's mysql_config is on your path (see \*(L"\s-1SOURCE INSTALLATION\*(R"\s0) or alternatively create a script called \f(CW\*(C`mysql_config\*(C'\fR. This is described in more details later. \*(L"Configuration\*(R". .SS "Manual installation" .IX Subsection "Manual installation" For a manual installation you need to fetch the DBD::mysql source distribution. The latest version is always available from .PP .Vb 1 \& https://metacpan.org/module/DBD::mysql .Ve .PP The name is typically something like .PP .Vb 1 \& DBD\-mysql\-4.025.tar.gz .Ve .PP The archive needs to be extracted. On Windows you may use a tool like 7\-zip, on *nix you type .PP .Vb 1 \& tar xf DBD\-mysql\-4.025.tar.gz .Ve .PP This will create a subdirectory DBD\-mysql\-4.025. Enter this subdirectory and type .PP .Vb 3 \& perl Makefile.PL \& make \& make test .Ve .PP (On Windows you may need to replace \*(L"make\*(R" with \*(L"dmake\*(R" or \&\*(L"nmake\*(R".) If the tests seem to look fine, you may continue with .PP .Vb 1 \& make install .Ve .PP If the compilation (make) or tests fail, you might need to configure some settings. .PP For example you might choose a different database, the C compiler or the linker might need some flags. \*(L"Configuration\*(R". \&\*(L"Compiler flags\*(R". \*(L"Linker flags\*(R". .PP For Cygwin there is a special section below. \&\*(L"Cygwin\*(R". .SS "Configuration" .IX Subsection "Configuration" The install script \*(L"Makefile.PL\*(R" can be configured via a lot of switches. All switches can be used on the command line. For example, the test database: .PP .Vb 1 \& perl Makefile.PL \-\-testdb= .Ve .PP If you do not like configuring these switches on the command line, you may alternatively create a script called \f(CW\*(C`mysql_config\*(C'\fR. This is described later on. .PP Available switches are: .IP "testdb" 4 .IX Item "testdb" Name of the test database, defaults to \fBtest\fR. .IP "testuser" 4 .IX Item "testuser" Name of the test user, defaults to empty. If the name is empty, then the currently logged in users name will be used. .IP "testpassword" 4 .IX Item "testpassword" Password of the test user, defaults to empty. .IP "testhost" 4 .IX Item "testhost" Host name or \s-1IP\s0 number of the test database; defaults to localhost. .IP "testport" 4 .IX Item "testport" Port number of the test database .IP "ps\-protcol=1 or 0" 4 .IX Item "ps-protcol=1 or 0" Whether to run the test suite using server prepared statements or driver emulated prepared statements. ps\-protocol=1 means use server prepare, ps\-protocol=0 means driver emulated. .IP "cflags" 4 .IX Item "cflags" This is a list of flags that you want to give to the C compiler. The most important flag is the location of the MySQL header files. For example, on Red Hat Linux the header files are in /usr/include/mysql and you might try .Sp .Vb 1 \& \-I/usr/include/mysql .Ve .Sp On Windows the header files may be in C:\emysql\einclude and you might try .Sp .Vb 1 \& \-IC:\emysql\einclude .Ve .Sp The default flags are determined by running .Sp .Vb 1 \& mysql_config \-\-cflags .Ve .Sp More details on the C compiler flags can be found in the following section. \*(L"Compiler flags\*(R". .IP "libs" 4 .IX Item "libs" This is a list of flags that you want to give to the linker or loader. The most important flags are the locations and names of additional libraries. For example, on Red Hat Linux your MySQL client libraries are in /usr/lib/mysql and you might try .Sp .Vb 1 \& \-L/usr/lib/mysql \-lmysqlclient \-lz .Ve .Sp On Windows the libraries may be in C:\emysql\elib and .Sp .Vb 1 \& \-LC:\emysql\elib \-lmysqlclient .Ve .Sp might be a good choice. The default flags are determined by running .Sp .Vb 1 \& mysql_config \-\-libs .Ve .Sp More details on the linker flags can be found in a separate section. \&\*(L"Linker flags\*(R". .PP If a switch is not present on the command line, then the script \f(CW\*(C`mysql_config\*(C'\fR will be executed. This script comes as part of the MySQL distribution. For example, to determine the C compiler flags, we are executing .PP .Vb 2 \& mysql_config \-\-cflags \& mysql_config \-\-libs .Ve .PP If you want to configure your own settings for database name, database user and so on, then you have to create a script with the same name, that replies .SS "Compiler flags" .IX Subsection "Compiler flags" Note: the following info about compiler and linker flags, you shouldn't have to use these options because Makefile.PL is pretty good at utilizing mysql_config to get the flags that you need for a successful compile. .PP It is typically not so difficult to determine the appropriate flags for the C compiler. The linker flags, which you find in the next section, are another story. .PP The determination of the C compiler flags is usually left to a configuration script called \fImysql_config\fR, which can be invoked with .PP .Vb 1 \& mysql_config \-\-cflags .Ve .PP When doing so, it will emit a line with suggested C compiler flags, for example like this: .PP .Vb 1 \& \-L/usr/include/mysql .Ve .PP The C compiler must find some header files. Header files have the extension \f(CW\*(C`.h\*(C'\fR. MySQL header files are, for example, \&\fImysql.h\fR and \fImysql_version.h\fR. In most cases the header files are not installed by default. For example, on Windows it is an installation option of the MySQL setup program (Custom installation), whether the header files are installed or not. On Red Hat Linux, you need to install an \s-1RPM\s0 archive \&\fImysql-devel\fR or \fIMySQL-devel\fR. .PP If you know the location of the header files, then you will need to add an option .PP .Vb 1 \& \-L
    .Ve .PP to the C compiler flags, for example \f(CW\*(C`\-L/usr/include/mysql\*(C'\fR. .SS "Linker flags" .IX Subsection "Linker flags" Appropriate linker flags are the most common source of problems while installing DBD::mysql. I will only give a rough overview, you'll find more details in the troubleshooting section. \&\*(L"\s-1KNOWN PROBLEMS\*(R"\s0 .PP The determination of the C compiler flags is usually left to a configuration script called \fImysql_config\fR, which can be invoked with .PP .Vb 1 \& mysql_config \-\-libs .Ve .PP When doing so, it will emit a line with suggested C compiler flags, for example like this: .PP .Vb 1 \& \-L\*(Aq/usr/lib/mysql\*(Aq \-lmysqlclient \-lnsl \-lm \-lz \-lcrypt .Ve .PP The following items typically need to be configured for the linker: .IP "The mysqlclient library" 4 .IX Item "The mysqlclient library" The MySQL client library comes as part of the MySQL distribution. Depending on your system it may be a file called .Sp .Vb 4 \& F statically linked library, Unix \& F dynamically linked library, Unix \& F statically linked library, Windows \& F dynamically linked library, Windows .Ve .Sp or something similar. .Sp As in the case of the header files, the client library is typically not installed by default. On Windows you will need to select them while running the MySQL setup program (Custom installation). On Red Hat Linux an \s-1RPM\s0 archive \fImysql-devel\fR or \fIMySQL-devel\fR must be installed. .Sp The linker needs to know the location and name of the mysqlclient library. This can be done by adding the flags .Sp .Vb 1 \& \-L \-lmysqlclient .Ve .Sp or by adding the complete path name. Examples: .Sp .Vb 2 \& \-L/usr/lib/mysql \-lmysqlclient \& \-LC:\emysql\elib \-lmysqlclient .Ve .Sp If you would like to use the static libraries (and there are excellent reasons to do so), you need to create a separate directory, copy the static libraries to that place and use the \-L switch above to point to your new directory. For example: .Sp .Vb 7 \& mkdir /tmp/mysql\-static \& cp /usr/lib/mysql/*.a /tmp/mysql\-static \& perl Makefile.PL \-\-libs="\-L/tmp/mysql\-static \-lmysqlclient" \& make \& make test \& make install \& rm \-rf /tmp/mysql\-static .Ve .IP "The gzip library" 4 .IX Item "The gzip library" The MySQL client can use compression when talking to the MySQL server, a nice feature when sending or receiving large texts over a slow network. .Sp On Unix you typically find the appropriate file name by running .Sp .Vb 2 \& ldconfig \-p | grep libz \& ldconfig \-p | grep libgz .Ve .Sp Once you know the name (libz.a or libgz.a is best), just add it to the list of linker flags. If this seems to be causing problem you may also try to link without gzip libraries. .SH "ENCRYPTED CONNECTIONS via SSL" .IX Header "ENCRYPTED CONNECTIONS via SSL" Connecting to your servers over an encrypted connection (\s-1SSL\s0) is only possible if you enabled this setting at build time. Since version 4.034, this is the default. .PP Attempting to connect to a server that requires an encrypted connection without first having DBD::mysql compiled with the \f(CW\*(C`\-\-ssl\*(C'\fR option will result in an error that makes things appear as if your password is incorrect. .PP If you want to compile DBD::mysql without \s-1SSL\s0 support, which you might probably only want if you for some reason can't install libssl headers, you can do this by passing the \f(CW\*(C`\-\-nossl\*(C'\fR option to Makefile.PL or by setting the \&\s-1DBD_MYSQL_NOSSL\s0 environment variable to '1'. .SH "MARIADB NATIVE CLIENT INSTALLATION" .IX Header "MARIADB NATIVE CLIENT INSTALLATION" The MariaDB native client is another option for connecting to a MySQL· database licensed \s-1LGPL 2.1.\s0 To build DBD::mysql against this client, you will first need to build the client. Generally, this is done with the following: .PP .Vb 4 \& cd path/to/src/mariadb\-native\-client \& cmake \-G "Unix Makefiles\*(Aq \& make \& sudo make install .Ve .PP Once the client is built and installed, you can build DBD::mysql against it: .PP .Vb 4 \& perl Makefile.PL \-\-testuser=xxx \-\-testpassword=xxx \-\-testsocket=/path/to//mysqld.sock \-\-mysql_config=/usr/local/bin/mariadb_config· \& make \& make test \& make install .Ve .SH "SPECIAL SYSTEMS" .IX Header "SPECIAL SYSTEMS" Below you find information on particular systems: .SS "macOS" .IX Subsection "macOS" For installing DBD::mysql you need to have the libssl header files and the mysql client libs. The easiest way to install these is using Homebrew (). .PP Once you have Homebrew set up, you can simply install the dependencies using .PP .Vb 1 \& brew install openssl mysql\-connector\-c .Ve .PP Then you can install DBD::mysql using your cpan client. .SS "Cygwin" .IX Subsection "Cygwin" If you are a user of Cygwin you already know, it contains a nicely running perl 5.6.1, installation of additional modules usually works like a charm via the standard procedure of .PP .Vb 4 \& perl makefile.PL \& make \& make test \& make install .Ve .PP The Windows binary distribution of MySQL runs smoothly under Cygwin. You can start/stop the server and use all Windows clients without problem. But to install DBD::mysql you have to take a little special action. .PP Don't attempt to build DBD::mysql against either the MySQL Windows or Linux/Unix \s-1BINARY\s0 distributions: neither will work! .PP You \s-1MUST\s0 compile the MySQL clients yourself under Cygwin, to get a \&'libmysqlclient.a' compiled under Cygwin. Really! You'll only need that library and the header files, you don't need any other client parts. Continue to use the Windows binaries. And don't attempt (currently) to build the MySQL Server part, it is unnecessary, as MySQL \s-1AB\s0 does an excellent job to deliver optimized binaries for the mainstream operating systems, and it is told, that the server compiled under Cygwin is unstable. .PP Install a MySQL server for testing against. You can install the regular Windows MySQL server package on your Windows machine, or you can also test against a MySQL server on a remote host. .PP \fIBuild MySQL clients under Cygwin:\fR .IX Subsection "Build MySQL clients under Cygwin:" .PP download the MySQL \s-1LINUX\s0 source from , unpack mysql\-.tar.gz into some tmp location and from this directory run configure: .PP .Vb 1 \& ./configure \-\-prefix=/usr/local/mysql \-\-without\-server .Ve .PP This prepares the Makefile with the installed Cygwin features. It takes some time, but should finish without error. The 'prefix', as given, installs the whole Cygwin/MySQL thingy into a location not normally in your \s-1PATH,\s0 so that you continue to use already installed Windows binaries. The \-\-without\-server parameter tells configure to only build the clients. .PP .Vb 1 \& make .Ve .PP This builds all MySQL client parts ... be patient. It should finish finally without any error. .PP .Vb 1 \& make install .Ve .PP This installs the compiled client files under /usr/local/mysql/. Remember, you don't need anything except the library under /usr/local/mysql/lib and the headers under /usr/local/mysql/include! .PP Essentially you are now done with this part. If you want, you may try your compiled binaries shortly; for that, do: .PP .Vb 2 \& cd /usr/local/mysql/bin \& ./mysql \-h 127.0.0.1 .Ve .PP The host (\-h) parameter 127.0.0.1 targets the local host, but forces the mysql client to use a \s-1TCP/IP\s0 connection. The default would be a pipe/socket connection (even if you say '\-h localhost') and this doesn't work between Cygwin and Windows (as far as I know). .PP If you have your MySQL server running on some other box, then please substitute '127.0.0.1' with the name or IP-number of that box. .PP Please note, in my environment the 'mysql' client did not accept a simple \s-1RETURN, I\s0 had to use CTRL-RETURN to send commands \&... strange, but I didn't attempt to fix that, as we are only interested in the built lib and headers. .PP At the 'mysql>' prompt do a quick check: .PP .Vb 4 \& mysql> use mysql \& mysql> show tables; \& mysql> select * from db; \& mysql> exit .Ve .PP You are now ready to build DBD::mysql! .PP \fIcompile DBD::mysql\fR .IX Subsection "compile DBD::mysql" .PP download and extract DBD\-mysql\-.tar.gz from \s-1CPAN\s0 .PP cd into unpacked dir DBD\-mysql\- you probably did that already, if you are reading this! .PP .Vb 1 \& cp /usr/local/mysql/bin/mysql_config . .Ve .PP This copies the executable script mentioned in the DBD::mysql docs from your just built Cywin/MySQL client directory; it knows about your Cygwin installation, especially about the right libraries to link with. .PP .Vb 1 \& perl Makefile.PL \-\-testhost=127.0.0.1 .Ve .PP The \-\-testhost=127.0.0.1 parameter again forces a \s-1TCP/IP\s0 connection to the MySQL server on the local host instead of a pipe/socket connection for the 'make test' phase. .PP .Vb 1 \& make .Ve .PP This should run without error .PP .Vb 2 \& make test \& make install .Ve .PP This installs DBD::mysql into the Perl hierarchy. .SH "KNOWN PROBLEMS" .IX Header "KNOWN PROBLEMS" .SS "no gzip on your system" .IX Subsection "no gzip on your system" Some Linux distributions don't come with a gzip library by default. Running \*(L"make\*(R" terminates with an error message like .PP .Vb 8 \& LD_RUN_PATH="/usr/lib/mysql:/lib:/usr/lib" gcc \& \-o blib/arch/auto/DBD/mysql/mysql.so \-shared \& \-L/usr/local/lib dbdimp.o mysql.o \-L/usr/lib/mysql \& \-lmysqlclient \-lm \-L/usr/lib/gcc\-lib/i386\-redhat\-linux/2.96 \& \-lgcc \-lz \& /usr/bin/ld: cannot find \-lz \& collect2: ld returned 1 exit status \& make: *** [blib/arch/auto/DBD/mysql/mysql.so] Error 1 .Ve .PP If this is the case for you, install an \s-1RPM\s0 archive like libz-devel, libgz-devel, zlib-devel or gzlib-devel or something similar. .SS "different compiler for mysql and perl" .IX Subsection "different compiler for mysql and perl" If Perl was compiled with gcc or egcs, but MySQL was compiled with another compiler or on another system, an error message like this is very likely when running \*(L"Make test\*(R": .PP .Vb 5 \& t/00base............install_driver(mysql) failed: Can\*(Aqt load \& \*(Aq../blib/arch/auto/DBD/mysql/mysql.so\*(Aq for module DBD::mysql: \& ../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: _umoddi3 \& at /usr/local/perl\-5.005/lib/5.005/i586\-linux\-thread/DynaLoader.pm \& line 168. .Ve .PP This means, that your linker doesn't include libgcc.a. You have the following options: .PP The solution is telling the linker to use libgcc. Run .PP .Vb 1 \& gcc \-\-print\-libgcc\-file .Ve .PP to determine the exact location of libgcc.a or for older versions of gcc .PP .Vb 1 \& gcc \-v .Ve .PP to determine the directory. If you know the directory, add a .PP .Vb 1 \& \-L \-lgcc .Ve .PP to the list of C compiler flags. \*(L"Configuration\*(R". \*(L"Linker flags\*(R". .SH "SUPPORT" .IX Header "SUPPORT" Finally, if everything else fails, you are not alone. First of all, for an immediate answer, you should look into the archives of the dbi-users mailing list, which is available at .PP To subscribe to this list, send and email to .PP .Vb 1 \& dbi\-users\-subscribe@perl.org .Ve .PP If you don't find an appropriate posting and reply in the mailing list, please post a question. Typically a reply will be seen within one or two days. man/man3/JSON::XS::Boolean.3pm000044400000005445152462503210011500 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "XS::Boolean 3" .TH XS::Boolean 3 "2013-10-29" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::XS::Boolean \- dummy module providing JSON::XS::Boolean .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& # do not "use" yourself .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module exists only to provide overload resolution for Storable and similar modules. It's only needed for compatibility with data serialised (by other modules such as Storable) that was decoded by \s-1JSON::XS\s0 versions before 3.0. .PP Since 3.0, JSON::PP::Boolean has replaced it. Support for JSON::XS::Boolean will be removed in a future release. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 2 \& Marc Lehmann \& http://home.schmorp.de/ .Ve man/man3/JSON::XS.3pm000044400000255675152462503210010030 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "XS 3" .TH XS 3 "2020-10-27" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::XS \- JSON serialising/deserialising, done correctly and fast .PP JSON::XS \- 正しくて高速な JSON シリアライザ/デシリアライザ (http://fleur.hio.jp/perldoc/mix/lib/JSON/XS.html) .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use JSON::XS; \& \& # exported functions, they croak on error \& # and expect/generate UTF\-8 \& \& $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; \& $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; \& \& # OO\-interface \& \& $coder = JSON::XS\->new\->ascii\->pretty\->allow_nonref; \& $pretty_printed_unencoded = $coder\->encode ($perl_scalar); \& $perl_scalar = $coder\->decode ($unicode_json_text); \& \& # Note that JSON version 2.0 and above will automatically use JSON::XS \& # if available, at virtually no speed overhead either, so you should \& # be able to just: \& \& use JSON; \& \& # and do the same things, except that you have a pure\-perl fallback now. .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module converts Perl data structures to \s-1JSON\s0 and vice versa. Its primary goal is to be \fIcorrect\fR and its secondary goal is to be \&\fIfast\fR. To reach the latter goal it was written in C. .PP See \s-1MAPPING,\s0 below, on how \s-1JSON::XS\s0 maps perl values to \s-1JSON\s0 values and vice versa. .SS "\s-1FEATURES\s0" .IX Subsection "FEATURES" .IP "\(bu" 4 correct Unicode handling .Sp This module knows how to handle Unicode, documents how and when it does so, and even documents what \*(L"correct\*(R" means. .IP "\(bu" 4 round-trip integrity .Sp When you serialise a perl data structure using only data types supported by \s-1JSON\s0 and Perl, the deserialised data structure is identical on the Perl level. (e.g. the string \*(L"2.0\*(R" doesn't suddenly become \*(L"2\*(R" just because it looks like a number). There \fIare\fR minor exceptions to this, read the \&\s-1MAPPING\s0 section below to learn about those. .IP "\(bu" 4 strict checking of \s-1JSON\s0 correctness .Sp There is no guessing, no generating of illegal \s-1JSON\s0 texts by default, and only \s-1JSON\s0 is accepted as input by default (the latter is a security feature). .IP "\(bu" 4 fast .Sp Compared to other \s-1JSON\s0 modules and other serialisers such as Storable, this module usually compares favourably in terms of speed, too. .IP "\(bu" 4 simple to use .Sp This module has both a simple functional interface as well as an object oriented interface. .IP "\(bu" 4 reasonably versatile output formats .Sp You can choose between the most compact guaranteed-single-line format possible (nice for simple line-based protocols), a pure-ASCII format (for when your transport is not 8\-bit clean, still supports the whole Unicode range), or a pretty-printed format (for when you want to read that stuff). Or you can combine those features in whatever way you like. .SH "FUNCTIONAL INTERFACE" .IX Header "FUNCTIONAL INTERFACE" The following convenience methods are provided by this module. They are exported by default: .ie n .IP "$json_text = encode_json $perl_scalar" 4 .el .IP "\f(CW$json_text\fR = encode_json \f(CW$perl_scalar\fR" 4 .IX Item "$json_text = encode_json $perl_scalar" Converts the given Perl data structure to a \s-1UTF\-8\s0 encoded, binary string (that is, the string contains octets only). Croaks on error. .Sp This function call is functionally identical to: .Sp .Vb 1 \& $json_text = JSON::XS\->new\->utf8\->encode ($perl_scalar) .Ve .Sp Except being faster. .ie n .IP "$perl_scalar = decode_json $json_text" 4 .el .IP "\f(CW$perl_scalar\fR = decode_json \f(CW$json_text\fR" 4 .IX Item "$perl_scalar = decode_json $json_text" The opposite of \f(CW\*(C`encode_json\*(C'\fR: expects a \s-1UTF\-8\s0 (binary) string and tries to parse that as a \s-1UTF\-8\s0 encoded \s-1JSON\s0 text, returning the resulting reference. Croaks on error. .Sp This function call is functionally identical to: .Sp .Vb 1 \& $perl_scalar = JSON::XS\->new\->utf8\->decode ($json_text) .Ve .Sp Except being faster. .SH "A FEW NOTES ON UNICODE AND PERL" .IX Header "A FEW NOTES ON UNICODE AND PERL" Since this often leads to confusion, here are a few very clear words on how Unicode works in Perl, modulo bugs. .IP "1. Perl strings can store characters with ordinal values > 255." 4 .IX Item "1. Perl strings can store characters with ordinal values > 255." This enables you to store Unicode characters as single characters in a Perl string \- very natural. .IP "2. Perl does \fInot\fR associate an encoding with your strings." 4 .IX Item "2. Perl does not associate an encoding with your strings." \&... until you force it to, e.g. when matching it against a regex, or printing the scalar to a file, in which case Perl either interprets your string as locale-encoded text, octets/binary, or as Unicode, depending on various settings. In no case is an encoding stored together with your data, it is \fIuse\fR that decides encoding, not any magical meta data. .IP "3. The internal utf\-8 flag has no meaning with regards to the encoding of your string." 4 .IX Item "3. The internal utf-8 flag has no meaning with regards to the encoding of your string." Just ignore that flag unless you debug a Perl bug, a module written in \&\s-1XS\s0 or want to dive into the internals of perl. Otherwise it will only confuse you, as, despite the name, it says nothing about how your string is encoded. You can have Unicode strings with that flag set, with that flag clear, and you can have binary data with that flag set and that flag clear. Other possibilities exist, too. .Sp If you didn't know about that flag, just the better, pretend it doesn't exist. .ie n .IP "4. A ""Unicode String"" is simply a string where each character can be validly interpreted as a Unicode code point." 4 .el .IP "4. A ``Unicode String'' is simply a string where each character can be validly interpreted as a Unicode code point." 4 .IX Item "4. A Unicode String is simply a string where each character can be validly interpreted as a Unicode code point." If you have \s-1UTF\-8\s0 encoded data, it is no longer a Unicode string, but a Unicode string encoded in \s-1UTF\-8,\s0 giving you a binary string. .ie n .IP "5. A string containing ""high"" (> 255) character values is \fInot\fR a \s-1UTF\-8\s0 string." 4 .el .IP "5. A string containing ``high'' (> 255) character values is \fInot\fR a \s-1UTF\-8\s0 string." 4 .IX Item "5. A string containing high (> 255) character values is not a UTF-8 string." It's a fact. Learn to live with it. .PP I hope this helps :) .SH "OBJECT-ORIENTED INTERFACE" .IX Header "OBJECT-ORIENTED INTERFACE" The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. .ie n .IP "$json = new \s-1JSON::XS\s0" 4 .el .IP "\f(CW$json\fR = new \s-1JSON::XS\s0" 4 .IX Item "$json = new JSON::XS" Creates a new \s-1JSON::XS\s0 object that can be used to de/encode \s-1JSON\s0 strings. All boolean flags described below are by default \fIdisabled\fR (with the exception of \f(CW\*(C`allow_nonref\*(C'\fR, which defaults to \fIenabled\fR since version \f(CW4.0\fR). .Sp The mutators for flags all return the \s-1JSON\s0 object again and thus calls can be chained: .Sp .Vb 2 \& my $json = JSON::XS\->new\->utf8\->space_after\->encode ({a => [1,2]}) \& => {"a": [1, 2]} .Ve .ie n .IP "$json = $json\->ascii ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->ascii ([$enable])" 4 .IX Item "$json = $json->ascii ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_ascii" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_ascii" 4 .IX Item "$enabled = $json->get_ascii" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not generate characters outside the code range \f(CW0..127\fR (which is \s-1ASCII\s0). Any Unicode characters outside that range will be escaped using either a single \euXXXX (\s-1BMP\s0 characters) or a double \euHHHH\euLLLLL escape sequence, as per \s-1RFC4627.\s0 The resulting encoded \s-1JSON\s0 text can be treated as a native Unicode string, an ascii-encoded, latin1\-encoded or \s-1UTF\-8\s0 encoded string, or any other superset of \s-1ASCII.\s0 .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. This results in a faster and more compact format. .Sp See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .Sp The main use for this flag is to produce \s-1JSON\s0 texts that can be transmitted over a 7\-bit channel, as the encoded \s-1JSON\s0 texts will not contain any 8 bit characters. .Sp .Vb 2 \& JSON::XS\->new\->ascii (1)\->encode ([chr 0x10401]) \& => ["\eud801\eudc01"] .Ve .ie n .IP "$json = $json\->latin1 ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->latin1 ([$enable])" 4 .IX Item "$json = $json->latin1 ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_latin1" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_latin1" 4 .IX Item "$enabled = $json->get_latin1" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the resulting \s-1JSON\s0 text as latin1 (or iso\-8859\-1), escaping any characters outside the code range \f(CW0..255\fR. The resulting string can be treated as a latin1\-encoded \s-1JSON\s0 text or a native Unicode string. The \f(CW\*(C`decode\*(C'\fR method will not be affected in any way by this flag, as \f(CW\*(C`decode\*(C'\fR by default expects Unicode, which is a strict superset of latin1. .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. .Sp See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .Sp The main use for this flag is efficiently encoding binary data as \s-1JSON\s0 text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting \s-1JSON\s0 text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for \s-1JSON.\s0 It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other \s-1JSON\s0 encoders/decoders. .Sp .Vb 2 \& JSON::XS\->new\->latin1\->encode (["\ex{89}\ex{abc}"] \& => ["\ex{89}\e\eu0abc"] # (perl syntax, U+abc escaped, U+89 not) .Ve .ie n .IP "$json = $json\->utf8 ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->utf8 ([$enable])" 4 .IX Item "$json = $json->utf8 ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_utf8" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_utf8" 4 .IX Item "$enabled = $json->get_utf8" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the \s-1JSON\s0 result into \s-1UTF\-8,\s0 as required by many protocols, while the \&\f(CW\*(C`decode\*(C'\fR method expects to be handed a UTF\-8\-encoded string. Please note that UTF\-8\-encoded strings do not contain any characters outside the range \f(CW0..255\fR, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the \s-1UTF\-16\s0 and \s-1UTF\-32\s0 encoding families, as described in \s-1RFC4627.\s0 .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will return the \s-1JSON\s0 string as a (non-encoded) Unicode string, while \f(CW\*(C`decode\*(C'\fR expects thus a Unicode string. Any decoding or encoding (e.g. to \s-1UTF\-8\s0 or \s-1UTF\-16\s0) needs to be done yourself, e.g. using the Encode module. .Sp See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .Sp Example, output UTF\-16BE\-encoded \s-1JSON:\s0 .Sp .Vb 2 \& use Encode; \& $jsontext = encode "UTF\-16BE", JSON::XS\->new\->encode ($object); .Ve .Sp Example, decode UTF\-32LE\-encoded \s-1JSON:\s0 .Sp .Vb 2 \& use Encode; \& $object = JSON::XS\->new\->decode (decode "UTF\-32LE", $jsontext); .Ve .ie n .IP "$json = $json\->pretty ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->pretty ([$enable])" 4 .IX Item "$json = $json->pretty ([$enable])" This enables (or disables) all of the \f(CW\*(C`indent\*(C'\fR, \f(CW\*(C`space_before\*(C'\fR and \&\f(CW\*(C`space_after\*(C'\fR (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. .Sp Example, pretty-print some simple structure: .Sp .Vb 8 \& my $json = JSON::XS\->new\->pretty(1)\->encode ({a => [1,2]}) \& => \& { \& "a" : [ \& 1, \& 2 \& ] \& } .Ve .ie n .IP "$json = $json\->indent ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->indent ([$enable])" 4 .IX Item "$json = $json->indent ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_indent" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_indent" 4 .IX Item "$enabled = $json->get_indent" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. .Sp If \f(CW$enable\fR is false, no newlines or indenting will be produced, and the resulting \s-1JSON\s0 text is guaranteed not to contain any \f(CW\*(C`newlines\*(C'\fR. .Sp This setting has no effect when decoding \s-1JSON\s0 texts. .ie n .IP "$json = $json\->space_before ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->space_before ([$enable])" 4 .IX Item "$json = $json->space_before ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_space_before" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_space_before" 4 .IX Item "$enabled = $json->get_space_before" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space before the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects. .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .Sp This setting has no effect when decoding \s-1JSON\s0 texts. You will also most likely combine this setting with \f(CW\*(C`space_after\*(C'\fR. .Sp Example, space_before enabled, space_after and indent disabled: .Sp .Vb 1 \& {"key" :"value"} .Ve .ie n .IP "$json = $json\->space_after ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->space_after ([$enable])" 4 .IX Item "$json = $json->space_after ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_space_after" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_space_after" 4 .IX Item "$enabled = $json->get_space_after" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space after the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects and extra whitespace after the \f(CW\*(C`,\*(C'\fR separating key-value pairs and array members. .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .Sp This setting has no effect when decoding \s-1JSON\s0 texts. .Sp Example, space_before and indent disabled, space_after enabled: .Sp .Vb 1 \& {"key": "value"} .Ve .ie n .IP "$json = $json\->relaxed ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->relaxed ([$enable])" 4 .IX Item "$json = $json->relaxed ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_relaxed" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_relaxed" 4 .IX Item "$enabled = $json->get_relaxed" .PD If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept some extensions to normal \s-1JSON\s0 syntax (see below). \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \fIBe aware that this option makes you accept invalid \&\s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .Sp If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .Sp Currently accepted extensions are: .RS 4 .IP "\(bu" 4 list items can have an end-comma .Sp \&\s-1JSON\s0 \fIseparates\fR array elements and key-value pairs with commas. This can be annoying if you write \s-1JSON\s0 texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: .Sp .Vb 8 \& [ \& 1, \& 2, <\- this comma not normally allowed \& ] \& { \& "k1": "v1", \& "k2": "v2", <\- this comma not normally allowed \& } .Ve .IP "\(bu" 4 shell-style '#'\-comments .Sp Whenever \s-1JSON\s0 allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, # this comment not allowed in JSON \& # neither this one... \& ] .Ve .IP "\(bu" 4 literal \s-1ASCII TAB\s0 characters in strings .Sp Literal \s-1ASCII TAB\s0 characters are now allowed in strings (and treated as \&\f(CW\*(C`\et\*(C'\fR). .Sp .Vb 4 \& [ \& "Hello\etWorld", \& "HelloWorld", # literal would not normally be allowed \& ] .Ve .RE .RS 4 .RE .ie n .IP "$json = $json\->canonical ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->canonical ([$enable])" 4 .IX Item "$json = $json->canonical ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_canonical" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_canonical" 4 .IX Item "$enabled = $json->get_canonical" .PD If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will output \s-1JSON\s0 objects by sorting their keys. This is adding a comparatively high overhead. .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). .Sp This option is useful if you want the same data structure to be encoded as the same \s-1JSON\s0 text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. .Sp This setting has no effect when decoding \s-1JSON\s0 texts. .Sp This setting has currently no effect on tied hashes. .ie n .IP "$json = $json\->allow_nonref ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->allow_nonref ([$enable])" 4 .IX Item "$json = $json->allow_nonref ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_allow_nonref" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_allow_nonref" 4 .IX Item "$enabled = $json->get_allow_nonref" .PD Unlike other boolean options, this opotion is enabled by default beginning with version \f(CW4.0\fR. See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 for the gory details. .Sp If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method can convert a non-reference into its corresponding string, number or null \s-1JSON\s0 value, which is an extension to \s-1RFC4627.\s0 Likewise, \f(CW\*(C`decode\*(C'\fR will accept those \s-1JSON\s0 values instead of croaking. .Sp If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will croak if it isn't passed an arrayref or hashref, as \s-1JSON\s0 texts must either be an object or array. Likewise, \f(CW\*(C`decode\*(C'\fR will croak if given something that is not a \&\s-1JSON\s0 object or array. .Sp Example, encode a Perl scalar as \s-1JSON\s0 value without enabled \f(CW\*(C`allow_nonref\*(C'\fR, resulting in an error: .Sp .Vb 2 \& JSON::XS\->new\->allow_nonref (0)\->encode ("Hello, World!") \& => hash\- or arrayref expected... .Ve .ie n .IP "$json = $json\->allow_unknown ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->allow_unknown ([$enable])" 4 .IX Item "$json = $json->allow_unknown ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_allow_unknown" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_allow_unknown" 4 .IX Item "$enabled = $json->get_allow_unknown" .PD If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR will \fInot\fR throw an exception when it encounters values it cannot represent in \s-1JSON\s0 (for example, filehandles) but instead will encode a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value. Note that blessed objects are not included here and are handled separately by c. .Sp If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters anything it cannot encode as \s-1JSON.\s0 .Sp This option does not affect \f(CW\*(C`decode\*(C'\fR in any way, and it is recommended to leave it off unless you know your communications partner. .ie n .IP "$json = $json\->allow_blessed ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->allow_blessed ([$enable])" 4 .IX Item "$json = $json->allow_blessed ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_allow_blessed" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_allow_blessed" 4 .IX Item "$enabled = $json->get_allow_blessed" .PD See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .Sp If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value is encoded instead of the object. .Sp If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters a blessed object that it cannot convert otherwise. .Sp This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .ie n .IP "$json = $json\->convert_blessed ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->convert_blessed ([$enable])" 4 .IX Item "$json = $json->convert_blessed ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_convert_blessed" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_convert_blessed" 4 .IX Item "$enabled = $json->get_convert_blessed" .PD See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .Sp If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`TO_JSON\*(C'\fR method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. .Sp The \f(CW\*(C`TO_JSON\*(C'\fR method may safely call die if it wants. If \f(CW\*(C`TO_JSON\*(C'\fR returns other blessed objects, those will be handled in the same way. \f(CW\*(C`TO_JSON\*(C'\fR must take care of not causing an endless recursion cycle (== crash) in this case. The name of \f(CW\*(C`TO_JSON\*(C'\fR was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any \f(CW\*(C`to_json\*(C'\fR function or method. .Sp If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion. .Sp This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .ie n .IP "$json = $json\->allow_tags ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->allow_tags ([$enable])" 4 .IX Item "$json = $json->allow_tags ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_allow_tags" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_allow_tags" 4 .IX Item "$enabled = $json->get_allow_tags" .PD See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .Sp If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`FREEZE\*(C'\fR method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged \s-1JSON\s0 value (that \s-1JSON\s0 decoders cannot decode). .Sp It also causes \f(CW\*(C`decode\*(C'\fR to parse such tagged \s-1JSON\s0 values and deserialise them via a call to the \f(CW\*(C`THAW\*(C'\fR method. .Sp If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion, and tagged \s-1JSON\s0 values will cause a parse error in \f(CW\*(C`decode\*(C'\fR, as if tags were not part of the grammar. .ie n .IP "$json\->boolean_values ([$false, $true])" 4 .el .IP "\f(CW$json\fR\->boolean_values ([$false, \f(CW$true\fR])" 4 .IX Item "$json->boolean_values ([$false, $true])" .PD 0 .ie n .IP "($false, $true) = $json\->get_boolean_values" 4 .el .IP "($false, \f(CW$true\fR) = \f(CW$json\fR\->get_boolean_values" 4 .IX Item "($false, $true) = $json->get_boolean_values" .PD By default, \s-1JSON\s0 booleans will be decoded as overloaded \&\f(CW$Types::Serialiser::false\fR and \f(CW$Types::Serialiser::true\fR objects. .Sp With this method you can specify your own boolean values for decoding \- on decode, \s-1JSON\s0 \f(CW\*(C`false\*(C'\fR will be decoded as a copy of \f(CW$false\fR, and \s-1JSON\s0 \&\f(CW\*(C`true\*(C'\fR will be decoded as \f(CW$true\fR (\*(L"copy\*(R" here is the same thing as assigning a value to another variable, i.e. \f(CW\*(C`$copy = $false\*(C'\fR). .Sp Calling this method without any arguments will reset the booleans to their default values. .Sp \&\f(CW\*(C`get_boolean_values\*(C'\fR will return both \f(CW$false\fR and \f(CW$true\fR values, or the empty list when they are set to the default. .ie n .IP "$json = $json\->filter_json_object ([$coderef\->($hashref)])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->filter_json_object ([$coderef\->($hashref)])" 4 .IX Item "$json = $json->filter_json_object ([$coderef->($hashref)])" When \f(CW$coderef\fR is specified, it will be called from \f(CW\*(C`decode\*(C'\fR each time it decodes a \s-1JSON\s0 object. The only argument is a reference to the newly-created hash. If the code reference returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (\s-1NOTE:\s0 \fInot\fR \f(CW\*(C`undef\*(C'\fR, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. .Sp When \f(CW$coderef\fR is omitted or undefined, any existing callback will be removed and \f(CW\*(C`decode\*(C'\fR will not change the deserialised hash in any way. .Sp Example, convert all \s-1JSON\s0 objects into the integer 5: .Sp .Vb 6 \& my $js = JSON::XS\->new\->filter_json_object (sub { 5 }); \& # returns [5] \& $js\->decode (\*(Aq[{}]\*(Aq) \& # throw an exception because allow_nonref is not enabled \& # so a lone 5 is not allowed. \& $js\->decode (\*(Aq{"a":1, "b":2}\*(Aq); .Ve .ie n .IP "$json = $json\->filter_json_single_key_object ($key [=> $coderef\->($value)])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->filter_json_single_key_object ($key [=> \f(CW$coderef\fR\->($value)])" 4 .IX Item "$json = $json->filter_json_single_key_object ($key [=> $coderef->($value)])" Works remotely similar to \f(CW\*(C`filter_json_object\*(C'\fR, but is only called for \&\s-1JSON\s0 objects having a single key named \f(CW$key\fR. .Sp This \f(CW$coderef\fR is called before the one specified via \&\f(CW\*(C`filter_json_object\*(C'\fR, if any. It gets passed the single value in the \s-1JSON\s0 object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even \f(CW\*(C`undef\*(C'\fR but the empty list), the callback from \f(CW\*(C`filter_json_object\*(C'\fR will be called next, as if no single-key callback were specified. .Sp If \f(CW$coderef\fR is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. .Sp As this callback gets called less often then the \f(CW\*(C`filter_json_object\*(C'\fR one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key \s-1JSON\s0 objects are as close to the type-tagged value concept as \s-1JSON\s0 gets (it's basically an \s-1ID/VALUE\s0 tuple). Of course, \s-1JSON\s0 does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. .Sp Typical names for the single object key are \f(CW\*(C`_\|_class_whatever_\|_\*(C'\fR, or \&\f(CW\*(C`$_\|_dollars_are_rarely_used_\|_$\*(C'\fR or \f(CW\*(C`}ugly_brace_placement\*(C'\fR, or even things like \f(CW\*(C`_\|_class_md5sum(classname)_\|_\*(C'\fR, to reduce the risk of clashing with real hashes. .Sp Example, decode \s-1JSON\s0 objects of the form \f(CW\*(C`{ "_\|_widget_\|_" => }\*(C'\fR into the corresponding \f(CW$WIDGET{}\fR object: .Sp .Vb 7 \& # return whatever is in $WIDGET{5}: \& JSON::XS \& \->new \& \->filter_json_single_key_object (_\|_widget_\|_ => sub { \& $WIDGET{ $_[0] } \& }) \& \->decode (\*(Aq{"_\|_widget_\|_": 5\*(Aq) \& \& # this can be used with a TO_JSON method in some "widget" class \& # for serialisation to json: \& sub WidgetBase::TO_JSON { \& my ($self) = @_; \& \& unless ($self\->{id}) { \& $self\->{id} = ..get..some..id..; \& $WIDGET{$self\->{id}} = $self; \& } \& \& { _\|_widget_\|_ => $self\->{id} } \& } .Ve .ie n .IP "$json = $json\->shrink ([$enable])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->shrink ([$enable])" 4 .IX Item "$json = $json->shrink ([$enable])" .PD 0 .ie n .IP "$enabled = $json\->get_shrink" 4 .el .IP "\f(CW$enabled\fR = \f(CW$json\fR\->get_shrink" 4 .IX Item "$enabled = $json->get_shrink" .PD Perl usually over-allocates memory a bit when allocating space for strings. This flag optionally resizes strings generated by either \&\f(CW\*(C`encode\*(C'\fR or \f(CW\*(C`decode\*(C'\fR to their minimum size possible. This can save memory when your \s-1JSON\s0 texts are either very very long or you have many short strings. It will also try to downgrade any strings to octet-form if possible: perl stores strings internally either in an encoding called UTF-X or in octet-form. The latter cannot store everything but uses less space in general (and some buggy Perl or C code might even rely on that internal representation being used). .Sp The actual definition of what shrink does might change in future versions, but it will always try to save space at the expense of time. .Sp If \f(CW$enable\fR is true (or missing), the string returned by \f(CW\*(C`encode\*(C'\fR will be shrunk-to-fit, while all strings generated by \f(CW\*(C`decode\*(C'\fR will also be shrunk-to-fit. .Sp If \f(CW$enable\fR is false, then the normal perl allocation algorithms are used. If you work with your data, then this is likely to be faster. .Sp In the future, this setting might control other things, such as converting strings that look like integers or floats into integers or floats internally (there is no difference on the Perl level), saving space. .ie n .IP "$json = $json\->max_depth ([$maximum_nesting_depth])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->max_depth ([$maximum_nesting_depth])" 4 .IX Item "$json = $json->max_depth ([$maximum_nesting_depth])" .PD 0 .ie n .IP "$max_depth = $json\->get_max_depth" 4 .el .IP "\f(CW$max_depth\fR = \f(CW$json\fR\->get_max_depth" 4 .IX Item "$max_depth = $json->get_max_depth" .PD Sets the maximum nesting level (default \f(CW512\fR) accepted while encoding or decoding. If a higher nesting level is detected in \s-1JSON\s0 text or a Perl data structure, then the encoder and decoder will stop and croak at that point. .Sp Nesting level is defined by number of hash\- or arrayrefs that the encoder needs to traverse to reach a given point or the number of \f(CW\*(C`{\*(C'\fR or \f(CW\*(C`[\*(C'\fR characters without their matching closing parenthesis crossed to reach a given character in a string. .Sp Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. .Sp If no argument is given, the highest possible setting will be used, which is rarely useful. .Sp Note that nesting is implemented by recursion in C. The default value has been chosen to be as large as typical operating systems allow without crashing. .Sp See \s-1SECURITY CONSIDERATIONS,\s0 below, for more info on why this is useful. .ie n .IP "$json = $json\->max_size ([$maximum_string_size])" 4 .el .IP "\f(CW$json\fR = \f(CW$json\fR\->max_size ([$maximum_string_size])" 4 .IX Item "$json = $json->max_size ([$maximum_string_size])" .PD 0 .ie n .IP "$max_size = $json\->get_max_size" 4 .el .IP "\f(CW$max_size\fR = \f(CW$json\fR\->get_max_size" 4 .IX Item "$max_size = $json->get_max_size" .PD Set the maximum length a \s-1JSON\s0 text may have (in bytes) where decoding is being attempted. The default is \f(CW0\fR, meaning no limit. When \f(CW\*(C`decode\*(C'\fR is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on \f(CW\*(C`encode\*(C'\fR (yet). .Sp If no argument is given, the limit check will be deactivated (same as when \&\f(CW0\fR is specified). .Sp See \s-1SECURITY CONSIDERATIONS,\s0 below, for more info on why this is useful. .ie n .IP "$json_text = $json\->encode ($perl_scalar)" 4 .el .IP "\f(CW$json_text\fR = \f(CW$json\fR\->encode ($perl_scalar)" 4 .IX Item "$json_text = $json->encode ($perl_scalar)" Converts the given Perl value or data structure to its \s-1JSON\s0 representation. Croaks on error. .ie n .IP "$perl_scalar = $json\->decode ($json_text)" 4 .el .IP "\f(CW$perl_scalar\fR = \f(CW$json\fR\->decode ($json_text)" 4 .IX Item "$perl_scalar = $json->decode ($json_text)" The opposite of \f(CW\*(C`encode\*(C'\fR: expects a \s-1JSON\s0 text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. .ie n .IP "($perl_scalar, $characters) = $json\->decode_prefix ($json_text)" 4 .el .IP "($perl_scalar, \f(CW$characters\fR) = \f(CW$json\fR\->decode_prefix ($json_text)" 4 .IX Item "($perl_scalar, $characters) = $json->decode_prefix ($json_text)" This works like the \f(CW\*(C`decode\*(C'\fR method, but instead of raising an exception when there is trailing garbage after the first \s-1JSON\s0 object, it will silently stop parsing there and return the number of characters consumed so far. .Sp This is useful if your \s-1JSON\s0 texts are not delimited by an outer protocol and you need to know where the \s-1JSON\s0 text ends. .Sp .Vb 2 \& JSON::XS\->new\->decode_prefix ("[1] the tail") \& => ([1], 3) .Ve .SH "INCREMENTAL PARSING" .IX Header "INCREMENTAL PARSING" In some cases, there is the need for incremental parsing of \s-1JSON\s0 texts. While this module always has to keep both \s-1JSON\s0 text and resulting Perl data structure in memory at one time, it does allow you to parse a \&\s-1JSON\s0 stream incrementally. It does so by accumulating text until it has a full \s-1JSON\s0 object, which it then can decode. This process is similar to using \f(CW\*(C`decode_prefix\*(C'\fR to see if a full \s-1JSON\s0 object is available, but is much more efficient (and can be implemented with a minimum of method calls). .PP \&\s-1JSON::XS\s0 will only attempt to parse the \s-1JSON\s0 text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid \s-1JSON\s0 text has been seen. This means you need to set resource limits (e.g. \f(CW\*(C`max_size\*(C'\fR) to ensure the parser will stop parsing in the presence if syntax errors. .PP The following methods implement this incremental parser. .ie n .IP "[void, scalar or list context] = $json\->incr_parse ([$string])" 4 .el .IP "[void, scalar or list context] = \f(CW$json\fR\->incr_parse ([$string])" 4 .IX Item "[void, scalar or list context] = $json->incr_parse ([$string])" This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). .Sp If \f(CW$string\fR is given, then this string is appended to the already existing \s-1JSON\s0 fragment stored in the \f(CW$json\fR object. .Sp After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. .Sp If the method is called in scalar context, then it will try to extract exactly \fIone\fR \s-1JSON\s0 object. If that is successful, it will return this object, otherwise it will return \f(CW\*(C`undef\*(C'\fR. If there is a parse error, this method will croak just as \f(CW\*(C`decode\*(C'\fR would do (one can then use \&\f(CW\*(C`incr_skip\*(C'\fR to skip the erroneous part). This is the most common way of using the method. .Sp And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the \s-1JSON\s0 objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed \s-1JSON\s0 texts will be lost. .Sp Example: Parse some \s-1JSON\s0 arrays/objects in a given string and return them. .Sp .Vb 1 \& my @objs = JSON::XS\->new\->incr_parse ("[5][7][1,2]"); .Ve .ie n .IP "$lvalue_string = $json\->incr_text" 4 .el .IP "\f(CW$lvalue_string\fR = \f(CW$json\fR\->incr_text" 4 .IX Item "$lvalue_string = $json->incr_text" This method returns the currently stored \s-1JSON\s0 fragment as an lvalue, that is, you can manipulate it. This \fIonly\fR works when a preceding call to \&\f(CW\*(C`incr_parse\*(C'\fR in \fIscalar context\fR successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it \fIwill\fR fail under real world conditions). As a special exception, you can also call this method before having parsed anything. .Sp That means you can only use this function to look at or manipulate text before or after complete \s-1JSON\s0 objects, not while the parser is in the middle of parsing a \s-1JSON\s0 object. .Sp This function is useful in two cases: a) finding the trailing text after a \&\s-1JSON\s0 object or b) parsing multiple \s-1JSON\s0 objects separated by non-JSON text (such as commas). .ie n .IP "$json\->incr_skip" 4 .el .IP "\f(CW$json\fR\->incr_skip" 4 .IX Item "$json->incr_skip" This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after \&\f(CW\*(C`incr_parse\*(C'\fR died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. .Sp The difference to \f(CW\*(C`incr_reset\*(C'\fR is that only text until the parse error occurred is removed. .ie n .IP "$json\->incr_reset" 4 .el .IP "\f(CW$json\fR\->incr_reset" 4 .IX Item "$json->incr_reset" This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. .Sp This is useful if you want to repeatedly parse \s-1JSON\s0 objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. .SS "\s-1LIMITATIONS\s0" .IX Subsection "LIMITATIONS" The incremental parser is a non-exact parser: it works by gathering as much text as possible that \fIcould\fR be a valid \s-1JSON\s0 text, followed by trying to decode it. .PP That means it sometimes needs to read more data than strictly necessary to diagnose an invalid \s-1JSON\s0 text. For example, after parsing the following fragment, the parser \fIcould\fR stop with an error, as this fragment \&\fIcannot\fR be the beginning of a valid \s-1JSON\s0 text: .PP .Vb 1 \& [, .Ve .PP In reality, hopwever, the parser might continue to read data until a length limit is exceeded or it finds a closing bracket. .SS "\s-1EXAMPLES\s0" .IX Subsection "EXAMPLES" Some examples will make all this clearer. First, a simple example that works similarly to \f(CW\*(C`decode_prefix\*(C'\fR: We want to decode the \s-1JSON\s0 object at the start of a string and identify the portion after the \s-1JSON\s0 object: .PP .Vb 1 \& my $text = "[1,2,3] hello"; \& \& my $json = new JSON::XS; \& \& my $obj = $json\->incr_parse ($text) \& or die "expected JSON object or array at beginning of string"; \& \& my $tail = $json\->incr_text; \& # $tail now contains " hello" .Ve .PP Easy, isn't it? .PP Now for a more complicated example: Imagine a hypothetical protocol where you read some requests from a \s-1TCP\s0 stream, and each request is a \s-1JSON\s0 array, without any separation between them (in fact, it is often useful to use newlines as \*(L"separators\*(R", as these get interpreted as whitespace at the start of the \s-1JSON\s0 text, which makes it possible to test said protocol with \f(CW\*(C`telnet\*(C'\fR...). .PP Here is how you'd do it (it is trivial to write this in an event-based manner): .PP .Vb 1 \& my $json = new JSON::XS; \& \& # read some data from the socket \& while (sysread $socket, my $buf, 4096) { \& \& # split and decode as many requests as possible \& for my $request ($json\->incr_parse ($buf)) { \& # act on the $request \& } \& } .Ve .PP Another complicated example: Assume you have a string with \s-1JSON\s0 objects or arrays, all separated by (optional) comma characters (e.g. \f(CW\*(C`[1],[2], [3]\*(C'\fR). To parse them, we have to skip the commas between the \s-1JSON\s0 texts, and here is where the lvalue-ness of \f(CW\*(C`incr_text\*(C'\fR comes in useful: .PP .Vb 2 \& my $text = "[1],[2], [3]"; \& my $json = new JSON::XS; \& \& # void context, so no parsing done \& $json\->incr_parse ($text); \& \& # now extract as many objects as possible. note the \& # use of scalar context so incr_text can be called. \& while (my $obj = $json\->incr_parse) { \& # do something with $obj \& \& # now skip the optional comma \& $json\->incr_text =~ s/^ \es* , //x; \& } .Ve .PP Now lets go for a very complex example: Assume that you have a gigantic \&\s-1JSON\s0 array-of-objects, many gigabytes in size, and you want to parse it, but you cannot load it into memory fully (this has actually happened in the real world :). .PP Well, you lost, you have to implement your own \s-1JSON\s0 parser. But \s-1JSON::XS\s0 can still help you: You implement a (very simple) array parser and let \&\s-1JSON\s0 decode the array elements, which are all full \s-1JSON\s0 objects on their own (this wouldn't work if the array elements could be \s-1JSON\s0 numbers, for example): .PP .Vb 1 \& my $json = new JSON::XS; \& \& # open the monster \& open my $fh, "incr_parse ($buf); # void context, so no parsing \& \& # Exit the loop once we found and removed(!) the initial "[". \& # In essence, we are (ab\-)using the $json object as a simple scalar \& # we append data to. \& last if $json\->incr_text =~ s/^ \es* \e[ //x; \& } \& \& # now we have the skipped the initial "[", so continue \& # parsing all the elements. \& for (;;) { \& # in this loop we read data until we got a single JSON object \& for (;;) { \& if (my $obj = $json\->incr_parse) { \& # do something with $obj \& last; \& } \& \& # add more data \& sysread $fh, my $buf, 65536 \& or die "read error: $!"; \& $json\->incr_parse ($buf); # void context, so no parsing \& } \& \& # in this loop we read data until we either found and parsed the \& # separating "," between elements, or the final "]" \& for (;;) { \& # first skip whitespace \& $json\->incr_text =~ s/^\es*//; \& \& # if we find "]", we are done \& if ($json\->incr_text =~ s/^\e]//) { \& print "finished.\en"; \& exit; \& } \& \& # if we find ",", we can continue with the next element \& if ($json\->incr_text =~ s/^,//) { \& last; \& } \& \& # if we find anything else, we have a parse error! \& if (length $json\->incr_text) { \& die "parse error near ", $json\->incr_text; \& } \& \& # else add more data \& sysread $fh, my $buf, 65536 \& or die "read error: $!"; \& $json\->incr_parse ($buf); # void context, so no parsing \& } .Ve .PP This is a complex example, but most of the complexity comes from the fact that we are trying to be correct (bear with me if I am wrong, I never ran the above example :). .SH "MAPPING" .IX Header "MAPPING" This section describes how \s-1JSON::XS\s0 maps Perl values to \s-1JSON\s0 values and vice versa. These mappings are designed to \*(L"do the right thing\*(R" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). .PP For the more enlightened: note that in the following descriptions, lowercase \fIperl\fR refers to the Perl interpreter, while uppercase \fIPerl\fR refers to the abstract Perl language itself. .SS "\s-1JSON\s0 \-> \s-1PERL\s0" .IX Subsection "JSON -> PERL" .IP "object" 4 .IX Item "object" A \s-1JSON\s0 object becomes a reference to a hash in Perl. No ordering of object keys is preserved (\s-1JSON\s0 does not preserve object key ordering itself). .IP "array" 4 .IX Item "array" A \s-1JSON\s0 array becomes a reference to an array in Perl. .IP "string" 4 .IX Item "string" A \s-1JSON\s0 string becomes a string scalar in Perl \- Unicode codepoints in \s-1JSON\s0 are represented by the same codepoints in the Perl string, so no manual decoding is necessary. .IP "number" 4 .IX Item "number" A \s-1JSON\s0 number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. .Sp If the number consists of digits only, \s-1JSON::XS\s0 will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the \s-1JSON\s0 number will be re-encoded to a \s-1JSON\s0 string). .Sp Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the \s-1JSON\s0 number will still be re-encoded as a \s-1JSON\s0 number). .Sp Note that precision is not accuracy \- binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, \s-1JSON::XS\s0 only guarantees precision up to but not including the least significant bit. .IP "true, false" 4 .IX Item "true, false" These \s-1JSON\s0 atoms become \f(CW\*(C`Types::Serialiser::true\*(C'\fR and \&\f(CW\*(C`Types::Serialiser::false\*(C'\fR, respectively. They are overloaded to act almost exactly like the numbers \f(CW1\fR and \f(CW0\fR. You can check whether a scalar is a \s-1JSON\s0 boolean by using the \f(CW\*(C`Types::Serialiser::is_bool\*(C'\fR function (after \f(CW\*(C`use Types::Serialier\*(C'\fR, of course). .IP "null" 4 .IX Item "null" A \s-1JSON\s0 null atom becomes \f(CW\*(C`undef\*(C'\fR in Perl. .ie n .IP "shell-style comments (""# \fItext\fP"")" 4 .el .IP "shell-style comments (\f(CW# \f(CItext\f(CW\fR)" 4 .IX Item "shell-style comments (# text)" As a nonstandard extension to the \s-1JSON\s0 syntax that is enabled by the \&\f(CW\*(C`relaxed\*(C'\fR setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. .ie n .IP "tagged values (""(\fItag\fP)\fIvalue\fP"")." 4 .el .IP "tagged values (\f(CW(\f(CItag\f(CW)\f(CIvalue\f(CW\fR)." 4 .IX Item "tagged values ((tag)value)." Another nonstandard extension to the \s-1JSON\s0 syntax, enabled with the \&\f(CW\*(C`allow_tags\*(C'\fR setting, are tagged values. In this implementation, the \&\fItag\fR must be a perl package/class name encoded as a \s-1JSON\s0 string, and the \&\fIvalue\fR must be a \s-1JSON\s0 array encoding optional constructor arguments. .Sp See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .SS "\s-1PERL\s0 \-> \s-1JSON\s0" .IX Subsection "PERL -> JSON" The mapping from Perl to \s-1JSON\s0 is slightly more difficult, as Perl is a truly typeless language, so we can only guess which \s-1JSON\s0 type is meant by a Perl value. .IP "hash references" 4 .IX Item "hash references" Perl hash references become \s-1JSON\s0 objects. As there is no inherent ordering in hash keys (or \s-1JSON\s0 objects), they will usually be encoded in a pseudo-random order. \s-1JSON::XS\s0 can optionally sort the hash keys (determined by the \fIcanonical\fR flag), so the same datastructure will serialise to the same \s-1JSON\s0 text (given same settings and version of \&\s-1JSON::XS\s0), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some \s-1JSON\s0 text against another for equality. .IP "array references" 4 .IX Item "array references" Perl array references become \s-1JSON\s0 arrays. .IP "other references" 4 .IX Item "other references" Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers \f(CW0\fR and \&\f(CW1\fR, which get turned into \f(CW\*(C`false\*(C'\fR and \f(CW\*(C`true\*(C'\fR atoms in \s-1JSON.\s0 .Sp Since \f(CW\*(C`JSON::XS\*(C'\fR uses the boolean model from Types::Serialiser, you can also \f(CW\*(C`use Types::Serialiser\*(C'\fR and then use \f(CW\*(C`Types::Serialiser::false\*(C'\fR and \f(CW\*(C`Types::Serialiser::true\*(C'\fR to improve readability. .Sp .Vb 2 \& use Types::Serialiser; \& encode_json [\e0, Types::Serialiser::true] # yields [false,true] .Ve .IP "Types::Serialiser::true, Types::Serialiser::false" 4 .IX Item "Types::Serialiser::true, Types::Serialiser::false" These special values from the Types::Serialiser module become \s-1JSON\s0 true and \s-1JSON\s0 false values, respectively. You can also use \f(CW\*(C`\e1\*(C'\fR and \f(CW\*(C`\e0\*(C'\fR directly if you want. .IP "blessed objects" 4 .IX Item "blessed objects" Blessed objects are not directly representable in \s-1JSON,\s0 but \f(CW\*(C`JSON::XS\*(C'\fR allows various ways of handling objects. See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .IP "simple scalars" 4 .IX Item "simple scalars" Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: \s-1JSON::XS\s0 will encode undefined scalars as \&\s-1JSON\s0 \f(CW\*(C`null\*(C'\fR values, scalars that have last been used in a string context before encoding as \s-1JSON\s0 strings, and anything else as number value: .Sp .Vb 4 \& # dump as number \& encode_json [2] # yields [2] \& encode_json [\-3.0e17] # yields [\-3e+17] \& my $value = 5; encode_json [$value] # yields [5] \& \& # used as string, so dump as string \& print $value; \& encode_json [$value] # yields ["5"] \& \& # undef becomes null \& encode_json [undef] # yields [null] .Ve .Sp You can force the type to be a \s-1JSON\s0 string by stringifying it: .Sp .Vb 4 \& my $x = 3.1; # some variable containing a number \& "$x"; # stringified \& $x .= ""; # another, more awkward way to stringify \& print $x; # perl does it for you, too, quite often .Ve .Sp You can force the type to be a \s-1JSON\s0 number by numifying it: .Sp .Vb 3 \& my $x = "3"; # some variable containing a string \& $x += 0; # numify it, ensuring it will be dumped as a number \& $x *= 1; # same thing, the choice is yours. .Ve .Sp You can not currently force the type in other, less obscure, ways. Tell me if you need this capability (but don't forget to explain why it's needed :). .Sp Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's \- these cannot be represented in \s-1JSON,\s0 and it is an error to pass those in. .SS "\s-1OBJECT SERIALISATION\s0" .IX Subsection "OBJECT SERIALISATION" As \s-1JSON\s0 cannot directly represent Perl objects, you have to choose between a pure \s-1JSON\s0 representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the \s-1JSON\s0 syntax, tagged values. .PP \fI\s-1SERIALISATION\s0\fR .IX Subsection "SERIALISATION" .PP What happens when \f(CW\*(C`JSON::XS\*(C'\fR encounters a Perl object depends on the \&\f(CW\*(C`allow_blessed\*(C'\fR, \f(CW\*(C`convert_blessed\*(C'\fR and \f(CW\*(C`allow_tags\*(C'\fR settings, which are used in this order: .ie n .IP "1. ""allow_tags"" is enabled and the object has a ""FREEZE"" method." 4 .el .IP "1. \f(CWallow_tags\fR is enabled and the object has a \f(CWFREEZE\fR method." 4 .IX Item "1. allow_tags is enabled and the object has a FREEZE method." In this case, \f(CW\*(C`JSON::XS\*(C'\fR uses the Types::Serialiser object serialisation protocol to create a tagged \s-1JSON\s0 value, using a nonstandard extension to the \s-1JSON\s0 syntax. .Sp This works by invoking the \f(CW\*(C`FREEZE\*(C'\fR method on the object, with the first argument being the object to serialise, and the second argument being the constant string \f(CW\*(C`JSON\*(C'\fR to distinguish it from other serialisers. .Sp The \f(CW\*(C`FREEZE\*(C'\fR method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged \s-1JSON\s0 value in the following format: .Sp .Vb 1 \& ("classname")[FREEZE return values...] .Ve .Sp e.g.: .Sp .Vb 3 \& ("URI")["http://www.google.com/"] \& ("MyDate")[2013,10,29] \& ("ImageData::JPEG")["Z3...VlCg=="] .Ve .Sp For example, the hypothetical \f(CW\*(C`My::Object\*(C'\fR \f(CW\*(C`FREEZE\*(C'\fR method might use the objects \f(CW\*(C`type\*(C'\fR and \f(CW\*(C`id\*(C'\fR members to encode the object: .Sp .Vb 2 \& sub My::Object::FREEZE { \& my ($self, $serialiser) = @_; \& \& ($self\->{type}, $self\->{id}) \& } .Ve .ie n .IP "2. ""convert_blessed"" is enabled and the object has a ""TO_JSON"" method." 4 .el .IP "2. \f(CWconvert_blessed\fR is enabled and the object has a \f(CWTO_JSON\fR method." 4 .IX Item "2. convert_blessed is enabled and the object has a TO_JSON method." In this case, the \f(CW\*(C`TO_JSON\*(C'\fR method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into \&\s-1JSON.\s0 This scalar replaces the object in the \s-1JSON\s0 text. .Sp For example, the following \f(CW\*(C`TO_JSON\*(C'\fR method will convert all \s-1URI\s0 objects to \s-1JSON\s0 strings when serialised. The fatc that these values originally were \s-1URI\s0 objects is lost. .Sp .Vb 4 \& sub URI::TO_JSON { \& my ($uri) = @_; \& $uri\->as_string \& } .Ve .ie n .IP "3. ""allow_blessed"" is enabled." 4 .el .IP "3. \f(CWallow_blessed\fR is enabled." 4 .IX Item "3. allow_blessed is enabled." The object will be serialised as a \s-1JSON\s0 null value. .IP "4. none of the above" 4 .IX Item "4. none of the above" If none of the settings are enabled or the respective methods are missing, \&\f(CW\*(C`JSON::XS\*(C'\fR throws an exception. .PP \fI\s-1DESERIALISATION\s0\fR .IX Subsection "DESERIALISATION" .PP For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case \f(CW\*(C`allow_tags\*(C'\fR decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the \f(CW\*(C`filter_json_object\*(C'\fR or \&\f(CW\*(C`filter_json_single_key_object\*(C'\fR callbacks to get some real objects our of your \s-1JSON.\s0 .PP This section only considers the tagged value case: I a tagged \s-1JSON\s0 object is encountered during decoding and \f(CW\*(C`allow_tags\*(C'\fR is disabled, a parse error will result (as if tagged values were not part of the grammar). .PP If \f(CW\*(C`allow_tags\*(C'\fR is enabled, \f(CW\*(C`JSON::XS\*(C'\fR will look up the \f(CW\*(C`THAW\*(C'\fR method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. .PP Otherwise, the \f(CW\*(C`THAW\*(C'\fR method is invoked with the classname as first argument, the constant string \f(CW\*(C`JSON\*(C'\fR as second argument, and all the values from the \s-1JSON\s0 array (the values originally returned by the \&\f(CW\*(C`FREEZE\*(C'\fR method) as remaining arguments. .PP The method must then return the object. While technically you can return any Perl scalar, you might have to enable the \f(CW\*(C`enable_nonref\*(C'\fR setting to make that work in all cases, so better return an actual blessed reference. .PP As an example, let's implement a \f(CW\*(C`THAW\*(C'\fR function that regenerates the \&\f(CW\*(C`My::Object\*(C'\fR from the \f(CW\*(C`FREEZE\*(C'\fR example earlier: .PP .Vb 2 \& sub My::Object::THAW { \& my ($class, $serialiser, $type, $id) = @_; \& \& $class\->new (type => $type, id => $id) \& } .Ve .SH "ENCODING/CODESET FLAG NOTES" .IX Header "ENCODING/CODESET FLAG NOTES" The interested reader might have seen a number of flags that signify encodings or codesets \- \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR. There seems to be some confusion on what these do, so here is a short comparison: .PP \&\f(CW\*(C`utf8\*(C'\fR controls whether the \s-1JSON\s0 text created by \f(CW\*(C`encode\*(C'\fR (and expected by \f(CW\*(C`decode\*(C'\fR) is \s-1UTF\-8\s0 encoded or not, while \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR only control whether \f(CW\*(C`encode\*(C'\fR escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. .PP Care has been taken to make all flags symmetrical with respect to \&\f(CW\*(C`encode\*(C'\fR and \f(CW\*(C`decode\*(C'\fR, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used \&\- in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. .PP Below comes a verbose discussion of these flags. Note that a \*(L"codeset\*(R" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and \fIencodes\fR them, in our case into octets. Unicode is (among other things) a codeset, \s-1UTF\-8\s0 is an encoding, and \s-1ISO\-8859\-1\s0 (= latin 1) and \s-1ASCII\s0 are both codesets \fIand\fR encodings at the same time, which can be confusing. .ie n .IP """utf8"" flag disabled" 4 .el .IP "\f(CWutf8\fR flag disabled" 4 .IX Item "utf8 flag disabled" When \f(CW\*(C`utf8\*(C'\fR is disabled (the default), then \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except \&\*(L"(re\-)interpreting\*(R" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). .Sp This is useful when you want to do the encoding yourself (e.g. when you want to have \s-1UTF\-16\s0 encoded \s-1JSON\s0 texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to \s-1UTF\-8\s0 you certainly do \s-1NOT\s0 want to \s-1UTF\-8\s0 encode your data first and have Perl encode it another time). .ie n .IP """utf8"" flag enabled" 4 .el .IP "\f(CWutf8\fR flag enabled" 4 .IX Item "utf8 flag enabled" If the \f(CW\*(C`utf8\*(C'\fR\-flag is enabled, \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR will encode all characters using the corresponding \s-1UTF\-8\s0 multi-byte sequence, and will expect your input strings to be encoded as \s-1UTF\-8,\s0 that is, no \*(L"character\*(R" of the input string must have any value > 255, as \s-1UTF\-8\s0 does not allow that. .Sp The \f(CW\*(C`utf8\*(C'\fR flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get a \s-1UTF\-8\s0 encoded octet/binary string in Perl. .ie n .IP """latin1"" or ""ascii"" flags enabled" 4 .el .IP "\f(CWlatin1\fR or \f(CWascii\fR flags enabled" 4 .IX Item "latin1 or ascii flags enabled" With \f(CW\*(C`latin1\*(C'\fR (or \f(CW\*(C`ascii\*(C'\fR) enabled, \f(CW\*(C`encode\*(C'\fR will escape characters with ordinal values > 255 (> 127 with \f(CW\*(C`ascii\*(C'\fR) and encode the remaining characters as specified by the \f(CW\*(C`utf8\*(C'\fR flag. .Sp If \f(CW\*(C`utf8\*(C'\fR is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a \&\s-1ISO\-8859\-1\s0 string, and a Unicode string with all character values < 128 is the same thing as an \s-1ASCII\s0 string in Perl). .Sp If \f(CW\*(C`utf8\*(C'\fR is enabled, you still get a correct UTF\-8\-encoded string, regardless of these flags, just some more characters will be escaped using \&\f(CW\*(C`\euXXXX\*(C'\fR then before. .Sp Note that \s-1ISO\-8859\-1\-\s0\fIencoded\fR strings are not compatible with \s-1UTF\-8\s0 encoding, while ASCII-encoded strings are. That is because the \s-1ISO\-8859\-1\s0 encoding is \s-1NOT\s0 a subset of \s-1UTF\-8\s0 (despite the \s-1ISO\-8859\-1\s0 \fIcodeset\fR being a subset of Unicode), while \s-1ASCII\s0 is. .Sp Surprisingly, \f(CW\*(C`decode\*(C'\fR will ignore these flags and so treat all input values as governed by the \f(CW\*(C`utf8\*(C'\fR flag. If it is disabled, this allows you to decode \s-1ISO\-8859\-1\-\s0 and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode \s-1UTF\-8\s0 encoded strings. .Sp So neither \f(CW\*(C`latin1\*(C'\fR nor \f(CW\*(C`ascii\*(C'\fR are incompatible with the \f(CW\*(C`utf8\*(C'\fR flag \- they only govern when the \s-1JSON\s0 output engine escapes a character or not. .Sp The main use for \f(CW\*(C`latin1\*(C'\fR is to relatively efficiently store binary data as \s-1JSON,\s0 at the expense of breaking compatibility with most \s-1JSON\s0 decoders. .Sp The main use for \f(CW\*(C`ascii\*(C'\fR is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as \s-1UTF\-8, ISO\-8859\-1, ASCII, KOI8\-R\s0 or most about any character set and 8\-bit\-encoding, and still get the same data structure back. This is useful when your channel for \s-1JSON\s0 transfer is not 8\-bit clean or the encoding might be mangled in between (e.g. in mail), and works because \s-1ASCII\s0 is a proper subset of most 8\-bit and multibyte encodings in use in the world. .SS "\s-1JSON\s0 and ECMAscript" .IX Subsection "JSON and ECMAscript" \&\s-1JSON\s0 syntax is based on how literals are represented in javascript (the not-standardised predecessor of ECMAscript) which is presumably why it is called \*(L"JavaScript Object Notation\*(R". .PP However, \s-1JSON\s0 is not a subset (and also not a superset of course) of ECMAscript (the standard) or javascript (whatever browsers actually implement). .PP If you want to use javascript's \f(CW\*(C`eval\*(C'\fR function to \*(L"parse\*(R" \s-1JSON,\s0 you might run into parse errors for valid \s-1JSON\s0 texts, or the resulting data structure might not be queryable: .PP One of the problems is that U+2028 and U+2029 are valid characters inside \&\s-1JSON\s0 strings, but are not allowed in ECMAscript string literals, so the following Perl fragment will not output something that can be guaranteed to be parsable by javascript's \f(CW\*(C`eval\*(C'\fR: .PP .Vb 1 \& use JSON::XS; \& \& print encode_json [chr 0x2028]; .Ve .PP The right fix for this is to use a proper \s-1JSON\s0 parser in your javascript programs, and not rely on \f(CW\*(C`eval\*(C'\fR (see for example Douglas Crockford's \&\fIjson2.js\fR parser). .PP If this is not an option, you can, as a stop-gap measure, simply encode to ASCII-only \s-1JSON:\s0 .PP .Vb 1 \& use JSON::XS; \& \& print JSON::XS\->new\->ascii\->encode ([chr 0x2028]); .Ve .PP Note that this will enlarge the resulting \s-1JSON\s0 text quite a bit if you have many non-ASCII characters. You might be tempted to run some regexes to only escape U+2028 and U+2029, e.g.: .PP .Vb 5 \& # DO NOT USE THIS! \& my $json = JSON::XS\->new\->utf8\->encode ([chr 0x2028]); \& $json =~ s/\exe2\ex80\exa8/\e\eu2028/g; # escape U+2028 \& $json =~ s/\exe2\ex80\exa9/\e\eu2029/g; # escape U+2029 \& print $json; .Ve .PP Note that \fIthis is a bad idea\fR: the above only works for U+2028 and U+2029 and thus only for fully ECMAscript-compliant parsers. Many existing javascript implementations, however, have issues with other characters as well \- using \f(CW\*(C`eval\*(C'\fR naively simply \fIwill\fR cause problems. .PP Another problem is that some javascript implementations reserve some property names for their own purposes (which probably makes them non-ECMAscript-compliant). For example, Iceweasel reserves the \&\f(CW\*(C`_\|_proto_\|_\*(C'\fR property name for its own purposes. .PP If that is a problem, you could parse try to filter the resulting \s-1JSON\s0 output for these property strings, e.g.: .PP .Vb 1 \& $json =~ s/"_\|_proto_\|_"\es*:/"_\|_proto_\|_renamed":/g; .Ve .PP This works because \f(CW\*(C`_\|_proto_\|_\*(C'\fR is not valid outside of strings, so every occurrence of \f(CW\*(C`"_\|_proto_\|_"\es*:\*(C'\fR must be a string used as property name. .PP If you know of other incompatibilities, please let me know. .SS "\s-1JSON\s0 and \s-1YAML\s0" .IX Subsection "JSON and YAML" You often hear that \s-1JSON\s0 is a subset of \s-1YAML.\s0 This is, however, a mass hysteria(*) and very far from the truth (as of the time of this writing), so let me state it clearly: \fIin general, there is no way to configure \&\s-1JSON::XS\s0 to output a data structure as valid \s-1YAML\s0\fR that works in all cases. .PP If you really must use \s-1JSON::XS\s0 to generate \s-1YAML,\s0 you should use this algorithm (subject to change in future versions): .PP .Vb 2 \& my $to_yaml = JSON::XS\->new\->utf8\->space_after (1); \& my $yaml = $to_yaml\->encode ($ref) . "\en"; .Ve .PP This will \fIusually\fR generate \s-1JSON\s0 texts that also parse as valid \&\s-1YAML.\s0 Please note that \s-1YAML\s0 has hardcoded limits on (simple) object key lengths that \s-1JSON\s0 doesn't have and also has different and incompatible unicode character escape syntax, so you should make sure that your hash keys are noticeably shorter than the 1024 \*(L"stream characters\*(R" \s-1YAML\s0 allows and that you do not have characters with codepoint values outside the Unicode \s-1BMP\s0 (basic multilingual page). \s-1YAML\s0 also does not allow \f(CW\*(C`\e/\*(C'\fR sequences in strings (which \s-1JSON::XS\s0 does not \fIcurrently\fR generate, but other \s-1JSON\s0 generators might). .PP There might be other incompatibilities that I am not aware of (or the \s-1YAML\s0 specification has been changed yet again \- it does so quite often). In general you should not try to generate \s-1YAML\s0 with a \s-1JSON\s0 generator or vice versa, or try to parse \s-1JSON\s0 with a \s-1YAML\s0 parser or vice versa: chances are high that you will run into severe interoperability problems when you least expect it. .IP "(*)" 4 I have been pressured multiple times by Brian Ingerson (one of the authors of the \s-1YAML\s0 specification) to remove this paragraph, despite him acknowledging that the actual incompatibilities exist. As I was personally bitten by this \*(L"\s-1JSON\s0 is \s-1YAML\*(R"\s0 lie, I refused and said I will continue to educate people about these issues, so others do not run into the same problem again and again. After this, Brian called me a (quote)\fIcomplete and worthless idiot\fR(unquote). .Sp In my opinion, instead of pressuring and insulting people who actually clarify issues with \s-1YAML\s0 and the wrong statements of some of its proponents, I would kindly suggest reading the \s-1JSON\s0 spec (which is not that difficult or long) and finally make \s-1YAML\s0 compatible to it, and educating users about the changes, instead of spreading lies about the real compatibility for many \fIyears\fR and trying to silence people who point out that it isn't true. .Sp Addendum/2009: the \s-1YAML 1.2\s0 spec is still incompatible with \s-1JSON,\s0 even though the incompatibilities have been documented (and are known to Brian) for many years and the spec makes explicit claims that \s-1YAML\s0 is a superset of \s-1JSON.\s0 It would be so easy to fix, but apparently, bullying people and corrupting userdata is so much easier. .SS "\s-1SPEED\s0" .IX Subsection "SPEED" It seems that \s-1JSON::XS\s0 is surprisingly fast, as shown in the following tables. They have been generated with the help of the \f(CW\*(C`eg/bench\*(C'\fR program in the \s-1JSON::XS\s0 distribution, to make it easy to compare on your own system. .PP First comes a comparison between various modules using a very short single-line \s-1JSON\s0 string (also available at ). .PP .Vb 3 \& {"method": "handleMessage", "params": ["user1", \& "we were just talking"], "id": null, "array":[1,11,234,\-5,1e5,1e7, \& 1, 0]} .Ve .PP It shows the number of encodes/decodes per second (\s-1JSON::XS\s0 uses the functional interface, while \s-1JSON::XS/2\s0 uses the \s-1OO\s0 interface with pretty-printing and hashkey sorting enabled, \s-1JSON::XS/3\s0 enables shrink. \s-1JSON::DWIW/DS\s0 uses the deserialise function, while \s-1JSON::DWIW::FJ\s0 uses the from_json method). Higher is better: .PP .Vb 11 \& module | encode | decode | \& \-\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-| \& JSON::DWIW/DS | 86302.551 | 102300.098 | \& JSON::DWIW/FJ | 86302.551 | 75983.768 | \& JSON::PP | 15827.562 | 6638.658 | \& JSON::Syck | 63358.066 | 47662.545 | \& JSON::XS | 511500.488 | 511500.488 | \& JSON::XS/2 | 291271.111 | 388361.481 | \& JSON::XS/3 | 361577.931 | 361577.931 | \& Storable | 66788.280 | 265462.278 | \& \-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-+ .Ve .PP That is, \s-1JSON::XS\s0 is almost six times faster than \s-1JSON::DWIW\s0 on encoding, about five times faster on decoding, and over thirty to seventy times faster than \s-1JSON\s0's pure perl implementation. It also compares favourably to Storable for small amounts of data. .PP Using a longer test string (roughly 18KB, generated from Yahoo! Locals search \s-1API\s0 (). .PP .Vb 11 \& module | encode | decode | \& \-\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-| \& JSON::DWIW/DS | 1647.927 | 2673.916 | \& JSON::DWIW/FJ | 1630.249 | 2596.128 | \& JSON::PP | 400.640 | 62.311 | \& JSON::Syck | 1481.040 | 1524.869 | \& JSON::XS | 20661.596 | 9541.183 | \& JSON::XS/2 | 10683.403 | 9416.938 | \& JSON::XS/3 | 20661.596 | 9400.054 | \& Storable | 19765.806 | 10000.725 | \& \-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-+ .Ve .PP Again, \s-1JSON::XS\s0 leads by far (except for Storable which non-surprisingly decodes a bit faster). .PP On large strings containing lots of high Unicode characters, some modules (such as \s-1JSON::PC\s0) seem to decode faster than \s-1JSON::XS,\s0 but the result will be broken due to missing (or wrong) Unicode handling. Others refuse to decode or encode properly, so it was impossible to prepare a fair comparison table for that case. .SH "SECURITY CONSIDERATIONS" .IX Header "SECURITY CONSIDERATIONS" When you are using \s-1JSON\s0 in a protocol, talking to untrusted potentially hostile creatures requires relatively few measures. .PP First of all, your \s-1JSON\s0 decoder should be secure, that is, should not have any buffer overflows. Obviously, this module should ensure that and I am trying hard on making that true, but you never know. .PP Second, you need to avoid resource-starving attacks. That means you should limit the size of \s-1JSON\s0 texts you accept, or make sure then when your resources run out, that's just fine (e.g. by using a separate process that can crash safely). The size of a \s-1JSON\s0 text in octets or characters is usually a good indication of the size of the resources required to decode it into a Perl structure. While \s-1JSON::XS\s0 can check the size of the \s-1JSON\s0 text, it might be too late when you already have it in memory, so you might want to check the size before you accept the string. .PP Third, \s-1JSON::XS\s0 recurses using the C stack when decoding objects and arrays. The C stack is a limited resource: for instance, on my amd64 machine with 8MB of stack size I can decode around 180k nested arrays but only 14k nested \s-1JSON\s0 objects (due to perl itself recursing deeply on croak to free the temporary). If that is exceeded, the program crashes. To be conservative, the default nesting limit is set to 512. If your process has a smaller stack, you should adjust this setting accordingly with the \&\f(CW\*(C`max_depth\*(C'\fR method. .PP Something else could bomb you, too, that I forgot to think of. In that case, you get to keep the pieces. I am always open for hints, though... .PP Also keep in mind that \s-1JSON::XS\s0 might leak contents of your Perl data structures in its error messages, so when you serialise sensitive information you might want to make sure that exceptions thrown by \s-1JSON::XS\s0 will not end up in front of untrusted eyes. .PP If you are using \s-1JSON::XS\s0 to return packets to consumption by JavaScript scripts in a browser you should have a look at to see whether you are vulnerable to some common attack vectors (which really are browser design bugs, but it is still you who will have to deal with it, as major browser developers care only for features, not about getting security right). .ie n .SS """\s-1OLD"" VS. ""NEW"" JSON\s0 (\s-1RFC4627 VS. RFC7159\s0)" .el .SS "``\s-1OLD'' VS. ``NEW'' JSON\s0 (\s-1RFC4627 VS. RFC7159\s0)" .IX Subsection "OLD VS. NEW JSON (RFC4627 VS. RFC7159)" \&\s-1JSON\s0 originally required \s-1JSON\s0 texts to represent an array or object \- scalar values were explicitly not allowed. This has changed, and versions of \s-1JSON::XS\s0 beginning with \f(CW4.0\fR reflect this by allowing scalar values by default. .PP One reason why one might not want this is that this removes a fundamental property of \s-1JSON\s0 texts, namely that they are self-delimited and self-contained, or in other words, you could take any number of \*(L"old\*(R" \&\s-1JSON\s0 texts and paste them together, and the result would be unambiguously parseable: .PP .Vb 1 \& [1,3]{"k":5}[][null] # four JSON texts, without doubt .Ve .PP By allowing scalars, this property is lost: in the following example, is this one \s-1JSON\s0 text (the number 12) or two \s-1JSON\s0 texts (the numbers 1 and 2): .PP .Vb 1 \& 12 # could be 12, or 1 and 2 .Ve .PP Another lost property of \*(L"old\*(R" \s-1JSON\s0 is that no lookahead is required to know the end of a \s-1JSON\s0 text, i.e. the \s-1JSON\s0 text definitely ended at the last \f(CW\*(C`]\*(C'\fR or \f(CW\*(C`}\*(C'\fR character, there was no need to read extra characters. .PP For example, a viable network protocol with \*(L"old\*(R" \s-1JSON\s0 was to simply exchange \s-1JSON\s0 texts without delimiter. For \*(L"new\*(R" \s-1JSON,\s0 you have to use a suitable delimiter (such as a newline) after every \s-1JSON\s0 text or ensure you never encode/decode scalar values. .PP Most protocols do work by only transferring arrays or objects, and the easiest way to avoid problems with the \*(L"new\*(R" \s-1JSON\s0 definition is to explicitly disallow scalar values in your encoder and decoder: .PP .Vb 1 \& $json_coder = JSON::XS\->new\->allow_nonref (0) .Ve .PP This is a somewhat unhappy situation, and the blame can fully be put on \&\s-1JSON\s0's inmventor, Douglas Crockford, who unilaterally changed the format in 2006 without consulting the \s-1IETF,\s0 forcing the \s-1IETF\s0 to either fork the format or go with it (as I was told, the \s-1IETF\s0 wasn't amused). .SH "RELATIONSHIP WITH I\-JSON" .IX Header "RELATIONSHIP WITH I-JSON" \&\s-1JSON\s0 is a somewhat sloppily-defined format \- it carries around obvious Javascript baggage, such as not really defining number range, probably because Javascript only has one type of numbers: \s-1IEEE 64\s0 bit floats (\*(L"binary64\*(R"). .PP For this reaosn, \s-1RFC7493\s0 defines \*(L"Internet \s-1JSON\*(R",\s0 which is a restricted subset of \s-1JSON\s0 that is supposedly more interoperable on the internet. .PP While \f(CW\*(C`JSON::XS\*(C'\fR does not offer specific support for I\-JSON, it of course accepts valid I\-JSON and by default implements some of the limitations of I\-JSON, such as parsing numbers as perl numbers, which are usually a superset of binary64 numbers. .PP To generate I\-JSON, follow these rules: .IP "\(bu" 4 always generate \s-1UTF\-8\s0 .Sp I\-JSON must be encoded in \s-1UTF\-8,\s0 the default for \f(CW\*(C`encode_json\*(C'\fR. .IP "\(bu" 4 numbers should be within \s-1IEEE 754\s0 binary64 range .Sp Basically all existing perl installations use binary64 to represent floating point numbers, so all you need to do is to avoid large integers. .IP "\(bu" 4 objects must not have duplicate keys .Sp This is trivially done, as \f(CW\*(C`JSON::XS\*(C'\fR does not allow duplicate keys. .IP "\(bu" 4 do not generate scalar \s-1JSON\s0 texts, use \f(CW\*(C`\->allow_nonref (0)\*(C'\fR .Sp I\-JSON strongly requests you to only encode arrays and objects into \s-1JSON.\s0 .IP "\(bu" 4 times should be strings in \s-1ISO 8601\s0 format .Sp There are a myriad of modules on \s-1CPAN\s0 dealing with \s-1ISO 8601\s0 \- search for \&\f(CW\*(C`ISO8601\*(C'\fR on \s-1CPAN\s0 and use one. .IP "\(bu" 4 encode binary data as base64 .Sp While it's tempting to just dump binary data as a string (and let \&\f(CW\*(C`JSON::XS\*(C'\fR do the escaping), for I\-JSON, it's \fIrecommended\fR to encode binary data as base64. .PP There are some other considerations \- read \s-1RFC7493\s0 for the details if interested. .SH "INTEROPERABILITY WITH OTHER MODULES" .IX Header "INTEROPERABILITY WITH OTHER MODULES" \&\f(CW\*(C`JSON::XS\*(C'\fR uses the Types::Serialiser module to provide boolean constants. That means that the \s-1JSON\s0 true and false values will be comaptible to true and false values of other modules that do the same, such as \s-1JSON::PP\s0 and \s-1CBOR::XS\s0. .SH "INTEROPERABILITY WITH OTHER JSON DECODERS" .IX Header "INTEROPERABILITY WITH OTHER JSON DECODERS" As long as you only serialise data that can be directly expressed in \s-1JSON,\s0 \&\f(CW\*(C`JSON::XS\*(C'\fR is incapable of generating invalid \s-1JSON\s0 output (modulo bugs, but \f(CW\*(C`JSON::XS\*(C'\fR has found more bugs in the official \s-1JSON\s0 testsuite (1) than the official \s-1JSON\s0 testsuite has found in \f(CW\*(C`JSON::XS\*(C'\fR (0)). .PP When you have trouble decoding \s-1JSON\s0 generated by this module using other decoders, then it is very likely that you have an encoding mismatch or the other decoder is broken. .PP When decoding, \f(CW\*(C`JSON::XS\*(C'\fR is strict by default and will likely catch all errors. There are currently two settings that change this: \f(CW\*(C`relaxed\*(C'\fR makes \f(CW\*(C`JSON::XS\*(C'\fR accept (but not generate) some non-standard extensions, and \f(CW\*(C`allow_tags\*(C'\fR will allow you to encode and decode Perl objects, at the cost of not outputting valid \s-1JSON\s0 anymore. .SS "\s-1TAGGED VALUE SYNTAX AND STANDARD JSON EN/DECODERS\s0" .IX Subsection "TAGGED VALUE SYNTAX AND STANDARD JSON EN/DECODERS" When you use \f(CW\*(C`allow_tags\*(C'\fR to use the extended (and also nonstandard and invalid) \s-1JSON\s0 syntax for serialised objects, and you still want to decode the generated When you want to serialise objects, you can run a regex to replace the tagged syntax by standard \s-1JSON\s0 arrays (it only works for \&\*(L"normal\*(R" package names without comma, newlines or single colons). First, the readable Perl version: .PP .Vb 2 \& # if your FREEZE methods return no values, you need this replace first: \& $json =~ s/\e( \es* (" (?: [^\e\e":,]+|\e\e.|::)* ") \es* \e) \es* \e[\es*\e]/[$1]/gx; \& \& # this works for non\-empty constructor arg lists: \& $json =~ s/\e( \es* (" (?: [^\e\e":,]+|\e\e.|::)* ") \es* \e) \es* \e[/[$1,/gx; .Ve .PP And here is a less readable version that is easy to adapt to other languages: .PP .Vb 1 \& $json =~ s/\e(\es*("([^\e\e":,]+|\e\e.|::)*")\es*\e)\es*\e[/[$1,/g; .Ve .PP Here is an ECMAScript version (same regex): .PP .Vb 1 \& json = json.replace (/\e(\es*("([^\e\e":,]+|\e\e.|::)*")\es*\e)\es*\e[/g, "[$1,"); .Ve .PP Since this syntax converts to standard \s-1JSON\s0 arrays, it might be hard to distinguish serialised objects from normal arrays. You can prepend a \&\*(L"magic number\*(R" as first array element to reduce chances of a collision: .PP .Vb 1 \& $json =~ s/\e(\es*("([^\e\e":,]+|\e\e.|::)*")\es*\e)\es*\e[/["XU1peReLzT4ggEllLanBYq4G9VzliwKF",$1,/g; .Ve .PP And after decoding the \s-1JSON\s0 text, you could walk the data structure looking for arrays with a first element of \&\f(CW\*(C`XU1peReLzT4ggEllLanBYq4G9VzliwKF\*(C'\fR. .PP The same approach can be used to create the tagged format with another encoder. First, you create an array with the magic string as first member, the classname as second, and constructor arguments last, encode it as part of your \s-1JSON\s0 structure, and then: .PP .Vb 1 \& $json =~ s/\e[\es*"XU1peReLzT4ggEllLanBYq4G9VzliwKF"\es*,\es*("([^\e\e":,]+|\e\e.|::)*")\es*,/($1)[/g; .Ve .PP Again, this has some limitations \- the magic string must not be encoded with character escapes, and the constructor arguments must be non-empty. .SH "(I\-)THREADS" .IX Header "(I-)THREADS" This module is \fInot\fR guaranteed to be ithread (or \s-1MULTIPLICITY\-\s0) safe and there are no plans to change this. Note that perl's builtin so-called threads/ithreads are officially deprecated and should not be used. .SH "THE PERILS OF SETLOCALE" .IX Header "THE PERILS OF SETLOCALE" Sometimes people avoid the Perl locale support and directly call the system's setlocale function with \f(CW\*(C`LC_ALL\*(C'\fR. .PP This breaks both perl and modules such as \s-1JSON::XS,\s0 as stringification of numbers no longer works correctly (e.g. \f(CW\*(C`$x = 0.1; print "$x"+1\*(C'\fR might print \f(CW1\fR, and \s-1JSON::XS\s0 might output illegal \s-1JSON\s0 as \s-1JSON::XS\s0 relies on perl to stringify numbers). .PP The solution is simple: don't call \f(CW\*(C`setlocale\*(C'\fR, or use it for only those categories you need, such as \f(CW\*(C`LC_MESSAGES\*(C'\fR or \f(CW\*(C`LC_CTYPE\*(C'\fR. .PP If you need \f(CW\*(C`LC_NUMERIC\*(C'\fR, you should enable it only around the code that actually needs it (avoiding stringification of numbers), and restore it afterwards. .SH "SOME HISTORY" .IX Header "SOME HISTORY" At the time this module was created there already were a number of \s-1JSON\s0 modules available on \s-1CPAN,\s0 so what was the reason to write yet another \&\s-1JSON\s0 module? While it seems there are many \s-1JSON\s0 modules, none of them correctly handled all corner cases, and in most cases their maintainers are unresponsive, gone missing, or not listening to bug reports for other reasons. .PP Beginning with version 2.0 of the \s-1JSON\s0 module, when both \s-1JSON\s0 and \&\s-1JSON::XS\s0 are installed, then \s-1JSON\s0 will fall back on \s-1JSON::XS\s0 (this can be overridden) with no overhead due to emulation (by inheriting constructor and methods). If \s-1JSON::XS\s0 is not available, it will fall back to the compatible \s-1JSON::PP\s0 module as backend, so using \s-1JSON\s0 instead of \s-1JSON::XS\s0 gives you a portable \s-1JSON API\s0 that can be fast when you need it and doesn't require a C compiler when that is a problem. .PP Somewhere around version 3, this module was forked into \&\f(CW\*(C`Cpanel::JSON::XS\*(C'\fR, because its maintainer had serious trouble understanding \s-1JSON\s0 and insisted on a fork with many bugs \*(L"fixed\*(R" that weren't actually bugs, while spreading \s-1FUD\s0 about this module without actually giving any details on his accusations. You be the judge, but in my personal opinion, if you want quality, you will stay away from dangerous forks like that. .SH "BUGS" .IX Header "BUGS" While the goal of this module is to be correct, that unfortunately does not mean it's bug-free, only that I think its design is bug-free. If you keep reporting bugs they will be fixed swiftly, though. .PP Please refrain from using rt.cpan.org or any other bug reporting service. I put the contact address into my modules for a reason. .SH "SEE ALSO" .IX Header "SEE ALSO" The \fIjson_xs\fR command line utility for quick experiments. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 2 \& Marc Lehmann \& http://home.schmorp.de/ .Ve man/man3/DBD::Gofer::Transport::stream.3pm000044400000011720152462503210014036 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Transport::stream 3" .TH DBD::Gofer::Transport::stream 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Transport::stream \- DBD::Gofer transport for stdio streaming .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& DBI\->connect(\*(Aqdbi:Gofer:transport=stream;url=ssh:username@host.example.com;dsn=dbi:...\*(Aq,...) .Ve .PP or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: .PP .Vb 1 \& export DBI_AUTOPROXY=\*(Aqdbi:Gofer:transport=stream;url=ssh:username@host.example.com\*(Aq .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Without the \f(CW\*(C`url=\*(C'\fR parameter it launches a subprocess as .PP .Vb 1 \& perl \-MDBI::Gofer::Transport::stream \-e run_stdio_hex .Ve .PP and feeds requests into it and reads responses from it. But that's not very useful. .PP With a \f(CW\*(C`url=ssh:username@host.example.com\*(C'\fR parameter it uses ssh to launch the subprocess on a remote system. That's much more useful! .PP It gives you secure remote access to \s-1DBI\s0 databases on any system you can login to. Using ssh also gives you optional compression and many other features (see the ssh manual for how to configure that and many other options via ~/.ssh/config file). .PP The actual command invoked is something like: .PP .Vb 1 \& ssh \-xq ssh:username@host.example.com bash \-c $setup $run .Ve .PP where \f(CW$run\fR is the command shown above, and \f(CW$command\fR is .PP .Vb 1 \& . .bash_profile 2>/dev/null || . .bash_login 2>/dev/null || . .profile 2>/dev/null; exec "$@" .Ve .PP which is trying (in a limited and fairly unportable way) to setup the environment (\s-1PATH, PERL5LIB\s0 etc) as it would be if you had logged in to that system. .PP The "\f(CW\*(C`perl\*(C'\fR" used in the command will default to the value of $^X when not using ssh. On most systems that's the full path to the perl that's currently executing. .SH "PERSISTENCE" .IX Header "PERSISTENCE" Currently gofer stream connections persist (remain connected) after all database handles have been disconnected. This makes later connections in the same process very fast. .PP Currently up to 5 different gofer stream connections (based on url) can persist. If more than 5 are in the cache when a new connection is made then the cache is cleared before adding the new connection. Simple but effective. .SH "TO DO" .IX Header "TO DO" Document go_perl attribute .PP Automatically reconnect (within reason) if there's a transport error. .PP Decide on default for persistent connection \- on or off? limits? ttl? .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. .SH "SEE ALSO" .IX Header "SEE ALSO" DBD::Gofer::Transport::Base .PP DBD::Gofer man/man3/DBI::Gofer::Serializer::Storable.3pm000044400000005624152462503210014446 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Serializer::Storable 3" .TH DBI::Gofer::Serializer::Storable 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Serializer::Storable \- Gofer serialization using Storable .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $serializer = DBI::Gofer::Serializer::Storable\->new(); \& \& $string = $serializer\->serialize( $data ); \& ($string, $deserializer_class) = $serializer\->serialize( $data ); \& \& $data = $serializer\->deserialize( $string ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Uses \fBStorable::nfreeze()\fR to serialize and \fBStorable::thaw()\fR to deserialize. .PP The \fBserialize()\fR method sets local \f(CW$Storable::forgive_me\fR = 1; so it doesn't croak if it encounters any data types that can't be serialized, such as code refs. .PP See also DBI::Gofer::Serializer::Base. man/man3/Net::SSL.3pm000044400000015553152462503210010101 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Net::SSL 3" .TH Net::SSL 3 "2014-04-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::SSL \- support for Secure Sockets Layer .SH "METHODS" .IX Header "METHODS" .IP "new" 4 .IX Item "new" Creates a new \f(CW\*(C`Net::SSL\*(C'\fR object. .IP "configure" 4 .IX Item "configure" Configures a \f(CW\*(C`Net::SSL\*(C'\fR socket for operation. .IP "configure_certs" 4 .IX Item "configure_certs" Sets up a certificate file to use for communicating with on the socket. .IP "connect" 4 .IX Item "connect" .PD 0 .IP "die_with_error" 4 .IX Item "die_with_error" .IP "get_cipher" 4 .IX Item "get_cipher" .IP "get_lwp_object" 4 .IX Item "get_lwp_object" .PD Walks up the caller stack and looks for something blessed into the \f(CW\*(C`LWP::UserAgent\*(C'\fR namespace and returns it. Vaguely deprecated. .IP "get_peer_certificate" 4 .IX Item "get_peer_certificate" Gets the peer certificate from the underlying \f(CW\*(C`Crypt::SSLeay::Conn\*(C'\fR object. .IP "get_peer_verify" 4 .IX Item "get_peer_verify" .PD 0 .IP "get_shared_ciphers" 4 .IX Item "get_shared_ciphers" .IP "getchunk" 4 .IX Item "getchunk" .PD Attempts to read up to 32KiB of data from the socket. Returns \&\f(CW\*(C`undef\*(C'\fR if nothing was read, otherwise returns the data as a scalar. .IP "pending" 4 .IX Item "pending" Provides access to OpenSSL's \f(CW\*(C`pending\*(C'\fR attribute on the \s-1SSL\s0 connection object. .IP "getline" 4 .IX Item "getline" Reads one character at a time until a newline is encountered, and returns the line, including the newline. Grossly inefficient. .IP "print" 4 .IX Item "print" Concatenates the input parameters and writes them to the socket. Does not honour \f(CW$,\fR nor \f(CW$/\fR. Returns the number of bytes written. .IP "printf" 4 .IX Item "printf" Performs a \f(CW\*(C`sprintf\*(C'\fR of the input parameters (thus, the first parameter must be the format), and writes the result to the socket. Returns the number of bytes written. .IP "proxy" 4 .IX Item "proxy" Returns the hostname of an https proxy server, as specified by the \&\f(CW\*(C`HTTPS_PROXY\*(C'\fR environment variable. .IP "proxy_connect_helper" 4 .IX Item "proxy_connect_helper" Helps set up a connection through a proxy. .IP "read" 4 .IX Item "read" Performs a read on the socket and returns the result. .IP "ssl_context" 4 .IX Item "ssl_context" .PD 0 .IP "sysread" 4 .IX Item "sysread" .PD Is an alias of \f(CW\*(C`read\*(C'\fR. .IP "timeout" 4 .IX Item "timeout" Returns the timeout value of the socket as defined by the implementing class or 60 seconds by default. .IP "blocking" 4 .IX Item "blocking" Returns a boolean indicating whether the underlying socket is in blocking mode. By default, Net::SSL sockets are in blocking mode. .Sp .Vb 1 \& $sock\->blocking(0); # set to non\-blocking mode .Ve .Sp This method simply calls the underlying \f(CW\*(C`blocking\*(C'\fR method of the IO::Socket object. .IP "write" 4 .IX Item "write" Writes the parameters passed in (thus, a list) to the socket. Returns the number of bytes written. .IP "syswrite" 4 .IX Item "syswrite" Is an alias of \f(CW\*(C`write\*(C'\fR. .IP "accept" 4 .IX Item "accept" Not yet implemented. Will die if called. .IP "getc" 4 .IX Item "getc" Not yet implemented. Will die if called. .IP "getlines" 4 .IX Item "getlines" Not yet implemented. Will die if called. .IP "ungetc" 4 .IX Item "ungetc" Not yet implemented. Will die if called. .IP "send_useragent_to_proxy" 4 .IX Item "send_useragent_to_proxy" By default (as of version 2.80 of \f(CW\*(C`Net::SSL\*(C'\fR in the 0.54 distribution of Crypt::SSLeay), the user agent string is no longer sent to the proxy (but will continue to be sent to the remote host). .Sp The previous behaviour was of marginal benefit, and could cause fatal errors in certain scenarios (see \s-1CPAN\s0 bug #4759) and so no longer happens by default. .Sp To reinstate the old behaviour, call \f(CW\*(C`Net::SSL::send_useragent_to_proxy\*(C'\fR with a true value (usually 1). .SH "DIAGNOSTICS" .IX Header "DIAGNOSTICS" .Vb 1 \& "no port given for proxy server " .Ve .PP A proxy was specified for configuring a socket, but no port number was given. Ensure that the proxy is specified as a host:port pair, such as \f(CW\*(C`proxy.example.com:8086\*(C'\fR. .PP .Vb 1 \& "configure certs failed: ; " \& \& "proxy connect failed: ; " \& \& "Connect failed: ; " .Ve .PP During \fBconnect()\fR. .SS "\s-1SEE ALSO\s0" .IX Subsection "SEE ALSO" .IP "IO::Socket::INET" 4 .IX Item "IO::Socket::INET" \&\f(CW\*(C`Net::SSL\*(C'\fR is implemented by subclassing \f(CW\*(C`IO::Socket::INET\*(C'\fR, hence methods not specifically overridden are defined by that package. .IP "Net::SSLeay" 4 .IX Item "Net::SSLeay" A package that provides a Perl-level interface to the \f(CW\*(C`openssl\*(C'\fR secure sockets layer library. man/man3/DBI::Profile.3pm000044400000072041152462503210010703 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Profile 3" .TH DBI::Profile 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Profile \- Performance profiling and benchmarking for the DBI .SH "SYNOPSIS" .IX Header "SYNOPSIS" The easiest way to enable \s-1DBI\s0 profiling is to set the \s-1DBI_PROFILE\s0 environment variable to 2 and then run your code as usual: .PP .Vb 1 \& DBI_PROFILE=2 prog.pl .Ve .PP This will profile your program and then output a textual summary grouped by query when the program exits. You can also enable profiling by setting the Profile attribute of any \s-1DBI\s0 handle: .PP .Vb 1 \& $dbh\->{Profile} = 2; .Ve .PP Then the summary will be printed when the handle is destroyed. .PP Many other values apart from are possible \- see \*(L"\s-1ENABLING A PROFILE\*(R"\s0 below. .SH "DESCRIPTION" .IX Header "DESCRIPTION" The DBI::Profile module provides a simple interface to collect and report performance and benchmarking data from the \s-1DBI.\s0 .PP For a more elaborate interface, suitable for larger programs, see DBI::ProfileDumper and dbiprof. For Apache/mod_perl applications see DBI::ProfileDumper::Apache. .SH "OVERVIEW" .IX Header "OVERVIEW" Performance data collection for the \s-1DBI\s0 is built around several concepts which are important to understand clearly. .IP "Method Dispatch" 4 .IX Item "Method Dispatch" Every method call on a \s-1DBI\s0 handle passes through a single 'dispatch' function which manages all the common aspects of \s-1DBI\s0 method calls, such as handling the RaiseError attribute. .IP "Data Collection" 4 .IX Item "Data Collection" If profiling is enabled for a handle then the dispatch code takes a high-resolution timestamp soon after it is entered. Then, after calling the appropriate method and just before returning, it takes another high-resolution timestamp and calls a function to record the information. That function is passed the two timestamps plus the \s-1DBI\s0 handle and the name of the method that was called. That data about a single \s-1DBI\s0 method call is called a \fIprofile sample\fR. .IP "Data Filtering" 4 .IX Item "Data Filtering" If the method call was invoked by the \s-1DBI\s0 or by a driver then the call is ignored for profiling because the time spent will be accounted for by the original 'outermost' call for your code. .Sp For example, the calls that the \fBselectrow_arrayref()\fR method makes to \fBprepare()\fR and \fBexecute()\fR etc. are not counted individually because the time spent in those methods is going to be allocated to the \fBselectrow_arrayref()\fR method when it returns. If this was not done then it would be very easy to double count time spent inside the \s-1DBI.\s0 .IP "Data Storage Tree" 4 .IX Item "Data Storage Tree" The profile data is accumulated as 'leaves on a tree'. The 'path' through the branches of the tree to a particular leaf is determined dynamically for each sample. This is a key feature of \s-1DBI\s0 profiling. .Sp For each profiled method call the \s-1DBI\s0 walks along the Path and uses each value in the Path to step into and grow the Data tree. .Sp For example, if the Path is .Sp .Vb 1 \& [ \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq ] .Ve .Sp then the new profile sample data will be \fImerged\fR into the tree at .Sp .Vb 1 \& $h\->{Profile}\->{Data}\->{foo}\->{bar}\->{baz} .Ve .Sp But it's not very useful to merge all the call data into one leaf node (except to get an overall 'time spent inside the \s-1DBI\s0' total). It's more common to want the Path to include dynamic values such as the current statement text and/or the name of the method called to show what the time spent inside the \s-1DBI\s0 was for. .Sp The Path can contain some 'magic cookie' values that are automatically replaced by corresponding dynamic values when they're used. These magic cookies always start with a punctuation character. .Sp For example a value of '\f(CW\*(C`!MethodName\*(C'\fR' in the Path causes the corresponding entry in the Data to be the name of the method that was called. For example, if the Path was: .Sp .Vb 1 \& [ \*(Aqfoo\*(Aq, \*(Aq!MethodName\*(Aq, \*(Aqbar\*(Aq ] .Ve .Sp and the \fBselectall_arrayref()\fR method was called, then the profile sample data for that call will be merged into the tree at: .Sp .Vb 1 \& $h\->{Profile}\->{Data}\->{foo}\->{selectall_arrayref}\->{bar} .Ve .IP "Profile Data" 4 .IX Item "Profile Data" Profile data is stored at the 'leaves' of the tree as references to an array of numeric values. For example: .Sp .Vb 9 \& [ \& 106, # 0: count of samples at this node \& 0.0312958955764771, # 1: total duration \& 0.000490069389343262, # 2: first duration \& 0.000176072120666504, # 3: shortest duration \& 0.00140702724456787, # 4: longest duration \& 1023115819.83019, # 5: time of first sample \& 1023115819.86576, # 6: time of last sample \& ] .Ve .Sp After the first sample, later samples always update elements 0, 1, and 6, and may update 3 or 4 depending on the duration of the sampled call. .SH "ENABLING A PROFILE" .IX Header "ENABLING A PROFILE" Profiling is enabled for a handle by assigning to the Profile attribute. For example: .PP .Vb 1 \& $h\->{Profile} = DBI::Profile\->new(); .Ve .PP The Profile attribute holds a blessed reference to a hash object that contains the profile data and attributes relating to it. .PP The class the Profile object is blessed into is expected to provide at least a \s-1DESTROY\s0 method which will dump the profile data to the \s-1DBI\s0 trace file handle (\s-1STDERR\s0 by default). .PP All these examples have the same effect as each other: .PP .Vb 5 \& $h\->{Profile} = 0; \& $h\->{Profile} = "/DBI::Profile"; \& $h\->{Profile} = DBI::Profile\->new(); \& $h\->{Profile} = {}; \& $h\->{Profile} = { Path => [] }; .Ve .PP Similarly, these examples have the same effect as each other: .PP .Vb 4 \& $h\->{Profile} = 6; \& $h\->{Profile} = "6/DBI::Profile"; \& $h\->{Profile} = "!Statement:!MethodName/DBI::Profile"; \& $h\->{Profile} = { Path => [ \*(Aq!Statement\*(Aq, \*(Aq!MethodName\*(Aq ] }; .Ve .PP If a non-blessed hash reference is given then the DBI::Profile module is automatically \f(CW\*(C`require\*(C'\fR'd and the reference is blessed into that class. .PP If a string is given then it is processed like this: .PP .Vb 1 \& ($path, $module, $args) = split /\e//, $string, 3 \& \& @path = split /:/, $path \& @args = split /:/, $args \& \& eval "require $module" if $module \& $module ||= "DBI::Profile" \& \& $module\->new( Path => \e@Path, @args ) .Ve .PP So the first value is used to select the Path to be used (see below). The second value, if present, is used as the name of a module which will be loaded and it's \f(CW\*(C`new\*(C'\fR method called. If not present it defaults to DBI::Profile. Any other values are passed as arguments to the \f(CW\*(C`new\*(C'\fR method. For example: "\f(CW\*(C`2/DBIx::OtherProfile/Foo:42\*(C'\fR". .PP Numbers can be used as a shorthand way to enable common Path values. The simplest way to explain how the values are interpreted is to show the code: .PP .Vb 5 \& push @Path, "DBI" if $path_elem & 0x01; \& push @Path, "!Statement" if $path_elem & 0x02; \& push @Path, "!MethodName" if $path_elem & 0x04; \& push @Path, "!MethodClass" if $path_elem & 0x08; \& push @Path, "!Caller2" if $path_elem & 0x10; .Ve .PP So \*(L"2\*(R" is the same as \*(L"!Statement\*(R" and \*(L"6\*(R" (2+4) is the same as \&\*(L"!Statement:!Method\*(R". Those are the two most commonly used values. Using a negative number will reverse the path. Thus \*(L"\-6\*(R" will group by method name then statement. .PP The splitting and parsing of string values assigned to the Profile attribute may seem a little odd, but there's a good reason for it. Remember that attributes can be embedded in the Data Source Name string which can be passed in to a script as a parameter. For example: .PP .Vb 2 \& dbi:DriverName(Profile=>2):dbname \& dbi:DriverName(Profile=>{Username}:!Statement/MyProfiler/Foo:42):dbname .Ve .PP And also, if the \f(CW\*(C`DBI_PROFILE\*(C'\fR environment variable is set then The \s-1DBI\s0 arranges for every driver handle to share the same profile object. When perl exits a single profile summary will be generated that reflects (as nearly as practical) the total use of the \s-1DBI\s0 by the application. .SH "THE PROFILE OBJECT" .IX Header "THE PROFILE OBJECT" The \s-1DBI\s0 core expects the Profile attribute value to be a hash reference and if the following values don't exist it will create them as needed: .SS "Data" .IX Subsection "Data" A reference to a hash containing the collected profile data. .SS "Path" .IX Subsection "Path" The Path value is a reference to an array. Each element controls the value to use at the corresponding level of the profile Data tree. .PP If the value of Path is anything other than an array reference, it is treated as if it was: .PP .Vb 1 \& [ \*(Aq!Statement\*(Aq ] .Ve .PP The elements of Path array can be one of the following types: .PP \fISpecial Constant\fR .IX Subsection "Special Constant" .PP \&\fB!Statement\fR .PP Use the current Statement text. Typically that's the value of the Statement attribute for the handle the method was called with. Some methods, like \&\fBcommit()\fR and \fBrollback()\fR, are unrelated to a particular statement. For those methods !Statement records an empty string. .PP For statement handles this is always simply the string that was given to \fBprepare()\fR when the handle was created. For database handles this is the statement that was last prepared or executed on that database handle. That can lead to a little 'fuzzyness' because, for example, calls to the \fBquote()\fR method to build a new statement will typically be associated with the previous statement. In practice this isn't a significant issue and the dynamic Path mechanism can be used to setup your own rules. .PP \&\fB!MethodName\fR .PP Use the name of the \s-1DBI\s0 method that the profile sample relates to. .PP \&\fB!MethodClass\fR .PP Use the fully qualified name of the \s-1DBI\s0 method, including the package, that the profile sample relates to. This shows you where the method was implemented. For example: .PP .Vb 4 \& \*(AqDBD::_::db::selectrow_arrayref\*(Aq => \& 0.022902s \& \*(AqDBD::mysql::db::selectrow_arrayref\*(Aq => \& 2.244521s / 99 = 0.022445s avg (first 0.022813s, min 0.022051s, max 0.028932s) .Ve .PP The \*(L"DBD::_::db::selectrow_arrayref\*(R" shows that the driver has inherited the selectrow_arrayref method provided by the \s-1DBI.\s0 .PP But you'll note that there is only one call to DBD::_::db::selectrow_arrayref but another 99 to DBD::mysql::db::selectrow_arrayref. Currently the first call doesn't record the true location. That may change. .PP \&\fB!Caller\fR .PP Use a string showing the filename and line number of the code calling the method. .PP \&\fB!Caller2\fR .PP Use a string showing the filename and line number of the code calling the method, as for !Caller, but also include filename and line number of the code that called that. Calls from \s-1DBI::\s0 and \s-1DBD::\s0 packages are skipped. .PP \&\fB!File\fR .PP Same as !Caller above except that only the filename is included, not the line number. .PP \&\fB!File2\fR .PP Same as !Caller2 above except that only the filenames are included, not the line number. .PP \&\fB!Time\fR .PP Use the current value of \fBtime()\fR. Rarely used. See the more useful \f(CW\*(C`!Time~N\*(C'\fR below. .PP \&\fB!Time~N\fR .PP Where \f(CW\*(C`N\*(C'\fR is an integer. Use the current value of \fBtime()\fR but with reduced precision. The value used is determined in this way: .PP .Vb 1 \& int( time() / N ) * N .Ve .PP This is a useful way to segregate a profile into time slots. For example: .PP .Vb 1 \& [ \*(Aq!Time~60\*(Aq, \*(Aq!Statement\*(Aq ] .Ve .PP \fICode Reference\fR .IX Subsection "Code Reference" .PP The subroutine is passed the handle it was called on and the \s-1DBI\s0 method name. The current Statement is in \f(CW$_\fR. The statement string should not be modified, so most subs start with \f(CW\*(C`local $_ = $_;\*(C'\fR. .PP The list of values it returns is used at that point in the Profile Path. Any undefined values are treated as the string "\f(CW\*(C`undef\*(C'\fR". .PP The sub can 'veto' (reject) a profile sample by including a reference to undef (\f(CW\*(C`\eundef\*(C'\fR) in the returned list. That can be useful when you want to only profile statements that match a certain pattern, or only profile certain methods. .PP \fISubroutine Specifier\fR .IX Subsection "Subroutine Specifier" .PP A Path element that begins with '\f(CW\*(C`&\*(C'\fR' is treated as the name of a subroutine in the DBI::ProfileSubs namespace and replaced with the corresponding code reference. .PP Currently this only works when the Path is specified by the \f(CW\*(C`DBI_PROFILE\*(C'\fR environment variable. .PP Also, currently, the only subroutine in the DBI::ProfileSubs namespace is \&\f(CW\*(Aq&norm_std_n3\*(Aq\fR. That's a very handy subroutine when profiling code that doesn't use placeholders. See DBI::ProfileSubs for more information. .PP \fIAttribute Specifier\fR .IX Subsection "Attribute Specifier" .PP A string enclosed in braces, such as '\f(CW\*(C`{Username}\*(C'\fR', specifies that the current value of the corresponding database handle attribute should be used at that point in the Path. .PP \fIReference to a Scalar\fR .IX Subsection "Reference to a Scalar" .PP Specifies that the current value of the referenced scalar be used at that point in the Path. This provides an efficient way to get 'contextual' values into your profile. .PP \fIOther Values\fR .IX Subsection "Other Values" .PP Any other values are stringified and used literally. .PP (References, and values that begin with punctuation characters are reserved.) .SH "REPORTING" .IX Header "REPORTING" .SS "Report Format" .IX Subsection "Report Format" The current accumulated profile data can be formatted and output using .PP .Vb 1 \& print $h\->{Profile}\->format; .Ve .PP To discard the profile data and start collecting fresh data you can do: .PP .Vb 1 \& $h\->{Profile}\->{Data} = undef; .Ve .PP The default results format looks like this: .PP .Vb 5 \& DBI::Profile: 0.001015s 42.7% (5 calls) programname @ YYYY\-MM\-DD HH:MM:SS \& \*(Aq\*(Aq => \& 0.000024s / 2 = 0.000012s avg (first 0.000015s, min 0.000009s, max 0.000015s) \& \*(AqSELECT mode,size,name FROM table\*(Aq => \& 0.000991s / 3 = 0.000330s avg (first 0.000678s, min 0.000009s, max 0.000678s) .Ve .PP Which shows the total time spent inside the \s-1DBI,\s0 with a count of the total number of method calls and the name of the script being run, then a formatted version of the profile data tree. .PP If the results are being formatted when the perl process is exiting (which is usually the case when the \s-1DBI_PROFILE\s0 environment variable is used) then the percentage of time the process spent inside the \&\s-1DBI\s0 is also shown. If the process is not exiting then the percentage is calculated using the time between the first and last call to the \s-1DBI.\s0 .PP In the example above the paths in the tree are only one level deep and use the Statement text as the value (that's the default behaviour). .PP The merged profile data at the 'leaves' of the tree are presented as total time spent, count, average time spent (which is simply total time divided by the count), then the time spent on the first call, the time spent on the fastest call, and finally the time spent on the slowest call. .PP The 'avg', 'first', 'min' and 'max' times are not particularly useful when the profile data path only contains the statement text. Here's an extract of a more detailed example using both statement text and method name in the path: .PP .Vb 5 \& \*(AqSELECT mode,size,name FROM table\*(Aq => \& \*(AqFETCH\*(Aq => \& 0.000076s \& \*(Aqfetchrow_hashref\*(Aq => \& 0.036203s / 108 = 0.000335s avg (first 0.000490s, min 0.000152s, max 0.002786s) .Ve .PP Here you can see the 'avg', 'first', 'min' and 'max' for the 108 calls to \fBfetchrow_hashref()\fR become rather more interesting. Also the data for \s-1FETCH\s0 just shows a time value because it was only called once. .PP Currently the profile data is output sorted by branch names. That may change in a later version so the leaf nodes are sorted by total time per leaf node. .SS "Report Destination" .IX Subsection "Report Destination" The default method of reporting is for the \s-1DESTROY\s0 method of the Profile object to format the results and write them using: .PP .Vb 1 \& DBI\->trace_msg($results, 0); # see $ON_DESTROY_DUMP below .Ve .PP to write them to the \s-1DBI\s0 \fBtrace()\fR filehandle (which defaults to \&\s-1STDERR\s0). To direct the \s-1DBI\s0 trace filehandle to write to a file without enabling tracing the \fBtrace()\fR method can be called with a trace level of 0. For example: .PP .Vb 1 \& DBI\->trace(0, $filename); .Ve .PP The same effect can be achieved without changing the code by setting the \f(CW\*(C`DBI_TRACE\*(C'\fR environment variable to \f(CW\*(C`0=filename\*(C'\fR. .PP The \f(CW$DBI::Profile::ON_DESTROY_DUMP\fR variable holds a code ref that's called to perform the output of the formatted results. The default value is: .PP .Vb 1 \& $ON_DESTROY_DUMP = sub { DBI\->trace_msg($results, 0) }; .Ve .PP Apart from making it easy to send the dump elsewhere, it can also be useful as a simple way to disable dumping results. .SH "CHILD HANDLES" .IX Header "CHILD HANDLES" Child handles inherit a reference to the Profile attribute value of their parent. So if profiling is enabled for a database handle then by default the statement handles created from it all contribute to the same merged profile data tree. .SH "PROFILE OBJECT METHODS" .IX Header "PROFILE OBJECT METHODS" .SS "format" .IX Subsection "format" See \*(L"\s-1REPORTING\*(R"\s0. .SS "as_node_path_list" .IX Subsection "as_node_path_list" .Vb 2 \& @ary = $dbh\->{Profile}\->as_node_path_list(); \& @ary = $dbh\->{Profile}\->as_node_path_list($node, $path); .Ve .PP Returns the collected data ($dbh\->{Profile}{Data}) restructured into a list of array refs, one for each leaf node in the Data tree. This 'flat' structure is often much simpler for applications to work with. .PP The first element of each array ref is a reference to the leaf node. The remaining elements are the 'path' through the data tree to that node. .PP For example, given a data tree like this: .PP .Vb 3 \& {key1a}{key2a}[node1] \& {key1a}{key2b}[node2] \& {key1b}{key2a}{key3a}[node3] .Ve .PP The \fBas_node_path_list()\fR method will return this list: .PP .Vb 3 \& [ [node1], \*(Aqkey1a\*(Aq, \*(Aqkey2a\*(Aq ] \& [ [node2], \*(Aqkey1a\*(Aq, \*(Aqkey2b\*(Aq ] \& [ [node3], \*(Aqkey1b\*(Aq, \*(Aqkey2a\*(Aq, \*(Aqkey3a\*(Aq ] .Ve .PP The nodes are ordered by key, depth-first. .PP The \f(CW$node\fR argument can be used to focus on a sub-tree. If not specified it defaults to \f(CW$dbh\fR\->{Profile}{Data}. .PP The \f(CW$path\fR argument can be used to specify a list of path elements that will be added to each element of the returned list. If not specified it defaults to a ref to an empty array. .SS "as_text" .IX Subsection "as_text" .Vb 8 \& @txt = $dbh\->{Profile}\->as_text(); \& $txt = $dbh\->{Profile}\->as_text({ \& node => undef, \& path => [], \& separator => " > ", \& format => \*(Aq%1$s: %11$fs / %10$d = %2$fs avg (first %12$fs, min %13$fs, max %14$fs)\*(Aq."\en"; \& sortsub => sub { ... }, \& ); .Ve .PP Returns the collected data ($dbh\->{Profile}{Data}) reformatted into a list of formatted strings. In scalar context the list is returned as a single concatenated string. .PP A hashref can be used to pass in arguments, the default values are shown in the example above. .PP The \f(CW\*(C`node\*(C'\fR and arguments are passed to \fBas_node_path_list()\fR. .PP The \f(CW\*(C`separator\*(C'\fR argument is used to join the elements of the path for each leaf node. .PP The \f(CW\*(C`sortsub\*(C'\fR argument is used to pass in a ref to a sub that will order the list. The subroutine will be passed a reference to the array returned by \&\fBas_node_path_list()\fR and should sort the contents of the array in place. The return value from the sub is ignored. For example, to sort the nodes by the second level key you could use: .PP .Vb 1 \& sortsub => sub { my $ary=shift; @$ary = sort { $a\->[2] cmp $b\->[2] } @$ary } .Ve .PP The \f(CW\*(C`format\*(C'\fR argument is a \f(CW\*(C`sprintf\*(C'\fR format string that specifies the format to use for each leaf node. It uses the explicit format parameter index mechanism to specify which of the arguments should appear where in the string. The arguments to sprintf are: .PP .Vb 10 \& 1: path to node, joined with the separator \& 2: average duration (total duration/count) \& (3 thru 9 are currently unused) \& 10: count \& 11: total duration \& 12: first duration \& 13: smallest duration \& 14: largest duration \& 15: time of first call \& 16: time of first call .Ve .SH "CUSTOM DATA MANIPULATION" .IX Header "CUSTOM DATA MANIPULATION" Recall that \f(CW\*(C`$h\->{Profile}\->{Data}\*(C'\fR is a reference to the collected data. Either to a 'leaf' array (when the Path is empty, i.e., \s-1DBI_PROFILE\s0 env var is 1), or a reference to hash containing values that are either further hash references or leaf array references. .PP Sometimes it's useful to be able to summarise some or all of the collected data. The \fBdbi_profile_merge_nodes()\fR function can be used to merge leaf node values. .SS "dbi_profile_merge_nodes" .IX Subsection "dbi_profile_merge_nodes" .Vb 1 \& use DBI qw(dbi_profile_merge_nodes); \& \& $time_in_dbi = dbi_profile_merge_nodes(my $totals=[], @$leaves); .Ve .PP Merges profile data node. Given a reference to a destination array, and zero or more references to profile data, merges the profile data into the destination array. For example: .PP .Vb 5 \& $time_in_dbi = dbi_profile_merge_nodes( \& my $totals=[], \& [ 10, 0.51, 0.11, 0.01, 0.22, 1023110000, 1023110010 ], \& [ 15, 0.42, 0.12, 0.02, 0.23, 1023110005, 1023110009 ], \& ); .Ve .PP \&\f(CW$totals\fR will then contain .PP .Vb 1 \& [ 25, 0.93, 0.11, 0.01, 0.23, 1023110000, 1023110010 ] .Ve .PP and \f(CW$time_in_dbi\fR will be 0.93; .PP The second argument need not be just leaf nodes. If given a reference to a hash then the hash is recursively searched for leaf nodes and all those found are merged. .PP For example, to get the time spent 'inside' the \s-1DBI\s0 during an http request, your logging code run at the end of the request (i.e. mod_perl LogHandler) could use: .PP .Vb 5 \& my $time_in_dbi = 0; \& if (my $Profile = $dbh\->{Profile}) { # if DBI profiling is enabled \& $time_in_dbi = dbi_profile_merge_nodes(my $total=[], $Profile\->{Data}); \& $Profile\->{Data} = {}; # reset the profile data \& } .Ve .PP If profiling has been enabled then \f(CW$time_in_dbi\fR will hold the time spent inside the \s-1DBI\s0 for that handle (and any other handles that share the same profile data) since the last request. .PP Prior to \s-1DBI 1.56\s0 the \fBdbi_profile_merge_nodes()\fR function was called \fBdbi_profile_merge()\fR. That name still exists as an alias. .SH "CUSTOM DATA COLLECTION" .IX Header "CUSTOM DATA COLLECTION" .SS "Using The Path Attribute" .IX Subsection "Using The Path Attribute" .Vb 6 \& XXX example to be added later using a selectall_arrayref call \& XXX nested inside a fetch loop where the first column of the \& XXX outer loop is bound to the profile Path using \& XXX bind_column(1, \e${ $dbh\->{Profile}\->{Path}\->[0] }) \& XXX so you end up with separate profiles for each loop \& XXX (patches welcome to add this to the docs :) .Ve .SS "Adding Your Own Samples" .IX Subsection "Adding Your Own Samples" The \fBdbi_profile()\fR function can be used to add extra sample data into the profile data tree. For example: .PP .Vb 2 \& use DBI; \& use DBI::Profile (dbi_profile dbi_time); \& \& my $t1 = dbi_time(); # floating point high\-resolution time \& \& ... execute code you want to profile here ... \& \& my $t2 = dbi_time(); \& dbi_profile($h, $statement, $method, $t1, $t2); .Ve .PP The \f(CW$h\fR parameter is the handle the extra profile sample should be associated with. The \f(CW$statement\fR parameter is the string to use where the Path specifies !Statement. If \f(CW$statement\fR is undef then \f(CW$h\fR\->{Statement} will be used. Similarly \f(CW$method\fR is the string to use if the Path specifies !MethodName. There is no default value for \f(CW$method\fR. .PP The \f(CW$h\fR\->{Profile}{Path} attribute is processed by \fBdbi_profile()\fR in the usual way. .PP The \f(CW$h\fR parameter is usually a \s-1DBI\s0 handle but it can also be a reference to a hash, in which case the \fBdbi_profile()\fR acts on each defined value in the hash. This is an efficient way to update multiple profiles with a single sample, and is used by the DashProfiler module. .SH "SUBCLASSING" .IX Header "SUBCLASSING" Alternate profile modules must subclass DBI::Profile to help ensure they work with future versions of the \s-1DBI.\s0 .SH "CAVEATS" .IX Header "CAVEATS" Applications which generate many different statement strings (typically because they don't use placeholders) and profile with !Statement in the Path (the default) will consume memory in the Profile Data structure for each statement. Use a code ref in the Path to return an edited (simplified) form of the statement. .PP If a method throws an exception itself (not via RaiseError) then it won't be counted in the profile. .PP If a HandleError subroutine throws an exception (rather than returning 0 and letting RaiseError do it) then the method call won't be counted in the profile. .PP Time spent in \s-1DESTROY\s0 is added to the profile of the parent handle. .PP Time spent in \s-1DBI\-\s0>*() methods is not counted. The time spent in the driver connect method, \f(CW$drh\fR\->\fBconnect()\fR, when it's called by \&\s-1DBI\-\s0>connect is counted if the \s-1DBI_PROFILE\s0 environment variable is set. .PP Time spent fetching tied variables, \f(CW$DBI::errstr\fR, is counted. .PP Time spent in \s-1FETCH\s0 for \f(CW$h\fR\->{Profile} is not counted, so getting the profile data doesn't alter it. .PP DBI::PurePerl does not support profiling (though it could in theory). .PP For asynchronous queries, time spent while the query is running on the backend is not counted. .PP A few platforms don't support the \fBgettimeofday()\fR high resolution time function used by the \s-1DBI\s0 (and available via the \fBdbi_time()\fR function). In which case you'll get integer resolution time which is mostly useless. .PP On Windows platforms the \fBdbi_time()\fR function is limited to millisecond resolution. Which isn't sufficiently fine for our needs, but still much better than integer resolution. This limited resolution means that fast method calls will often register as taking 0 time. And timings in general will have much more 'jitter' depending on where within the 'current millisecond' the start and end timing was taken. .PP This documentation could be more clear. Probably needs to be reordered to start with several examples and build from there. Trying to explain the concepts first seems painful and to lead to just as many forward references. (Patches welcome!) man/man3/DBD::File::Developers.3pm000044400000064220152462503210012372 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::File::Developers 3" .TH DBD::File::Developers 3 "2013-04-04" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::File::Developers \- Developers documentation for DBD::File .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& package DBD::myDriver; \& \& use base qw( DBD::File ); \& \& sub driver \& { \& ... \& my $drh = $proto\->SUPER::driver ($attr); \& ... \& return $drh\->{class}; \& } \& \& sub CLONE { ... } \& \& package DBD::myDriver::dr; \& \& @ISA = qw( DBD::File::dr ); \& \& sub data_sources { ... } \& ... \& \& package DBD::myDriver::db; \& \& @ISA = qw( DBD::File::db ); \& \& sub init_valid_attributes { ... } \& sub init_default_attributes { ... } \& sub set_versions { ... } \& sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } \& sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } \& sub get_myd_versions { ... } \& \& package DBD::myDriver::st; \& \& @ISA = qw( DBD::File::st ); \& \& sub FETCH { ... } \& sub STORE { ... } \& \& package DBD::myDriver::Statement; \& \& @ISA = qw( DBD::File::Statement ); \& \& package DBD::myDriver::Table; \& \& @ISA = qw( DBD::File::Table ); \& \& my %reset_on_modify = ( \& myd_abc => "myd_foo", \& myd_mno => "myd_bar", \& ); \& _\|_PACKAGE_\|_\->register_reset_on_modify (\e%reset_on_modify); \& my %compat_map = ( \& abc => \*(Aqfoo_abc\*(Aq, \& xyz => \*(Aqfoo_xyz\*(Aq, \& ); \& _\|_PACKAGE_\|_\->register_compat_map (\e%compat_map); \& \& sub bootstrap_table_meta { ... } \& sub init_table_meta { ... } \& sub table_meta_attr_changed { ... } \& sub open_data { ... } \& \& sub fetch_row { ... } \& sub push_row { ... } \& sub push_names { ... } \& \& # optimize the SQL engine by add one or more of \& sub update_current_row { ... } \& # or \& sub update_specific_row { ... } \& # or \& sub update_one_row { ... } \& # or \& sub insert_new_row { ... } \& # or \& sub delete_current_row { ... } \& # or \& sub delete_one_row { ... } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document describes how \s-1DBD\s0 developers can write DBD::File based \s-1DBI\s0 drivers. It supplements \s-1DBI::DBD\s0 and DBI::DBD::SqlEngine::Developers, which you should read first. .SH "CLASSES" .IX Header "CLASSES" Each \s-1DBI\s0 driver must provide a package global \f(CW\*(C`driver\*(C'\fR method and three \&\s-1DBI\s0 related classes: .IP "DBD::File::dr" 4 .IX Item "DBD::File::dr" Driver package, contains the methods \s-1DBI\s0 calls indirectly via \s-1DBI\s0 interface: .Sp .Vb 1 \& DBI\->connect (\*(AqDBI:DBM:\*(Aq, undef, undef, {}) \& \& # invokes \& package DBD::DBM::dr; \& @DBD::DBM::dr::ISA = qw( DBD::File::dr ); \& \& sub connect ($$;$$$) \& { \& ... \& } .Ve .Sp Similar for \f(CW\*(C`data_sources\*(C'\fR and \f(CW\*(C`disconnect_all\*(C'\fR. .Sp Pure Perl \s-1DBI\s0 drivers derived from DBD::File do not usually need to override any of the methods provided through the DBD::XXX::dr package however if you need additional initialization in the connect method you may need to. .IP "DBD::File::db" 4 .IX Item "DBD::File::db" Contains the methods which are called through \s-1DBI\s0 database handles (\f(CW$dbh\fR). e.g., .Sp .Vb 3 \& $sth = $dbh\->prepare ("select * from foo"); \& # returns the f_encoding setting for table foo \& $dbh\->csv_get_meta ("foo", "f_encoding"); .Ve .Sp DBD::File provides the typical methods required here. Developers who write \s-1DBI\s0 drivers based on DBD::File need to override the methods \f(CW\*(C`set_versions\*(C'\fR and \f(CW\*(C`init_valid_attributes\*(C'\fR. .IP "DBD::File::st" 4 .IX Item "DBD::File::st" Contains the methods to deal with prepared statement handles. e.g., .Sp .Vb 1 \& $sth\->execute () or die $sth\->errstr; .Ve .SS "DBD::File" .IX Subsection "DBD::File" This is the main package containing the routines to initialize DBD::File based \s-1DBI\s0 drivers. Primarily the \f(CW\*(C`DBD::File::driver\*(C'\fR method is invoked, either directly from \s-1DBI\s0 when the driver is initialized or from the derived class. .PP .Vb 1 \& package DBD::DBM; \& \& use base qw( DBD::File ); \& \& sub driver \& { \& my ($class, $attr) = @_; \& ... \& my $drh = $class\->SUPER::driver ($attr); \& ... \& return $drh; \& } .Ve .PP It is not necessary to implement your own driver method as long as additional initialization (e.g. installing more private driver methods) is not required. You do not need to call \f(CW\*(C`setup_driver\*(C'\fR as DBD::File takes care of it. .SS "DBD::File::dr" .IX Subsection "DBD::File::dr" The driver package contains the methods \s-1DBI\s0 calls indirectly via the \s-1DBI\s0 interface (see \*(L"\s-1DBI\s0 Class Methods\*(R" in \s-1DBI\s0). .PP DBD::File based \s-1DBI\s0 drivers usually do not need to implement anything here, it is enough to do the basic initialization: .PP .Vb 1 \& package DBD:XXX::dr; \& \& @DBD::XXX::dr::ISA = qw (DBD::File::dr); \& $DBD::XXX::dr::imp_data_size = 0; \& $DBD::XXX::dr::data_sources_attr = undef; \& $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; .Ve .SS "DBD::File::db" .IX Subsection "DBD::File::db" This package defines the database methods, which are called via the \s-1DBI\s0 database handle \f(CW$dbh\fR. .PP Methods provided by DBD::File: .IP "ping" 4 .IX Item "ping" Simply returns the content of the \f(CW\*(C`Active\*(C'\fR attribute. Override when your driver needs more complicated actions here. .IP "prepare" 4 .IX Item "prepare" Prepares a new \s-1SQL\s0 statement to execute. Returns a statement handle, \&\f(CW$sth\fR \- instance of the DBD:XXX::st. It is neither required nor recommended to override this method. .IP "\s-1FETCH\s0" 4 .IX Item "FETCH" Fetches an attribute of a \s-1DBI\s0 database object. Private handle attributes must have a prefix (this is mandatory). If a requested attribute is detected as a private attribute without a valid prefix, the driver prefix (written as \f(CW$drv_prefix\fR) is added. .Sp The driver prefix is extracted from the attribute name and verified against \&\f(CW\*(C`$dbh\->{$drv_prefix . "valid_attrs"}\*(C'\fR (when it exists). If the requested attribute value is not listed as a valid attribute, this method croaks. If the attribute is valid and readonly (listed in \f(CW\*(C`$dbh\->{ $drv_prefix . "readonly_attrs" }\*(C'\fR when it exists), a real copy of the attribute value is returned. So it's not possible to modify \&\f(CW\*(C`f_valid_attrs\*(C'\fR from outside of DBD::File::db or a derived class. .IP "\s-1STORE\s0" 4 .IX Item "STORE" Stores a database private attribute. Private handle attributes must have a prefix (this is mandatory). If a requested attribute is detected as a private attribute without a valid prefix, the driver prefix (written as \&\f(CW$drv_prefix\fR) is added. If the database handle has an attribute \&\f(CW\*(C`${drv_prefix}_valid_attrs\*(C'\fR \- for attribute names which are not listed in that hash, this method croaks. If the database handle has an attribute \&\f(CW\*(C`${drv_prefix}_readonly_attrs\*(C'\fR, only attributes which are not listed there can be stored (once they are initialized). Trying to overwrite such an immutable attribute forces this method to croak. .Sp An example of a valid attributes list can be found in \&\f(CW\*(C`DBD::File::db::init_valid_attributes\*(C'\fR. .IP "set_versions" 4 .IX Item "set_versions" This method sets the attribute \f(CW\*(C`f_version\*(C'\fR with the version of DBD::File. .Sp This method is called at the begin of the \f(CW\*(C`connect ()\*(C'\fR phase. .Sp When overriding this method, do not forget to invoke the superior one. .IP "init_valid_attributes" 4 .IX Item "init_valid_attributes" This method is called after the database handle is instantiated as the first attribute initialization. .Sp \&\f(CW\*(C`DBD::File::db::init_valid_attributes\*(C'\fR initializes the attributes \&\f(CW\*(C`f_valid_attrs\*(C'\fR and \f(CW\*(C`f_readonly_attrs\*(C'\fR. .Sp When overriding this method, do not forget to invoke the superior one, preferably before doing anything else. Compatibility table attribute access must be initialized here to allow DBD::File to instantiate the map tie: .Sp .Vb 6 \& # for DBD::CSV \& $dbh\->{csv_meta} = "csv_tables"; \& # for DBD::DBM \& $dbh\->{dbm_meta} = "dbm_tables"; \& # for DBD::AnyData \& $dbh\->{ad_meta} = "ad_tables"; .Ve .IP "init_default_attributes" 4 .IX Item "init_default_attributes" This method is called after the database handle is instantiated to initialize the default attributes. .Sp \&\f(CW\*(C`DBD::File::db::init_default_attributes\*(C'\fR initializes the attributes \&\f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_meta\*(C'\fR, \f(CW\*(C`f_meta_map\*(C'\fR, \f(CW\*(C`f_version\*(C'\fR. .Sp When the derived implementor class provides the attribute to validate attributes (e.g. \f(CW\*(C`$dbh\->{dbm_valid_attrs} = {...};\*(C'\fR) or the attribute containing the immutable attributes (e.g. \&\f(CW\*(C`$dbh\->{dbm_readonly_attrs} = {...};\*(C'\fR), the attributes \&\f(CW\*(C`drv_valid_attrs\*(C'\fR, \f(CW\*(C`drv_readonly_attrs\*(C'\fR, \f(CW\*(C`drv_version\*(C'\fR and \f(CW\*(C`drv_meta\*(C'\fR are added (when available) to the list of valid and immutable attributes (where \f(CW\*(C`drv_\*(C'\fR is interpreted as the driver prefix). .Sp If \f(CW\*(C`drv_meta\*(C'\fR is set, an attribute with the name in \f(CW\*(C`drv_meta\*(C'\fR is initialized providing restricted read/write access to the meta data of the tables using \f(CW\*(C`DBD::File::TieTables\*(C'\fR in the first (table) level and \&\f(CW\*(C`DBD::File::TieMeta\*(C'\fR for the meta attribute level. \f(CW\*(C`DBD::File::TieTables\*(C'\fR uses \f(CW\*(C`DBD::DRV::Table::get_table_meta\*(C'\fR to initialize the second level tied hash on \s-1FETCH/STORE.\s0 The \f(CW\*(C`DBD::File::TieMeta\*(C'\fR class uses \&\f(CW\*(C`DBD::DRV::Table::get_table_meta_attr\*(C'\fR to \s-1FETCH\s0 attribute values and \&\f(CW\*(C`DBD::DRV::Table::set_table_meta_attr\*(C'\fR to \s-1STORE\s0 attribute values. This allows it to map meta attributes for compatibility reasons. .IP "get_single_table_meta" 4 .IX Item "get_single_table_meta" .PD 0 .IP "get_file_meta" 4 .IX Item "get_file_meta" .PD Retrieve an attribute from a table's meta information. The method signature is \f(CW\*(C`get_file_meta ($dbh, $table, $attr)\*(C'\fR. This method is called by the injected db handle method \f(CW\*(C`${drv_prefix}get_meta\*(C'\fR. .Sp While get_file_meta allows \f(CW$table\fR or \f(CW$attr\fR to be a list of tables or attributes to retrieve, get_single_table_meta allows only one table name and only one attribute name. A table name of \f(CW\*(Aq.\*(Aq\fR (single dot) is interpreted as the default table and this will retrieve the appropriate attribute globally from the dbh. This has the same restrictions as \&\f(CW\*(C`$dbh\->{$attrib}\*(C'\fR. .Sp get_file_meta allows \f(CW\*(Aq+\*(Aq\fR and \f(CW\*(Aq*\*(Aq\fR as wildcards for table names and \&\f(CW$table\fR being a regular expression matching against the table names (evaluated without the default table). The table name \f(CW\*(Aq*\*(Aq\fR is \&\fIall currently known tables, including the default one\fR. The table name \f(CW\*(Aq+\*(Aq\fR is \fIall table names which conform to \&\s-1ANSI\s0 file name restrictions\fR (/^[_A\-Za\-z0\-9]+$/). .Sp The table meta information is retrieved using the get_table_meta and get_table_meta_attr methods of the table class of the implementation. .IP "set_single_table_meta" 4 .IX Item "set_single_table_meta" .PD 0 .IP "set_file_meta" 4 .IX Item "set_file_meta" .PD Sets an attribute in a table's meta information. The method signature is \&\f(CW\*(C`set_file_meta ($dbh, $table, $attr, $value)\*(C'\fR. This method is called by the injected db handle method \f(CW\*(C`${drv_prefix}set_meta\*(C'\fR. .Sp While set_file_meta allows \f(CW$table\fR to be a list of tables and \f(CW$attr\fR to be a hash of several attributes to set, set_single_table_meta allows only one table name and only one attribute name/value pair. .Sp The wildcard characters for the table name are the same as for get_file_meta. .Sp The table meta information is updated using the get_table_meta and set_table_meta_attr methods of the table class of the implementation. .IP "clear_file_meta" 4 .IX Item "clear_file_meta" Clears all meta information cached about a table. The method signature is \&\f(CW\*(C`clear_file_meta ($dbh, $table)\*(C'\fR. This method is called by the injected db handle method \f(CW\*(C`${drv_prefix}clear_meta\*(C'\fR. .SS "DBD::File::st" .IX Subsection "DBD::File::st" Contains the methods to deal with prepared statement handles: .IP "\s-1FETCH\s0" 4 .IX Item "FETCH" Fetches statement handle attributes. Supported attributes (for full overview see \*(L"Statement Handle Attributes\*(R" in \s-1DBI\s0) are \f(CW\*(C`NAME\*(C'\fR, \f(CW\*(C`TYPE\*(C'\fR, \f(CW\*(C`PRECISION\*(C'\fR and \f(CW\*(C`NULLABLE\*(C'\fR in case that SQL::Statement is used as \s-1SQL\s0 execution engine and a statement is successful prepared. When SQL::Statement has additional information about a table, those information are returned. Otherwise, the same defaults as in DBI::DBD::SqlEngine are used. .Sp This method usually requires extending in a derived implementation. See \s-1DBD::CSV\s0 or \s-1DBD::DBM\s0 for some example. .SS "DBD::File::TableSource::FileSystem" .IX Subsection "DBD::File::TableSource::FileSystem" Provides data sources and table information on database driver and database handle level. .PP .Vb 1 \& package DBD::File::TableSource::FileSystem; \& \& sub data_sources ($;$) \& { \& my ($class, $drh, $attrs) = @_; \& ... \& } \& \& sub avail_tables \& { \& my ($class, $drh) = @_; \& ... \& } .Ve .PP The \f(CW\*(C`data_sources\*(C'\fR method is called when the user invokes any of the following: .PP .Vb 2 \& @ary = DBI\->data_sources ($driver); \& @ary = DBI\->data_sources ($driver, \e%attr); \& \& @ary = $dbh\->data_sources (); \& @ary = $dbh\->data_sources (\e%attr); .Ve .PP The \f(CW\*(C`avail_tables\*(C'\fR method is called when the user invokes any of the following: .PP .Vb 1 \& @names = $dbh\->tables ($catalog, $schema, $table, $type); \& \& $sth = $dbh\->table_info ($catalog, $schema, $table, $type); \& $sth = $dbh\->table_info ($catalog, $schema, $table, $type, \e%attr); \& \& $dbh\->func ("list_tables"); .Ve .PP Every time where an \f(CW\*(C`\e%attr\*(C'\fR argument can be specified, this \f(CW\*(C`\e%attr\*(C'\fR object's \f(CW\*(C`sql_table_source\*(C'\fR attribute is preferred over the \f(CW$dbh\fR attribute or the driver default. .SS "DBD::File::DataSource::Stream" .IX Subsection "DBD::File::DataSource::Stream" .Vb 1 \& package DBD::File::DataSource::Stream; \& \& @DBD::File::DataSource::Stream::ISA = \*(AqDBI::DBD::SqlEngine::DataSource\*(Aq; \& \& sub complete_table_name \& { \& my ($self, $meta, $file, $respect_case) = @_; \& ... \& } .Ve .PP Clears all meta attributes identifying a file: \f(CW\*(C`f_fqfn\*(C'\fR, \f(CW\*(C`f_fqbn\*(C'\fR and \&\f(CW\*(C`f_fqln\*(C'\fR. The table name is set according to \f(CW$respect_case\fR and \&\f(CW\*(C`$meta\->{sql_identifier_case}\*(C'\fR (\s-1SQL_IC_LOWER, SQL_IC_UPPER\s0). .PP .Vb 1 \& package DBD::File::DataSource::Stream; \& \& sub apply_encoding \& { \& my ($self, $meta, $fn) = @_; \& ... \& } .Ve .PP Applies the encoding from \fImeta information\fR (\f(CW\*(C`$meta\->{f_encoding}\*(C'\fR) to the file handled opened in \f(CW\*(C`open_data\*(C'\fR. .PP .Vb 1 \& package DBD::File::DataSource::Stream; \& \& sub open_data \& { \& my ($self, $meta, $attrs, $flags) = @_; \& ... \& } .Ve .PP Opens (\f(CW\*(C`dup (2)\*(C'\fR) the file handle provided in \f(CW\*(C`$meta\->{f_file}\*(C'\fR. .PP .Vb 1 \& package DBD::File::DataSource::Stream; \& \& sub can_flock { ... } .Ve .PP Returns whether \f(CW\*(C`flock (2)\*(C'\fR is available or not (avoids retesting in subclasses). .SS "DBD::File::DataSource::File" .IX Subsection "DBD::File::DataSource::File" .Vb 1 \& package DBD::File::DataSource::File; \& \& sub complete_table_name ($$;$) \& { \& my ($self, $meta, $table, $respect_case) = @_; \& ... \& } .Ve .PP The method \f(CW\*(C`complete_table_name\*(C'\fR tries to map a filename to the associated table name. It is called with a partially filled meta structure for the resulting table containing at least the following attributes: \&\f(CW\*(C`f_ext\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_lockfile\*(C'\fR and \f(CW\*(C`sql_identifier_case\*(C'\fR. .PP If a file/table map can be found then this method sets the \f(CW\*(C`f_fqfn\*(C'\fR, \f(CW\*(C`f_fqbn\*(C'\fR, \f(CW\*(C`f_fqln\*(C'\fR and \f(CW\*(C`table_name\*(C'\fR attributes in the meta structure. If a map cannot be found the table name will be undef. .PP .Vb 1 \& package DBD::File::DataSource::File; \& \& sub open_data ($) \& { \& my ($self, $meta, $attrs, $flags) = @_; \& ... \& } .Ve .PP Depending on the attributes set in the table's meta data, the following steps are performed. Unless \f(CW\*(C`f_dontopen\*(C'\fR is set to a true value, \f(CW\*(C`f_fqfn\*(C'\fR must contain the full qualified file name for the table to work on (file2table ensures this). The encoding in \&\f(CW\*(C`f_encoding\*(C'\fR is applied if set and the file is opened. If \&\f(CW\*(C` (full qualified lock name) is set, this file is opened, too. Depending on the value in \f(CW\*(C`f_lock\*(C'\fR, the appropriate lock is set on the opened data file or lock file. .SS "DBD::File::Statement" .IX Subsection "DBD::File::Statement" Derives from DBI::SQL::Nano::Statement to provide following method: .IP "open_table" 4 .IX Item "open_table" Implements the open_table method required by SQL::Statement and DBI::SQL::Nano. All the work for opening the file(s) belonging to the table is handled and parametrized in DBD::File::Table. Unless you intend to add anything to the following implementation, an empty DBD::XXX::Statement package satisfies DBD::File. .Sp .Vb 3 \& sub open_table ($$$$$) \& { \& my ($self, $data, $table, $createMode, $lockMode) = @_; \& \& my $class = ref $self; \& $class =~ s/::Statement/::Table/; \& \& my $flags = { \& createMode => $createMode, \& lockMode => $lockMode, \& }; \& $self\->{command} eq "DROP" and $flags\->{dropMode} = 1; \& \& return $class\->new ($data, { table => $table }, $flags); \& } # open_table .Ve .SS "DBD::File::Table" .IX Subsection "DBD::File::Table" Derives from DBI::SQL::Nano::Table and provides physical file access for the table data which are stored in the files. .IP "bootstrap_table_meta" 4 .IX Item "bootstrap_table_meta" Initializes a table meta structure. Can be safely overridden in a derived class, as long as the \f(CW\*(C`SUPER\*(C'\fR method is called at the end of the overridden method. .Sp It copies the following attributes from the database into the table meta data \&\f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_ext\*(C'\fR, \f(CW\*(C`f_encoding\*(C'\fR, \f(CW\*(C`f_lock\*(C'\fR, \f(CW\*(C`f_schema\*(C'\fR and \f(CW\*(C`f_lockfile\*(C'\fR and makes them sticky to the table. .Sp This method should be called before you attempt to map between file name and table name to ensure the correct directory, extension etc. are used. .IP "init_table_meta" 4 .IX Item "init_table_meta" Initializes more attributes of the table meta data \- usually more expensive ones (e.g. those which require class instantiations) \- when the file name and the table name could mapped. .IP "get_table_meta" 4 .IX Item "get_table_meta" Returns the table meta data. If there are none for the required table, a new one is initialized. When it fails, nothing is returned. On success, the name of the table and the meta data structure is returned. .IP "get_table_meta_attr" 4 .IX Item "get_table_meta_attr" Returns a single attribute from the table meta data. If the attribute name appears in \f(CW%compat_map\fR, the attribute name is updated from there. .IP "set_table_meta_attr" 4 .IX Item "set_table_meta_attr" Sets a single attribute in the table meta data. If the attribute name appears in \f(CW%compat_map\fR, the attribute name is updated from there. .IP "table_meta_attr_changed" 4 .IX Item "table_meta_attr_changed" Called when an attribute of the meta data is modified. .Sp If the modified attribute requires to reset a calculated attribute, the calculated attribute is reset (deleted from meta data structure) and the \fIinitialized\fR flag is removed, too. The decision is made based on \&\f(CW%register_reset_on_modify\fR. .IP "register_reset_on_modify" 4 .IX Item "register_reset_on_modify" Allows \f(CW\*(C`set_table_meta_attr\*(C'\fR to reset meta attributes when special attributes are modified. For DBD::File, modifying one of \f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \&\f(CW\*(C`f_ext\*(C'\fR or \f(CW\*(C`f_lockfile\*(C'\fR will reset \f(CW\*(C`f_fqfn\*(C'\fR. \s-1DBD::DBM\s0 extends the list for \f(CW\*(C`dbm_type\*(C'\fR and \f(CW\*(C`dbm_mldbm\*(C'\fR to reset the value of \f(CW\*(C`dbm_tietype\*(C'\fR. .Sp If your \s-1DBD\s0 has calculated values in the meta data area, then call \&\f(CW\*(C`register_reset_on_modify\*(C'\fR: .Sp .Vb 2 \& my %reset_on_modify = (xxx_foo => "xxx_bar"); \& _\|_PACKAGE_\|_\->register_reset_on_modify (\e%reset_on_modify); .Ve .IP "register_compat_map" 4 .IX Item "register_compat_map" Allows \f(CW\*(C`get_table_meta_attr\*(C'\fR and \f(CW\*(C`set_table_meta_attr\*(C'\fR to update the attribute name to the current favored one: .Sp .Vb 3 \& # from DBD::DBM \& my %compat_map = (dbm_ext => "f_ext"); \& _\|_PACKAGE_\|_\->register_compat_map (\e%compat_map); .Ve .IP "open_file" 4 .IX Item "open_file" Called to open the table's data file. .Sp Depending on the attributes set in the table's meta data, the following steps are performed. Unless \f(CW\*(C`f_dontopen\*(C'\fR is set to a true value, \f(CW\*(C`f_fqfn\*(C'\fR must contain the full qualified file name for the table to work on (file2table ensures this). The encoding in \&\f(CW\*(C`f_encoding\*(C'\fR is applied if set and the file is opened. If \&\f(CW\*(C` (full qualified lock name) is set, this file is opened, too. Depending on the value in \f(CW\*(C`f_lock\*(C'\fR, the appropriate lock is set on the opened data file or lock file. .Sp After this is done, a derived class might add more steps in an overridden \&\f(CW\*(C`open_file\*(C'\fR method. .IP "new" 4 .IX Item "new" Instantiates the table. This is done in 3 steps: .Sp .Vb 3 \& 1. get the table meta data \& 2. open the data file \& 3. bless the table data structure using inherited constructor new .Ve .Sp It is not recommended to override the constructor of the table class. Find a reasonable place to add you extensions in one of the above four methods. .IP "drop" 4 .IX Item "drop" Implements the abstract table method for the \f(CW\*(C`DROP\*(C'\fR command. Discards table meta data after all files belonging to the table are closed and unlinked. .Sp Overriding this method might be reasonable in very rare cases. .IP "seek" 4 .IX Item "seek" Implements the abstract table method used when accessing the table from the engine. \f(CW\*(C`seek\*(C'\fR is called every time the engine uses dumb algorithms for iterating over the table content. .IP "truncate" 4 .IX Item "truncate" Implements the abstract table method used when dumb table algorithms for \f(CW\*(C`UPDATE\*(C'\fR or \f(CW\*(C`DELETE\*(C'\fR need to truncate the table storage after the last written row. .PP You should consult the documentation of \f(CW\*(C`SQL::Eval::Table\*(C'\fR (see SQL::Eval) to get more information about the abstract methods of the table's base class you have to override and a description of the table meta information expected by the \s-1SQL\s0 engines. .SH "AUTHOR" .IX Header "AUTHOR" The module DBD::File is currently maintained by .PP H.Merijn Brand < h.m.brand at xs4all.nl > and Jens Rehsack < rehsack at googlemail.com > .PP The original author is Jochen Wiedmann. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2010\-2013 by H.Merijn Brand & Jens Rehsack .PP All rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. man/man3/Expect.3pm000044400000165501152462503210010034 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Expect 3" .TH Expect 3 "2017-05-18" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Expect \- automate interactions with command line programs that expose a text terminal interface. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Expect; \& \& # create an Expect object by spawning another process \& my $exp = Expect\->spawn($command, @params) \& or die "Cannot spawn $command: $!\en"; \& \& # or by using an already opened filehandle (e.g. from Net::Telnet) \& my $exp = Expect\->exp_init(\e*FILEHANDLE); \& \& # if you prefer the OO mindset: \& my $exp = Expect\->new; \& $exp\->raw_pty(1); \& $exp\->spawn($command, @parameters) \& or die "Cannot spawn $command: $!\en"; \& \& # send some string there: \& $exp\->send("string\en"); \& \& # or, for the filehandle mindset: \& print $exp "string\en"; \& \& # then do some pattern matching with either the simple interface \& $patidx = $exp\->expect($timeout, @match_patterns); \& \& # or multi\-match on several spawned commands with callbacks, \& # just like the Tcl version \& $exp\->expect($timeout, \& [ qr/regex1/ => sub { my $exp = shift; \& $exp\->send("response\en"); \& exp_continue; } ], \& [ "regexp2" , \e&callback, @cbparms ], \& ); \& \& # if no longer needed, do a soft_close to nicely shut down the command \& $exp\->soft_close(); \& \& # or be less patient with \& $exp\->hard_close(); .Ve .PP Expect.pm is built to either spawn a process or take an existing filehandle and interact with it such that normally interactive tasks can be done without operator assistance. This concept makes more sense if you are already familiar with the versatile Tcl version of Expect. The public functions that make up Expect.pm are: .PP .Vb 10 \& Expect\->new() \& Expect::interconnect(@objects_to_be_read_from) \& Expect::test_handles($timeout, @objects_to_test) \& Expect::version($version_requested | undef); \& $object\->spawn(@command) \& $object\->clear_accum() \& $object\->set_accum($value) \& $object\->debug($debug_level) \& $object\->exp_internal(0 | 1) \& $object\->notransfer(0 | 1) \& $object\->raw_pty(0 | 1) \& $object\->stty(@stty_modes) # See the IO::Stty docs \& $object\->slave() \& $object\->before(); \& $object\->match(); \& $object\->after(); \& $object\->matchlist(); \& $object\->match_number(); \& $object\->error(); \& $object\->command(); \& $object\->exitstatus(); \& $object\->pty_handle(); \& $object\->do_soft_close(); \& $object\->restart_timeout_upon_receive(0 | 1); \& $object\->interact($other_object, $escape_sequence) \& $object\->log_group(0 | 1 | undef) \& $object\->log_user(0 | 1 | undef) \& $object\->log_file("filename" | $filehandle | \e&coderef | undef) \& $object\->manual_stty(0 | 1 | undef) \& $object\->match_max($max_buffersize or undef) \& $object\->pid(); \& $object\->send_slow($delay, @strings_to_send) \& $object\->set_group(@listen_group_objects | undef) \& $object\->set_seq($sequence,\e&function,\e@parameters); .Ve .PP There are several configurable package variables that affect the behavior of Expect. They are: .PP .Vb 8 \& $Expect::Debug; \& $Expect::Exp_Internal; \& $Expect::IgnoreEintr; \& $Expect::Log_Group; \& $Expect::Log_Stdout; \& $Expect::Manual_Stty; \& $Expect::Multiline_Matching; \& $Expect::Do_Soft_Close; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" See an explanation of What is Expect .PP The Expect module is a successor of Comm.pl and a descendent of Chat.pl. It more closely resembles the Tcl Expect language than its predecessors. It does not contain any of the networking code found in Comm.pl. I suspect this would be obsolete anyway given the advent of IO::Socket and external tools such as netcat. .PP Expect.pm is an attempt to have more of a \fBswitch()\fR & case feeling to make decision processing more fluid. Three separate types of debugging have been implemented to make code production easier. .PP It is possible to interconnect multiple file handles (and processes) much like Tcl's Expect. An attempt was made to enable all the features of Tcl's Expect without forcing Tcl on the victim programmer :\-) . .PP Please, before you consider using Expect, read the FAQs about \&\*(L"I want to automate password entry for su/ssh/scp/rsh/...\*(R" and \&\*(L"I want to use Expect to automate [anything with a buzzword]...\*(R" .SH "USAGE" .IX Header "USAGE" .IP "new" 4 .IX Item "new" Creates a new Expect object, i.e. a pty. You can change parameters on it before actually spawning a command. This is important if you want to modify the terminal settings for the slave. See \fBslave()\fR below. The object returned is actually a reblessed IO::Pty filehandle, so see there for additional methods. .IP "Expect\->exp_init(\e*FILEHANDLE) \fIor\fR" 4 .IX Item "Expect->exp_init(*FILEHANDLE) or" .PD 0 .IP "Expect\->init(\e*FILEHANDLE)" 4 .IX Item "Expect->init(*FILEHANDLE)" .PD Initializes \f(CW$new_handle_object\fR for use with other Expect functions. It must be passed a \fB_reference_\fR to \s-1FILEHANDLE\s0 if you want it to work properly. IO::File objects are preferable. Returns a reference to the newly created object. .Sp You can use only real filehandles, certain tied filehandles (e.g. Net::SSH2) that lack a \fBfileno()\fR will not work. Net::Telnet objects can be used but have been reported to work only for certain hosts. \s-1YMMV.\s0 .ie n .IP "Expect\->spawn($command, @parameters) \fIor\fR" 4 .el .IP "Expect\->spawn($command, \f(CW@parameters\fR) \fIor\fR" 4 .IX Item "Expect->spawn($command, @parameters) or" .PD 0 .ie n .IP "$object\->spawn($command, @parameters) \fIor\fR" 4 .el .IP "\f(CW$object\fR\->spawn($command, \f(CW@parameters\fR) \fIor\fR" 4 .IX Item "$object->spawn($command, @parameters) or" .ie n .IP "Expect\->new($command, @parameters)" 4 .el .IP "Expect\->new($command, \f(CW@parameters\fR)" 4 .IX Item "Expect->new($command, @parameters)" .PD Forks and execs \f(CW$command\fR. Returns an Expect object upon success or \&\f(CW\*(C`undef\*(C'\fR if the fork was unsuccessful or the command could not be found. \fBspawn()\fR passes its parameters unchanged to Perls \fBexec()\fR, so look there for detailed semantics. .Sp Note that if spawn cannot \fBexec()\fR the given command, the Expect object is still valid and the next \fBexpect()\fR will see \*(L"Cannot exec\*(R", so you can use that for error handling. .Sp Also note that you cannot reuse an object with an already spawned command, even if that command has exited. Sorry, but you have to allocate a new object... .ie n .IP "$object\->debug(0 | 1 | 2 | 3 | undef)" 4 .el .IP "\f(CW$object\fR\->debug(0 | 1 | 2 | 3 | undef)" 4 .IX Item "$object->debug(0 | 1 | 2 | 3 | undef)" Sets debug level for \f(CW$object\fR. 1 refers to general debugging information, 2 refers to verbose debugging and 0 refers to no debugging. If you call \fBdebug()\fR with no parameters it will return the current debugging level. When the object is created the debugging level will match that \f(CW$Expect::Debug\fR, normally 0. .Sp The '3' setting is new with 1.05, and adds the additional functionality of having the _full_ accumulated buffer printed every time data is read from an Expect object. This was implemented by request. I recommend against using this unless you think you need it as it can create quite a quantity of output under some circumstances.. .ie n .IP "$object\->exp_internal(1 | 0)" 4 .el .IP "\f(CW$object\fR\->exp_internal(1 | 0)" 4 .IX Item "$object->exp_internal(1 | 0)" Sets/unsets 'exp_internal' debugging. This is similar in nature to its Tcl counterpart. It is extremely valuable when debugging \fBexpect()\fR sequences. When the object is created the exp_internal setting will match the value of \&\f(CW$Expect::Exp_Internal\fR, normally 0. Returns the current setting if called without parameters. It is highly recommended that you make use of the debugging features lest you have angry code. .ie n .IP "$object\->raw_pty(1 | 0)" 4 .el .IP "\f(CW$object\fR\->raw_pty(1 | 0)" 4 .IX Item "$object->raw_pty(1 | 0)" Set pty to raw mode before spawning. This disables echoing, \s-1CR\-\s0>\s-1LF\s0 translation and an ugly hack for broken Solaris TTYs (which send to slow things down) and thus gives a more pipe-like behaviour (which is important if you want to transfer binary content). Note that this must be set \fIbefore\fR spawning the program. .ie n .IP "$object\->stty(qw(mode1 mode2...))" 4 .el .IP "\f(CW$object\fR\->stty(qw(mode1 mode2...))" 4 .IX Item "$object->stty(qw(mode1 mode2...))" Sets the tty mode for \f(CW$object\fR's associated terminal to the given modes. Note that on many systems the master side of the pty is not a tty, so you have to modify the slave pty instead, see next item. This needs IO::Stty installed, which is no longer required. .ie n .IP "$object\->\fBslave()\fR" 4 .el .IP "\f(CW$object\fR\->\fBslave()\fR" 4 .IX Item "$object->slave()" Returns a filehandle to the slave part of the pty. Very useful in modifying the terminal settings: .Sp .Vb 1 \& $object\->slave\->stty(qw(raw \-echo)); .Ve .Sp Typical values are 'sane', 'raw', and 'raw \-echo'. Note that I recommend setting the terminal to 'raw' or 'raw \-echo', as this avoids a lot of hassle and gives pipe-like (i.e. transparent) behaviour (without the buffering issue). .ie n .IP "$object\->print(@strings) \fIor\fR" 4 .el .IP "\f(CW$object\fR\->print(@strings) \fIor\fR" 4 .IX Item "$object->print(@strings) or" .PD 0 .ie n .IP "$object\->send(@strings)" 4 .el .IP "\f(CW$object\fR\->send(@strings)" 4 .IX Item "$object->send(@strings)" .PD Sends the given strings to the spawned command. Note that the strings are not logged in the logfile (see print_log_file) but will probably be echoed back by the pty, depending on pty settings (default is echo) and thus end up there anyway. This must also be taken into account when \fBexpect()\fRing for an answer: the next string will be the command just sent. I suggest setting the pty to raw, which disables echo and makes the pty transparently act like a bidirectional pipe. .ie n .IP "$object\->expect($timeout, @match_patterns)" 4 .el .IP "\f(CW$object\fR\->expect($timeout, \f(CW@match_patterns\fR)" 4 .IX Item "$object->expect($timeout, @match_patterns)" .RS 4 .PD 0 .IP "Simple interface" 4 .IX Item "Simple interface" .PD Given \f(CW$timeout\fR in seconds Expect will wait for \f(CW$object\fR's handle to produce one of the match_patterns, which are matched exactly by default. If you want a regexp match, prefix the pattern with '\-re'. .Sp .Vb 1 \& $object\->expect(15, \*(Aqmatch me exactly\*(Aq,\*(Aq\-re\*(Aq,\*(Aqmatch\es+me\es+exactly\*(Aq); .Ve .Sp Due to o/s limitations \f(CW$timeout\fR should be a round number. If \f(CW$timeout\fR is 0 Expect will check one time to see if \f(CW$object\fR's handle contains any of the match_patterns. If \f(CW$timeout\fR is undef Expect will wait forever for a pattern to match. .Sp If called in a scalar context, \fBexpect()\fR will return the position of the matched pattern within \f(CW@matched_patterns\fR, or undef if no pattern was matched. This is a position starting from 1, so if you want to know which of an array of \f(CW@matched_patterns\fR matched you should subtract one from the return value. .Sp If called in an array context \fBexpect()\fR will return ($matched_pattern_position, \f(CW$error\fR, \f(CW$successfully_matching_string\fR, \&\f(CW$before_match\fR, and \f(CW$after_match\fR). .Sp \&\f(CW$matched_pattern_position\fR will contain the value that would have been returned if \fBexpect()\fR had been called in a scalar context. .Sp \&\f(CW$error\fR is the error that occurred that caused \fBexpect()\fR to return. \f(CW$error\fR will contain a number followed by a string equivalent expressing the nature of the error. Possible values are undef, indicating no error, \&'1:TIMEOUT' indicating that \f(CW$timeout\fR seconds had elapsed without a match, '2:EOF' indicating an eof was read from \f(CW$object\fR, '3: spawn id($fileno) died' indicating that the process exited before matching and '4:$!' indicating whatever error was set in \f(CW$ERRNO\fR during the last read on \f(CW$object\fR's handle or during \fBselect()\fR. All handles indicated by set_group plus \s-1STDOUT\s0 will have all data to come out of \f(CW$object\fR printed to them during \fBexpect()\fR if log_group and log_stdout are set. .Sp \&\f(CW$successfully_matching_string\fR \&\f(CW$before_match\fR \&\f(CW$after_match\fR .Sp Changed from older versions is the regular expression handling. By default now all strings passed to \fBexpect()\fR are treated as literals. To match a regular expression pass '\-re' as a parameter in front of the pattern you want to match as a regexp. .Sp This change makes it possible to match literals and regular expressions in the same \fBexpect()\fR call. .Sp Also new is multiline matching. ^ will now match the beginning of lines. Unfortunately, because perl doesn't use $/ in determining where lines break using $ to find the end of a line frequently doesn't work. This is because your terminal is returning \*(L"\er\en\*(R" at the end of every line. One way to check for a pattern at the end of a line would be to use \er?$ instead of $. .Sp Example: Spawning telnet to a host, you might look for the escape character. telnet would return to you \*(L"\er\enEscape character is \&'^]'.\er\en\*(R". To find this you might use \f(CW$match\fR='^Escape char.*\e.\er?$'; .Sp .Vb 1 \& $telnet\->expect(10,\*(Aq\-re\*(Aq,$match); .Ve .IP "New more Tcl/Expect\-like interface" 4 .IX Item "New more Tcl/Expect-like interface" .Vb 11 \& expect($timeout, \& \*(Aq\-i\*(Aq, [ $obj1, $obj2, ... ], \& [ $re_pattern, sub { ...; exp_continue; }, @subparms, ], \& [ \*(Aqeof\*(Aq, sub { ... } ], \& [ \*(Aqtimeout\*(Aq, sub { ... }, \e$subparm1 ], \& \*(Aq\-i\*(Aq, [ $objn, ...], \& \*(Aq\-ex\*(Aq, $exact_pattern, sub { ... }, \& $exact_pattern, sub { ...; exp_continue_timeout; }, \& \*(Aq\-re\*(Aq, $re_pattern, sub { ... }, \& \*(Aq\-i\*(Aq, \e@object_list, @pattern_list, \& ...); .Ve .Sp It's now possible to expect on more than one connection at a time by specifying '\f(CW\*(C`\-i\*(C'\fR' and a single Expect object or a ref to an array containing Expect objects, e.g. .Sp .Vb 4 \& expect($timeout, \& \*(Aq\-i\*(Aq, $exp1, @patterns_1, \& \*(Aq\-i\*(Aq, [ $exp2, $exp3 ], @patterns_2_3, \& ) .Ve .Sp Furthermore, patterns can now be specified as array refs containing [$regexp, sub { ...}, \f(CW@optional_subprams\fR] . When the pattern matches, the subroutine is called with parameters ($matched_expect_obj, \&\f(CW@optional_subparms\fR). The subroutine can return the symbol `exp_continue' to continue the expect matching with timeout starting anew or return the symbol `exp_continue_timeout' for continuing expect without resetting the timeout count. .Sp .Vb 8 \& $exp\->expect($timeout, \& [ qr/username: /i, sub { my $self = shift; \& $self\->send("$username\en"); \& exp_continue; }], \& [ qr/password: /i, sub { my $self = shift; \& $self\->send("$password\en"); \& exp_continue; }], \& $shell_prompt); .Ve .Sp `expect' is now exported by default. .RE .RS 4 .RE .ie n .IP "$object\->\fBexp_before()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_before()\fR \fIor\fR" 4 .IX Item "$object->exp_before() or" .PD 0 .ie n .IP "$object\->\fBbefore()\fR" 4 .el .IP "\f(CW$object\fR\->\fBbefore()\fR" 4 .IX Item "$object->before()" .PD \&\fBbefore()\fR returns the 'before' part of the last \fBexpect()\fR call. If the last \&\fBexpect()\fR call didn't match anything, \fBexp_before()\fR will return the entire output of the object accumulated before the \fBexpect()\fR call finished. .Sp Note that this is something different than Tcl Expects \fBbefore()\fR!! .ie n .IP "$object\->\fBexp_after()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_after()\fR \fIor\fR" 4 .IX Item "$object->exp_after() or" .PD 0 .ie n .IP "$object\->\fBafter()\fR" 4 .el .IP "\f(CW$object\fR\->\fBafter()\fR" 4 .IX Item "$object->after()" .PD returns the 'after' part of the last \fBexpect()\fR call. If the last \&\fBexpect()\fR call didn't match anything, \fBexp_after()\fR will return \fBundef()\fR. .ie n .IP "$object\->\fBexp_match()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_match()\fR \fIor\fR" 4 .IX Item "$object->exp_match() or" .PD 0 .ie n .IP "$object\->\fBmatch()\fR" 4 .el .IP "\f(CW$object\fR\->\fBmatch()\fR" 4 .IX Item "$object->match()" .PD returns the string matched by the last \fBexpect()\fR call, undef if no string was matched. .ie n .IP "$object\->\fBexp_match_number()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_match_number()\fR \fIor\fR" 4 .IX Item "$object->exp_match_number() or" .PD 0 .ie n .IP "$object\->\fBmatch_number()\fR" 4 .el .IP "\f(CW$object\fR\->\fBmatch_number()\fR" 4 .IX Item "$object->match_number()" .PD \&\fBexp_match_number()\fR returns the number of the pattern matched by the last \&\fBexpect()\fR call. Keep in mind that the first pattern in a list of patterns is 1, not 0. Returns undef if no pattern was matched. .ie n .IP "$object\->\fBexp_matchlist()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_matchlist()\fR \fIor\fR" 4 .IX Item "$object->exp_matchlist() or" .PD 0 .ie n .IP "$object\->\fBmatchlist()\fR" 4 .el .IP "\f(CW$object\fR\->\fBmatchlist()\fR" 4 .IX Item "$object->matchlist()" .PD \&\fBexp_matchlist()\fR returns a list of matched substrings from the brackets () inside the regexp that last matched. ($object\->matchlist)[0] thus corresponds to \f(CW$1\fR, ($object\->matchlist)[1] to \f(CW$2\fR, etc. .ie n .IP "$object\->\fBexp_error()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_error()\fR \fIor\fR" 4 .IX Item "$object->exp_error() or" .PD 0 .ie n .IP "$object\->\fBerror()\fR" 4 .el .IP "\f(CW$object\fR\->\fBerror()\fR" 4 .IX Item "$object->error()" .PD \&\fBexp_error()\fR returns the error generated by the last \fBexpect()\fR call if no pattern was matched. It is typically useful to examine the value returned by \&\fBbefore()\fR to find out what the output of the object was in determining why it didn't match any of the patterns. .ie n .IP "$object\->\fBclear_accum()\fR" 4 .el .IP "\f(CW$object\fR\->\fBclear_accum()\fR" 4 .IX Item "$object->clear_accum()" Clear the contents of the accumulator for \f(CW$object\fR. This gets rid of any residual contents of a handle after \fBexpect()\fR or \fBsend_slow()\fR such that the next \fBexpect()\fR call will only see new data from \f(CW$object\fR. The contents of the accumulator are returned. .ie n .IP "$object\->set_accum($value)" 4 .el .IP "\f(CW$object\fR\->set_accum($value)" 4 .IX Item "$object->set_accum($value)" Sets the content of the accumulator for \f(CW$object\fR to \f(CW$value\fR. The previous content of the accumulator is returned. .ie n .IP "$object\->\fBexp_command()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_command()\fR \fIor\fR" 4 .IX Item "$object->exp_command() or" .PD 0 .ie n .IP "$object\->\fBcommand()\fR" 4 .el .IP "\f(CW$object\fR\->\fBcommand()\fR" 4 .IX Item "$object->command()" .PD \&\fBexp_command()\fR returns the string that was used to spawn the command. Helpful for debugging and for reused patternmatch subroutines. .ie n .IP "$object\->\fBexp_exitstatus()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_exitstatus()\fR \fIor\fR" 4 .IX Item "$object->exp_exitstatus() or" .PD 0 .ie n .IP "$object\->\fBexitstatus()\fR" 4 .el .IP "\f(CW$object\fR\->\fBexitstatus()\fR" 4 .IX Item "$object->exitstatus()" .PD Returns the exit status of \f(CW$object\fR (if it already exited). .ie n .IP "$object\->\fBexp_pty_handle()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_pty_handle()\fR \fIor\fR" 4 .IX Item "$object->exp_pty_handle() or" .PD 0 .ie n .IP "$object\->\fBpty_handle()\fR" 4 .el .IP "\f(CW$object\fR\->\fBpty_handle()\fR" 4 .IX Item "$object->pty_handle()" .PD Returns a string representation of the attached pty, for example: `spawn \fBid\fR\|(5)' (pty has fileno 5), `handle \fBid\fR\|(7)' (pty was initialized from fileno 7) or `\s-1STDIN\s0'. Useful for debugging. .ie n .IP "$object\->restart_timeout_upon_receive(0 | 1)" 4 .el .IP "\f(CW$object\fR\->restart_timeout_upon_receive(0 | 1)" 4 .IX Item "$object->restart_timeout_upon_receive(0 | 1)" If this is set to 1, the expect timeout is retriggered whenever something is received from the spawned command. This allows to perform some aliveness testing and still expect for patterns. .Sp .Vb 5 \& $exp\->restart_timeout_upon_receive(1); \& $exp\->expect($timeout, \& [ timeout => \e&report_timeout ], \& [ qr/pattern/ => \e&handle_pattern], \& ); .Ve .Sp Now the timeout isn't triggered if the command produces any kind of output, i.e. is still alive, but you can act upon patterns in the output. .ie n .IP "$object\->notransfer(1 | 0)" 4 .el .IP "\f(CW$object\fR\->notransfer(1 | 0)" 4 .IX Item "$object->notransfer(1 | 0)" Do not truncate the content of the accumulator after a match. Normally, the accumulator is set to the remains that come after the matched string. Note that this setting is per object and not per pattern, so if you want to have normal acting patterns that truncate the accumulator, you have to add a .Sp .Vb 1 \& $exp\->set_accum($exp\->after); .Ve .Sp to their callback, e.g. .Sp .Vb 12 \& $exp\->notransfer(1); \& $exp\->expect($timeout, \& # accumulator not truncated, pattern1 will match again \& [ "pattern1" => sub { my $self = shift; \& ... \& } ], \& # accumulator truncated, pattern2 will not match again \& [ "pattern2" => sub { my $self = shift; \& ... \& $self\->set_accum($self\->after()); \& } ], \& ); .Ve .Sp This is only a temporary fix until I can rewrite the pattern matching part so it can take that additional \-notransfer argument. .IP "Expect::interconnect(@objects);" 4 .IX Item "Expect::interconnect(@objects);" Read from \f(CW@objects\fR and print to their \f(CW@listen_groups\fR until an escape sequence is matched from one of \f(CW@objects\fR and the associated function returns 0 or undef. The special escape sequence '\s-1EOF\s0' is matched when an object's handle returns an end of file. Note that it is not necessary to include objects that only accept data in \f(CW@objects\fR since the escape sequence is _read_ from an object. Further note that the listen_group for a write-only object is always empty. Why would you want to have objects listening to \s-1STDOUT\s0 (for example)? By default every member of \f(CW@objects\fR _as well as every member of its listen group_ will be set to 'raw \-echo' for the duration of interconnection. Setting \f(CW$object\fR\->\fBmanual_stty()\fR will stop this behavior per object. The original tty settings will be restored as interconnect exits. .Sp For a generic way to interconnect processes, take a look at IPC::Run. .IP "Expect::test_handles(@objects)" 4 .IX Item "Expect::test_handles(@objects)" Given a set of objects determines which objects' handles have data ready to be read. \fBReturns an array\fR who's members are positions in \f(CW@objects\fR that have ready handles. Returns undef if there are no such handles ready. .IP "Expect::version($version_requested or undef);" 4 .IX Item "Expect::version($version_requested or undef);" Returns current version of Expect. As of .99 earlier versions are not supported. Too many things were changed to make versioning possible. .ie n .IP "$object\->interact( ""\e*FILEHANDLE, $escape_sequence"")" 4 .el .IP "\f(CW$object\fR\->interact( \f(CW\e*FILEHANDLE, $escape_sequence\fR)" 4 .IX Item "$object->interact( *FILEHANDLE, $escape_sequence)" \&\fBinteract()\fR is essentially a macro for calling \fBinterconnect()\fR for connecting 2 processes together. \e*FILEHANDLE defaults to \e*STDIN and \&\f(CW$escape_sequence\fR defaults to undef. Interaction ceases when \f(CW$escape_sequence\fR is read from \fB\s-1FILEHANDLE\s0\fR, not \f(CW$object\fR. \f(CW$object\fR's listen group will consist solely of \e*FILEHANDLE for the duration of the interaction. \&\e*FILEHANDLE will not be echoed on \s-1STDOUT.\s0 .ie n .IP "$object\->log_group(0 | 1 | undef)" 4 .el .IP "\f(CW$object\fR\->log_group(0 | 1 | undef)" 4 .IX Item "$object->log_group(0 | 1 | undef)" Set/unset logging of \f(CW$object\fR to its 'listen group'. If set all objects in the listen group will have output from \f(CW$object\fR printed to them during \&\f(CW$object\fR\->\fBexpect()\fR, \f(CW$object\fR\->\fBsend_slow()\fR, and \f(CW\*(C`Expect::interconnect($object , ...)\*(C'\fR. Default value is on. During creation of \f(CW$object\fR the setting will match the value of \f(CW$Expect::Log_Group\fR, normally 1. .ie n .IP "$object\->log_user(0 | 1 | undef) \fIor\fR" 4 .el .IP "\f(CW$object\fR\->log_user(0 | 1 | undef) \fIor\fR" 4 .IX Item "$object->log_user(0 | 1 | undef) or" .PD 0 .ie n .IP "$object\->log_stdout(0 | 1 | undef)" 4 .el .IP "\f(CW$object\fR\->log_stdout(0 | 1 | undef)" 4 .IX Item "$object->log_stdout(0 | 1 | undef)" .PD Set/unset logging of object's handle to \s-1STDOUT.\s0 This corresponds to Tcl's log_user variable. Returns current setting if called without parameters. Default setting is off for initialized handles. When a process object is created (not a filehandle initialized with exp_init) the log_stdout setting will match the value of \f(CW$Expect::Log_Stdout\fR variable, normally 1. If/when you initialize \s-1STDIN\s0 it is usually associated with a tty which will by default echo to \s-1STDOUT\s0 anyway, so be careful or you will have multiple echoes. .ie n .IP "$object\->log_file(""filename"" | $filehandle | \e&coderef | undef)" 4 .el .IP "\f(CW$object\fR\->log_file(``filename'' | \f(CW$filehandle\fR | \e&coderef | undef)" 4 .IX Item "$object->log_file(filename | $filehandle | &coderef | undef)" Log session to a file. All characters send to or received from the spawned process are written to the file. Normally appends to the logfile, but you can pass an additional mode of \*(L"w\*(R" to truncate the file upon \fBopen()\fR: .Sp .Vb 1 \& $object\->log_file("filename", "w"); .Ve .Sp Returns the logfilehandle. .Sp If called with an undef value, stops logging and closes logfile: .Sp .Vb 1 \& $object\->log_file(undef); .Ve .Sp If called without argument, returns the logfilehandle: .Sp .Vb 1 \& $fh = $object\->log_file(); .Ve .Sp Can be set to a code ref, which will be called instead of printing to the logfile: .Sp .Vb 1 \& $object\->log_file(\e&myloggerfunc); .Ve .ie n .IP "$object\->print_log_file(@strings)" 4 .el .IP "\f(CW$object\fR\->print_log_file(@strings)" 4 .IX Item "$object->print_log_file(@strings)" Prints to logfile (if opened) or calls the logfile hook function. This allows the user to add arbitrary text to the logfile. Note that this could also be done as \f(CW$object\fR\->log_file\->\fBprint()\fR but would only work for log files, not code hooks. .ie n .IP "$object\->set_seq($sequence, \e&function, \e@function_parameters)" 4 .el .IP "\f(CW$object\fR\->set_seq($sequence, \e&function, \e@function_parameters)" 4 .IX Item "$object->set_seq($sequence, &function, @function_parameters)" During Expect\->\fBinterconnect()\fR if \f(CW$sequence\fR is read from \f(CW$object\fR &function will be executed with parameters \f(CW@function_parameters\fR. It is \fB_highly recommended_\fR that the escape sequence be a single character since the likelihood is great that the sequence will be broken into to separate reads from the \f(CW$object\fR's handle, making it impossible to strip \f(CW$sequence\fR from getting printed to \f(CW$object\fR's listen group. \e&function should be something like 'main::control_w_function' and \f(CW@function_parameters\fR should be an array defined by the caller, passed by reference to \fBset_seq()\fR. Your function should return a non-zero value if execution of \fBinterconnect()\fR is to resume after the function returns, zero or undefined if \fBinterconnect()\fR should return after your function returns. The special sequence '\s-1EOF\s0' matches the end of file being reached by \f(CW$object\fR. See \fBinterconnect()\fR for details. .ie n .IP "$object\->set_group(@listener_objects)" 4 .el .IP "\f(CW$object\fR\->set_group(@listener_objects)" 4 .IX Item "$object->set_group(@listener_objects)" \&\f(CW@listener_objects\fR is the list of objects that should have their handles printed to by \f(CW$object\fR when Expect::interconnect, \f(CW$object\fR\->\fBexpect()\fR or \&\f(CW$object\fR\->\fBsend_slow()\fR are called. Calling w/out parameters will return the current list of the listener objects. .ie n .IP "$object\->manual_stty(0 | 1 | undef)" 4 .el .IP "\f(CW$object\fR\->manual_stty(0 | 1 | undef)" 4 .IX Item "$object->manual_stty(0 | 1 | undef)" Sets/unsets whether or not Expect should make reasonable guesses as to when and how to set tty parameters for \f(CW$object\fR. Will match \&\f(CW$Expect::Manual_Stty\fR value (normally 0) when \f(CW$object\fR is created. If called without parameters \fBmanual_stty()\fR will return the current manual_stty setting. .ie n .IP "$object\->match_max($maximum_buffer_length | undef) \fIor\fR" 4 .el .IP "\f(CW$object\fR\->match_max($maximum_buffer_length | undef) \fIor\fR" 4 .IX Item "$object->match_max($maximum_buffer_length | undef) or" .PD 0 .ie n .IP "$object\->max_accum($maximum_buffer_length | undef)" 4 .el .IP "\f(CW$object\fR\->max_accum($maximum_buffer_length | undef)" 4 .IX Item "$object->max_accum($maximum_buffer_length | undef)" .PD Set the maximum accumulator size for object. This is useful if you think that the accumulator will grow out of hand during \fBexpect()\fR calls. Since the buffer will be matched by every match_pattern it may get slow if the buffer gets too large. Returns current value if called without parameters. Not defined by default. .ie n .IP "$object\->notransfer(0 | 1)" 4 .el .IP "\f(CW$object\fR\->notransfer(0 | 1)" 4 .IX Item "$object->notransfer(0 | 1)" If set, matched strings will not be deleted from the accumulator. Returns current value if called without parameters. False by default. .ie n .IP "$object\->\fBexp_pid()\fR \fIor\fR" 4 .el .IP "\f(CW$object\fR\->\fBexp_pid()\fR \fIor\fR" 4 .IX Item "$object->exp_pid() or" .PD 0 .ie n .IP "$object\->\fBpid()\fR" 4 .el .IP "\f(CW$object\fR\->\fBpid()\fR" 4 .IX Item "$object->pid()" .PD Return pid of \f(CW$object\fR, if one exists. Initialized filehandles will not have pids (of course). .ie n .IP "$object\->send_slow($delay, @strings);" 4 .el .IP "\f(CW$object\fR\->send_slow($delay, \f(CW@strings\fR);" 4 .IX Item "$object->send_slow($delay, @strings);" print each character from each string of \f(CW@strings\fR one at a time with \f(CW$delay\fR seconds before each character. This is handy for devices such as modems that can be annoying if you send them data too fast. After each character \&\f(CW$object\fR will be checked to determine whether or not it has any new data ready and if so update the accumulator for future \fBexpect()\fR calls and print the output to \s-1STDOUT\s0 and \f(CW@listen_group\fR if log_stdout and log_group are appropriately set. .SS "Configurable Package Variables:" .IX Subsection "Configurable Package Variables:" .ie n .IP "$Expect::Debug" 4 .el .IP "\f(CW$Expect::Debug\fR" 4 .IX Item "$Expect::Debug" Defaults to 0. Newly created objects have a \f(CW$object\fR\->\fBdebug()\fR value of \f(CW$Expect::Debug\fR. See \f(CW$object\fR\->\fBdebug()\fR; .ie n .IP "$Expect::Do_Soft_Close" 4 .el .IP "\f(CW$Expect::Do_Soft_Close\fR" 4 .IX Item "$Expect::Do_Soft_Close" Defaults to 0. When destroying objects, soft_close may take up to half a minute to shut everything down. From now on, only hard_close will be called, which is less polite but still gives the process a chance to terminate properly. Set this to '1' for old behaviour. .ie n .IP "$Expect::Exp_Internal" 4 .el .IP "\f(CW$Expect::Exp_Internal\fR" 4 .IX Item "$Expect::Exp_Internal" Defaults to 0. Newly created objects have a \f(CW$object\fR\->\fBexp_internal()\fR value of \f(CW$Expect::Exp_Internal\fR. See \f(CW$object\fR\->\fBexp_internal()\fR. .ie n .IP "$Expect::IgnoreEintr" 4 .el .IP "\f(CW$Expect::IgnoreEintr\fR" 4 .IX Item "$Expect::IgnoreEintr" Defaults to 0. If set to 1, when waiting for new data, Expect will ignore \s-1EINTR\s0 errors and restart the \fBselect()\fR call instead. .ie n .IP "$Expect::Log_Group" 4 .el .IP "\f(CW$Expect::Log_Group\fR" 4 .IX Item "$Expect::Log_Group" Defaults to 1. Newly created objects have a \f(CW$object\fR\->\fBlog_group()\fR value of \f(CW$Expect::Log_Group\fR. See \f(CW$object\fR\->\fBlog_group()\fR. .ie n .IP "$Expect::Log_Stdout" 4 .el .IP "\f(CW$Expect::Log_Stdout\fR" 4 .IX Item "$Expect::Log_Stdout" Defaults to 1 for spawned commands, 0 for file handles attached with \fBexp_init()\fR. Newly created objects have a \&\f(CW$object\fR\->\fBlog_stdout()\fR value of \f(CW$Expect::Log_Stdout\fR. See \&\f(CW$object\fR\->\fBlog_stdout()\fR. .ie n .IP "$Expect::Manual_Stty" 4 .el .IP "\f(CW$Expect::Manual_Stty\fR" 4 .IX Item "$Expect::Manual_Stty" Defaults to 0. Newly created objects have a \f(CW$object\fR\->\fBmanual_stty()\fR value of \f(CW$Expect::Manual_Stty\fR. See \f(CW$object\fR\->\fBmanual_stty()\fR. .ie n .IP "$Expect::Multiline_Matching" 4 .el .IP "\f(CW$Expect::Multiline_Matching\fR" 4 .IX Item "$Expect::Multiline_Matching" Defaults to 1. Affects whether or not \fBexpect()\fR uses the /m flag for doing regular expression matching. If set to 1 /m is used. .Sp This makes a difference when you are trying to match ^ and $. If you have this on you can match lines in the middle of a page of output using ^ and $ instead of it matching the beginning and end of the entire expression. I think this is handy. .Sp The \f(CW$Expect::Multiline_Matching\fR turns on and off Expect's multi-line matching mode. But this only has an effect if you pass in a string, and then use '\-re' mode. If you pass in a regular expression value (via qr//), then the qr//'s own flags are preserved irrespective of what it gets interpolated into. There was a bug in Perl 5.8.x where interpolating a regex without /m into a match with /m would incorrectly apply the /m to the inner regex too, but this was fixed in Perl 5.10. The correct behavior, as seen in Perl 5.10, is that if you pass in a regex (via qr//), then \f(CW$Expect::Multiline_Matching\fR has no effect. So if you pass in a regex, then you must use the qr's flags to control whether it is multiline (which by default it is not, opposite of the default behavior of Expect). .SH "CONTRIBUTIONS" .IX Header "CONTRIBUTIONS" Lee Eakin has ported the kibitz script from Tcl/Expect to Perl/Expect. .PP Jeff Carr provided a simple example of how handle terminal window resize events (transmitted via the \s-1WINCH\s0 signal) in a ssh session. .PP You can find both scripts in the examples/ subdir. Thanks to both! .PP Historical notes: .PP There are still a few lines of code dating back to the inspirational Comm.pl and Chat.pl modules without which this would not have been possible. Kudos to Eric Arnold and Randal 'Nuke your \s-1NT\s0 box with one line of perl code' Schwartz for making these available to the perl public. .PP As of .98 I think all the old code is toast. No way could this have been done without it though. Special thanks to Graham Barr for helping make sense of the IO::Handle stuff as well as providing the highly recommended IO::Tty module. .SH "REFERENCES" .IX Header "REFERENCES" Mark Rogaski wrote: .PP \&\*(L"I figured that you'd like to know that Expect.pm has been very useful to \s-1AT&T\s0 Labs over the past couple of years (since I first talked to Austin about design decisions). We use Expect.pm for managing the switches in our network via the telnet interface, and such automation has significantly increased our reliability. So, you can honestly say that one of the largest digital networks in existence (\s-1AT&T\s0 Frame Relay) uses Expect.pm quite extensively.\*(R" .SH "FAQ \- Frequently Asked Questions" .IX Header "FAQ - Frequently Asked Questions" This is a growing collection of things that might help. Please send you questions that are not answered here to RGiersig@cpan.org .SS "What systems does Expect run on?" .IX Subsection "What systems does Expect run on?" Expect itself doesn't have real system dependencies, but the underlying IO::Tty needs pseudoterminals. IO::Stty uses \s-1POSIX\s0.pm and Fcntl.pm. .PP I have used it on Solaris, Linux and \s-1AIX,\s0 others report *BSD and \s-1OSF\s0 as working. Generally, any modern \s-1POSIX\s0 Unix should do, but there are exceptions to every rule. Feedback is appreciated. .PP See IO::Tty for a list of verified systems. .SS "Can I use this module with ActivePerl on Windows?" .IX Subsection "Can I use this module with ActivePerl on Windows?" Up to now, the answer was 'No', but this has changed. .PP You still cannot use ActivePerl, but if you use the Cygwin environment (http://sources.redhat.com), which brings its own perl, and have the latest IO::Tty (v0.05 or later) installed, it should work (feedback appreciated). .SS "The examples in the tutorial don't work!" .IX Subsection "The examples in the tutorial don't work!" The tutorial is hopelessly out of date and needs a serious overhaul. I apologize for this, I have concentrated my efforts mainly on the functionality. Volunteers welcomed. .SS "How can I find out what Expect is doing?" .IX Subsection "How can I find out what Expect is doing?" If you set .PP .Vb 1 \& $Expect::Exp_Internal = 1; .Ve .PP Expect will tell you very verbosely what it is receiving and sending, what matching it is trying and what it found. You can do this on a per-command base with .PP .Vb 1 \& $exp\->exp_internal(1); .Ve .PP You can also set .PP .Vb 1 \& $Expect::Debug = 1; # or 2, 3 for more verbose output .Ve .PP or .PP .Vb 1 \& $exp\->debug(1); .Ve .PP which gives you even more output. .SS "I am seeing the output of the command I spawned. Can I turn that off?" .IX Subsection "I am seeing the output of the command I spawned. Can I turn that off?" Yes, just set .PP .Vb 1 \& $Expect::Log_Stdout = 0; .Ve .PP to globally disable it or .PP .Vb 1 \& $exp\->log_stdout(0); .Ve .PP for just that command. 'log_user' is provided as an alias so Tcl/Expect user get a \s-1DWIM\s0 experience... :\-) .SS "No, I mean that when I send some text to the spawned process, it gets echoed back and I have to deal with it in the next expect." .IX Subsection "No, I mean that when I send some text to the spawned process, it gets echoed back and I have to deal with it in the next expect." This is caused by the pty, which has probably 'echo' enabled. A solution would be to set the pty to raw mode, which in general is cleaner for communication between two programs (no more unexpected character translations). Unfortunately this would break a lot of old code that sends \*(L"\er\*(R" to the program instead of \*(L"\en\*(R" (translating this is also handled by the pty), so I won't add this to Expect just like that. But feel free to experiment with \f(CW\*(C`$exp\->raw_pty(1)\*(C'\fR. .SS "How do I send control characters to a process?" .IX Subsection "How do I send control characters to a process?" A: You can send any characters to a process with the print command. To represent a control character in Perl, use \ec followed by the letter. For example, control-G can be represented with \*(L"\ecG\*(R" . Note that this will not work if you single-quote your string. So, to send control-C to a process in \&\f(CW$exp\fR, do: .PP .Vb 1 \& print $exp "\ecC"; .Ve .PP Or, if you prefer: .PP .Vb 1 \& $exp\->send("\ecC"); .Ve .PP The ability to include control characters in a string like this is provided by Perl, not by Expect.pm . Trying to learn Expect.pm without a thorough grounding in Perl can be very daunting. We suggest you look into some of the excellent Perl learning material, such as the books _Programming Perl_ and _Learning Perl_ by O'Reilly, as well as the extensive online Perl documentation available through the perldoc command. .SS "My script fails from time to time without any obvious reason. It seems that I am sometimes loosing output from the spawned program." .IX Subsection "My script fails from time to time without any obvious reason. It seems that I am sometimes loosing output from the spawned program." You could be exiting too fast without giving the spawned program enough time to finish. Try adding \f(CW$exp\fR\->\fBsoft_close()\fR to terminate the program gracefully or do an \fBexpect()\fR for 'eof'. .PP Alternatively, try adding a 'sleep 1' after you \fBspawn()\fR the program. It could be that pty creation on your system is just slow (but this is rather improbable if you are using the latest IO-Tty). .SS "I want to automate password entry for su/ssh/scp/rsh/..." .IX Subsection "I want to automate password entry for su/ssh/scp/rsh/..." You shouldn't use Expect for this. Putting passwords, especially root passwords, into scripts in clear text can mean severe security problems. I strongly recommend using other means. For 'su', consider switching to 'sudo', which gives you root access on a per-command and per-user basis without the need to enter passwords. 'ssh'/'scp' can be set up with \s-1RSA\s0 authentication without passwords. 'rsh' can use the .rhost mechanism, but I'd strongly suggest to switch to 'ssh'; to mention 'rsh' and 'security' in the same sentence makes an oxymoron. .PP It will work for 'telnet', though, and there are valid uses for it, but you still might want to consider using 'ssh', as keeping cleartext passwords around is very insecure. .SS "I want to use Expect to automate [anything with a buzzword]..." .IX Subsection "I want to use Expect to automate [anything with a buzzword]..." Are you sure there is no other, easier way? As a rule of thumb, Expect is useful for automating things that expect to talk to a human, where no formal standard applies. For other tasks that do follow a well-defined protocol, there are often better-suited modules that already can handle those protocols. Don't try to do \s-1HTTP\s0 requests by spawning telnet to port 80, use \s-1LWP\s0 instead. To automate \s-1FTP,\s0 take a look at Net::FTP or \f(CW\*(C`ncftp\*(C'\fR (http://www.ncftp.org). You don't use a screwdriver to hammer in your nails either, or do you? .SS "Is it possible to use threads with Expect?" .IX Subsection "Is it possible to use threads with Expect?" Basically yes, with one restriction: you must \fBspawn()\fR your programs in the main thread and then pass the Expect objects to the handling threads. The reason is that \fBspawn()\fR uses \fBfork()\fR, and perlthrtut: .PP .Vb 1 \& "Thinking of mixing fork() and threads? Please lie down and wait until the feeling passes." .Ve .SS "I want to log the whole session to a file." .IX Subsection "I want to log the whole session to a file." Use .PP .Vb 1 \& $exp\->log_file("filename"); .Ve .PP or .PP .Vb 1 \& $exp\->log_file($filehandle); .Ve .PP or even .PP .Vb 1 \& $exp\->log_file(\e&log_procedure); .Ve .PP for maximum flexibility. .PP Note that the logfile is appended to by default, but you can specify an optional mode \*(L"w\*(R" to truncate the logfile: .PP .Vb 1 \& $exp\->log_file("filename", "w"); .Ve .PP To stop logging, just call it with a false argument: .PP .Vb 1 \& $exp\->log_file(undef); .Ve .SS "How can I turn off multi-line matching for my regexps?" .IX Subsection "How can I turn off multi-line matching for my regexps?" To globally unset multi-line matching for all regexps: .PP .Vb 1 \& $Expect::Multiline_Matching = 0; .Ve .PP You can do that on a per-regexp basis by stating \f(CW\*(C`(?\-m)\*(C'\fR inside the regexp (you need perl5.00503 or later for that). .SS "How can I expect on multiple spawned commands?" .IX Subsection "How can I expect on multiple spawned commands?" You can use the \fB\-i\fR parameter to specify a single object or a list of Expect objects. All following patterns will be evaluated against that list. .PP You can specify \fB\-i\fR multiple times to create groups of objects and patterns to match against within the same expect statement. .PP This works just like in Tcl/Expect. .PP See the source example below. .SS "I seem to have problems with ptys!" .IX Subsection "I seem to have problems with ptys!" Well, pty handling is really a black magic, as it is extremely system dependent. I have extensively revised IO-Tty, so these problems should be gone. .PP If your system is listed in the \*(L"verified\*(R" list of IO::Tty, you probably have some non-standard setup, e.g. you compiled your Linux-kernel yourself and disabled ptys. Please ask your friendly sysadmin for help. .PP If your system is not listed, unpack the latest version of IO::Tty, do a 'perl Makefile.PL; make; make test; uname \f(CW\*(C`\-a\*(C'\fR' and send me the results and I'll see what I can deduce from that. .SS "I just want to read the output of a process without \fBexpect()\fPing anything. How can I do this?" .IX Subsection "I just want to read the output of a process without expect()ing anything. How can I do this?" [ Are you sure you need Expect for this? How about \fBqx()\fR or open(\*(L"prog|\*(R")? ] .PP By using expect without any patterns to match. .PP .Vb 3 \& $process\->expect(undef); # Forever until EOF \& $process\->expect($timeout); # For a few seconds \& $process\->expect(0); # Is there anything ready on the handle now? .Ve .SS "Ok, so now how do I get what was read on the handle?" .IX Subsection "Ok, so now how do I get what was read on the handle?" .Vb 1 \& $read = $process\->before(); .Ve .SS "Where's IO::Pty?" .IX Subsection "Where's IO::Pty?" Find it on \s-1CPAN\s0 as IO-Tty, which provides both. .SS "How come when I automate the passwd program to change passwords for me passwd dies before changing the password sometimes/every time?" .IX Subsection "How come when I automate the passwd program to change passwords for me passwd dies before changing the password sometimes/every time?" What's happening is you are closing the handle before passwd exits. When you close the handle to a process, it is sent a signal (\s-1SIGPIPE\s0?) telling it that \s-1STDOUT\s0 has gone away. The default behavior for processes is to die in this circumstance. Two ways you can make this not happen are: .PP .Vb 1 \& $process\->soft_close(); .Ve .PP This will wait 15 seconds for a process to come up with an \s-1EOF\s0 by itself before killing it. .PP .Vb 1 \& $process\->expect(undef); .Ve .PP This will wait forever for the process to match an empty set of patterns. It will return when the process hits an \s-1EOF.\s0 .PP As a rule, you should always \fBexpect()\fR the result of your transaction before you continue with processing. .SS "How come when I try to make a logfile with \fBlog_file()\fP or \fBset_group()\fP it doesn't print anything after the last time I run \fBexpect()\fP?" .IX Subsection "How come when I try to make a logfile with log_file() or set_group() it doesn't print anything after the last time I run expect()?" Output is only printed to the logfile/group when Expect reads from the process, during \fBexpect()\fR, \fBsend_slow()\fR and \fBinterconnect()\fR. One way you can force this is to make use of .PP .Vb 1 \& $process\->expect(undef); .Ve .PP and .PP .Vb 1 \& $process\->expect(0); .Ve .PP which will make \fBexpect()\fR run with an empty pattern set forever or just for an instant to capture the output of \f(CW$process\fR. The output is available in the accumulator, so you can grab it using \&\f(CW$process\fR\->\fBbefore()\fR. .SS "I seem to have problems with terminal settings, double echoing, etc." .IX Subsection "I seem to have problems with terminal settings, double echoing, etc." Tty settings are a major pain to keep track of. If you find unexpected behavior such as double-echoing or a frozen session, doublecheck the documentation for default settings. When in doubt, handle them yourself using \f(CW$exp\fR\->\fBstty()\fR and \fBmanual_stty()\fR functions. As of .98 you shouldn't have to worry about stty settings getting fouled unless you use interconnect or intentionally change them (like doing \-echo to get a password). .PP If you foul up your terminal's tty settings, kill any hung processes and enter 'stty sane' at a shell prompt. This should make your terminal manageable again. .PP Note that IO::Tty returns ptys with your systems default setting regarding echoing, \s-1CRLF\s0 translation etc. and Expect does not change them. I have considered setting the ptys to 'raw' without any translation whatsoever, but this would break a lot of existing things, as '\er' translation would not work anymore. On the other hand, a raw pty works much like a pipe and is more \s-1WYGIWYE\s0 (what you get is what you expect), so I suggest you set it to 'raw' by yourself: .PP .Vb 3 \& $exp = Expect\->new; \& $exp\->raw_pty(1); \& $exp\->spawn(...); .Ve .PP To disable echo: .PP .Vb 1 \& $exp\->slave\->stty(qw(\-echo)); .Ve .SS "I'm spawning a telnet/ssh session and then let the user interact with it. But screen-oriented applications on the other side don't work properly." .IX Subsection "I'm spawning a telnet/ssh session and then let the user interact with it. But screen-oriented applications on the other side don't work properly." You have to set the terminal screen size for that. Luckily, IO::Pty already has a method for that, so modify your code to look like this: .PP .Vb 3 \& my $exp = Expect\->new; \& $exp\->slave\->clone_winsize_from(\e*STDIN); \& $exp\->spawn("telnet somehost); .Ve .PP Also, some applications need the \s-1TERM\s0 shell variable set so they know how to move the cursor across the screen. When logging in, the remote shell sends a query (Ctrl-Z I think) and expects the terminal to answer with a string, e.g. 'xterm'. If you really want to go that way (be aware, madness lies at its end), you can handle that and send back the value in \f(CW$ENV\fR{\s-1TERM\s0}. This is only a hand-waving explanation, please figure out the details by yourself. .SS "I set the terminal size as explained above, but if I resize the window, the application does not notice this." .IX Subsection "I set the terminal size as explained above, but if I resize the window, the application does not notice this." You have to catch the signal \s-1WINCH\s0 (\*(L"window size changed\*(R"), change the terminal size and propagate the signal to the spawned application: .PP .Vb 4 \& my $exp = Expect\->new; \& $exp\->slave\->clone_winsize_from(\e*STDIN); \& $exp\->spawn("ssh somehost); \& $SIG{WINCH} = \e&winch; \& \& sub winch { \& $exp\->slave\->clone_winsize_from(\e*STDIN); \& kill WINCH => $exp\->pid if $exp\->pid; \& $SIG{WINCH} = \e&winch; \& } \& \& $exp\->interact(); .Ve .PP There is an example file ssh.pl in the examples/ subdir that shows how this works with ssh. Please note that I do strongly object against using Expect to automate ssh login, as there are better way to do that (see ssh-keygen). .SS "I noticed that the test uses a string that resembles, but not exactly matches, a well-known sentence that contains every character. What does that mean?" .IX Subsection "I noticed that the test uses a string that resembles, but not exactly matches, a well-known sentence that contains every character. What does that mean?" That means you are anal-retentive. :\-) [Gotcha there!] .ie n .SS "I get a ""Could not assign a pty"" error when running as a non-root user on an \s-1IRIX\s0 box?" .el .SS "I get a ``Could not assign a pty'' error when running as a non-root user on an \s-1IRIX\s0 box?" .IX Subsection "I get a Could not assign a pty error when running as a non-root user on an IRIX box?" The \s-1OS\s0 may not be configured to grant additional pty's (pseudo terminals) to non-root users. /usr/sbin/mkpts should be 4755, not 700 for this to work. I don't know about security implications if you do this. .SS "How come I don't notice when the spawned process closes its stdin/out/err??" .IX Subsection "How come I don't notice when the spawned process closes its stdin/out/err??" You are probably on one of the systems where the master doesn't get an \&\s-1EOF\s0 when the slave closes stdin/out/err. .PP One possible solution is when you spawn a process, follow it with a unique string that would indicate the process is finished. .PP .Vb 1 \& $process = Expect\->spawn(\*(Aqtelnet somehost; echo _\|_\|_\|_END_\|_\|_\|_\*(Aq); .Ve .PP And then \f(CW$process\fR\->expect($timeout,'_\|_\|_\|_END_\|_\|_\|_','other','patterns'); .SH "Source Examples" .IX Header "Source Examples" .SS "How to automate login" .IX Subsection "How to automate login" .Vb 3 \& my $telnet = Net::Telnet\->new("remotehost") # see Net::Telnet \& or die "Cannot telnet to remotehost: $!\en";; \& my $exp = Expect\->exp_init($telnet); \& \& # deprecated use of spawned telnet command \& # my $exp = Expect\->spawn("telnet localhost") \& # or die "Cannot spawn telnet: $!\en";; \& \& my $spawn_ok; \& $exp\->expect($timeout, \& [ \& qr\*(Aqlogin: $\*(Aq, \& sub { \& $spawn_ok = 1; \& my $fh = shift; \& $fh\->send("$username\en"); \& exp_continue; \& } \& ], \& [ \& \*(AqPassword: $\*(Aq, \& sub { \& my $fh = shift; \& print $fh "$password\en"; \& exp_continue; \& } \& ], \& [ \& eof => \& sub { \& if ($spawn_ok) { \& die "ERROR: premature EOF in login.\en"; \& } else { \& die "ERROR: could not spawn telnet.\en"; \& } \& } \& ], \& [ \& timeout => \& sub { \& die "No login.\en"; \& } \& ], \& \*(Aq\-re\*(Aq, qr\*(Aq[#>:] $\*(Aq, #\*(Aq wait for shell prompt, then exit expect \& ); .Ve .SS "How to expect on multiple spawned commands" .IX Subsection "How to expect on multiple spawned commands" .Vb 3 \& foreach my $cmd (@list_of_commands) { \& push @commands, Expect\->spawn($cmd); \& } \& \& expect($timeout, \& \*(Aq\-i\*(Aq, \e@commands, \& [ \& qr"pattern", # find this pattern in output of all commands \& sub { \& my $obj = shift; # object that matched \& print $obj "something\en"; \& exp_continue; # we don\*(Aqt want to terminate the expect call \& } \& ], \& \*(Aq\-i\*(Aq, $some_other_command, \& [ \& "some other pattern", \& sub { \& my ($obj, $parmref) = @_; \& # ... \& \& # now we exit the expect command \& }, \& \e$parm \& ], \& ); .Ve .SS "How to propagate terminal sizes" .IX Subsection "How to propagate terminal sizes" .Vb 4 \& my $exp = Expect\->new; \& $exp\->slave\->clone_winsize_from(\e*STDIN); \& $exp\->spawn("ssh somehost); \& $SIG{WINCH} = \e&winch; \& \& sub winch { \& $exp\->slave\->clone_winsize_from(\e*STDIN); \& kill WINCH => $exp\->pid if $exp\->pid; \& $SIG{WINCH} = \e&winch; \& } \& \& $exp\->interact(); .Ve .SH "HOMEPAGE" .IX Header "HOMEPAGE" though the source code is now in GitHub: .SH "MAILING LISTS" .IX Header "MAILING LISTS" There are two mailing lists available, expectperl-announce and expectperl-discuss, at .PP .Vb 1 \& http://lists.sourceforge.net/lists/listinfo/expectperl\-announce .Ve .PP and .PP .Vb 1 \& http://lists.sourceforge.net/lists/listinfo/expectperl\-discuss .Ve .SH "BUG TRACKING" .IX Header "BUG TRACKING" You can use the \s-1CPAN\s0 Request Tracker http://rt.cpan.org/ and submit new bugs under .PP .Vb 1 \& http://rt.cpan.org/Ticket/Create.html?Queue=Expect .Ve .SH "AUTHORS" .IX Header "AUTHORS" (c) 1997 Austin Schutz <\fIASchutz@users.sourceforge.net\fR> (retired) .PP \&\fBexpect()\fR interface & functionality enhancements (c) 1999\-2006 Roland Giersig. .PP This module is now maintained by Dave Jacoby <\fIjacoby@cpan.org\fR> .SH "LICENSE" .IX Header "LICENSE" This module can be used under the same terms as Perl. .SH "DISCLAIMER" .IX Header "DISCLAIMER" \&\s-1THIS SOFTWARE IS PROVIDED\s0 ``\s-1AS IS\s0'' \s-1AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\s0 (\s-1INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES\s0; \s-1LOSS OF USE, DATA, OR PROFITS\s0; \s-1OR BUSINESS INTERRUPTION\s0) \s-1HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\s0 (\s-1INCLUDING NEGLIGENCE OR OTHERWISE\s0) \s-1ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\s0 .PP In other words: Use at your own risk. Provided as is. Your mileage may vary. Read the source, Luke! .PP And finally, just to be sure: .PP Any Use of This Product, in Any Manner Whatsoever, Will Increase the Amount of Disorder in the Universe. Although No Liability Is Implied Herein, the Consumer Is Warned That This Process Will Ultimately Lead to the Heat Death of the Universe. man/man3/JSON::Syck.3pm000044400000017632152462503210010374 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::Syck 3" .TH JSON::Syck 3 "2020-10-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::Syck \- JSON is YAML (but consider using JSON::XS instead!) .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use JSON::Syck; # no exports by default \& \& my $data = JSON::Syck::Load($json); \& my $json = JSON::Syck::Dump($data); \& \& # $file can be an IO object, or a filename \& my $data = JSON::Syck::LoadFile($file); \& JSON::Syck::DumpFile($file, $data); \& \& # Dump into a pre\-existing buffer \& my $json; \& JSON::Syck::DumpInto(\e$json, $data); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" JSON::Syck is a syck implementation of \s-1JSON\s0 parsing and generation. Because \&\s-1JSON\s0 is \s-1YAML\s0 (), using syck gives you a fast and memory-efficient parser and dumper for \s-1JSON\s0 data representation. .PP However, a newer module \s-1JSON::XS\s0, has since emerged. It is more flexible, efficient and robust, so please consider using it instead of this module. .SH "DIFFERENCE WITH JSON" .IX Header "DIFFERENCE WITH JSON" You might want to know the difference between the \fI\s-1JSON\s0\fR module and this one. .PP Since \s-1JSON\s0 is a pure-perl module and JSON::Syck is based on libsyck, JSON::Syck is supposed to be very fast and memory efficient. See chansen's benchmark table at .PP \&\s-1JSON\s0.pm comes with dozens of ways to do the same thing and lots of options, while JSON::Syck doesn't. There's only \f(CW\*(C`Load\*(C'\fR and \f(CW\*(C`Dump\*(C'\fR. .PP Oh, and JSON::Syck doesn't use camelCase method names :\-) .SH "REFERENCES" .IX Header "REFERENCES" .SS "\s-1SCALAR REFERENCE\s0" .IX Subsection "SCALAR REFERENCE" For now, when you pass a scalar reference to JSON::Syck, it dereferences to get the actual scalar value. .PP JSON::Syck raises an exception when you pass in circular references. .PP If you want to serialize self referencing stuff, you should use \&\s-1YAML\s0 which supports it. .SS "\s-1SUBROUTINE REFERENCE\s0" .IX Subsection "SUBROUTINE REFERENCE" When you pass subroutine reference, JSON::Syck dumps it as null. .SH "UTF\-8 FLAGS" .IX Header "UTF-8 FLAGS" By default this module doesn't touch any of utf\-8 flags set in strings, and assumes \s-1UTF\-8\s0 bytes to be passed and emit. .PP However, when you set \f(CW$JSON::Syck::ImplicitUnicode\fR to 1, this module properly decodes \s-1UTF\-8\s0 binaries and sets \s-1UTF\-8\s0 flag everywhere, as in: .PP .Vb 4 \& JSON (UTF\-8 bytes) => Perl (UTF\-8 flagged) \& JSON (UTF\-8 flagged) => Perl (UTF\-8 flagged) \& Perl (UTF\-8 bytes) => JSON (UTF\-8 flagged) \& Perl (UTF\-8 flagged) => JSON (UTF\-8 flagged) .Ve .PP By default, JSON::Syck::Dump will only transverse up to 512 levels of a datastructure in order to avoid an infinite loop when it is presented with an circular reference. .PP However, you set \f(CW$JSON::Syck::MaxLevels\fR to a larger value if you have very complex structures. .PP Unfortunately, there's no implicit way to dump Perl \s-1UTF\-8\s0 flagged data structure to utf\-8 encoded \s-1JSON.\s0 To do this, simply use Encode module, e.g.: .PP .Vb 2 \& use Encode; \& use JSON::Syck qw(Dump); \& \& my $json = encode_utf8( Dump($data) ); .Ve .PP Alternatively you can use Encode::JavaScript::UCS to encode Unicode strings as in \fI\f(CI%uXXXX\fI\fR form. .PP .Vb 3 \& use Encode; \& use Encode::JavaScript::UCS; \& use JSON::Syck qw(Dump); \& \& my $json_unicode_escaped = encode( \*(AqJavaScript\-UCS\*(Aq, Dump($data) ); .Ve .SH "QUOTING" .IX Header "QUOTING" According to the \s-1JSON\s0 specification, all \s-1JSON\s0 strings are to be double-quoted. However, when embedding JavaScript in \s-1HTML\s0 attributes, it may be more convenient to use single quotes. .PP Set \f(CW$JSON::Syck::SingleQuote\fR to 1 will make both \f(CW\*(C`Dump\*(C'\fR and \f(CW\*(C`Load\*(C'\fR expect single-quoted string literals. .SH "BUGS" .IX Header "BUGS" Dumping into tied (or other magic variables) with \f(CW\*(C`DumpInto\*(C'\fR might not work properly in all cases. .PP When dumping with \f(CW\*(C`DumpFile\*(C'\fR, some spacing might be wrong and \&\f(CW$JSON::Syck::SingleQuote\fR might be handled incorrectly. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1JSON::XS\s0, YAML::Syck .SH "AUTHORS" .IX Header "AUTHORS" Audrey Tang .PP Tatsuhiko Miyagawa .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2005\-2009 by Audrey Tang . .PP This software is released under the \s-1MIT\s0 license cited below. .PP The \fIlibsyck\fR code bundled with this library is released by \&\*(L"why the lucky stiff\*(R", under a BSD-style license. See the \fI\s-1COPYING\s0\fR file for details. .ie n .SS "The ""\s-1MIT""\s0 License" .el .SS "The ``\s-1MIT''\s0 License" .IX Subsection "The MIT License" Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \*(L"Software\*(R"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: .PP The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. .PP \&\s-1THE SOFTWARE IS PROVIDED \*(L"AS IS\*(R", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\s0 man/man3/LWP.3pm000044400000063761152462503210007253 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP 3" .TH LWP 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP \- The World\-Wide Web library for Perl .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use LWP; \& print "This is libwww\-perl\-$LWP::VERSION\en"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The libwww-perl collection is a set of Perl modules which provides a simple and consistent application programming interface (\s-1API\s0) to the World-Wide Web. The main focus of the library is to provide classes and functions that allow you to write \s-1WWW\s0 clients. The library also contain modules that are of more general use and even classes that help you implement simple \s-1HTTP\s0 servers. .PP Most modules in this library provide an object oriented \s-1API.\s0 The user agent, requests sent and responses received from the \s-1WWW\s0 server are all represented by objects. This makes a simple and powerful interface to these services. The interface is easy to extend and customize for your own needs. .PP The main features of the library are: .IP "\(bu" 3 Contains various reusable components (modules) that can be used separately or together. .IP "\(bu" 3 Provides an object oriented model of HTTP-style communication. Within this framework we currently support access to \f(CW\*(C`http\*(C'\fR, \f(CW\*(C`https\*(C'\fR, \f(CW\*(C`gopher\*(C'\fR, \&\f(CW\*(C`ftp\*(C'\fR, \f(CW\*(C`news\*(C'\fR, \f(CW\*(C`file\*(C'\fR, and \f(CW\*(C`mailto\*(C'\fR resources. .IP "\(bu" 3 Provides a full object oriented interface or a very simple procedural interface. .IP "\(bu" 3 Supports the basic and digest authorization schemes. .IP "\(bu" 3 Supports transparent redirect handling. .IP "\(bu" 3 Supports access through proxy servers. .IP "\(bu" 3 Provides parser for \fIrobots.txt\fR files and a framework for constructing robots. .IP "\(bu" 3 Supports parsing of \s-1HTML\s0 forms. .IP "\(bu" 3 Implements \s-1HTTP\s0 content negotiation algorithm that can be used both in protocol modules and in server scripts (like \s-1CGI\s0 scripts). .IP "\(bu" 3 Supports \s-1HTTP\s0 cookies. .IP "\(bu" 3 Some simple command line clients, for instance \f(CW\*(C`lwp\-request\*(C'\fR and \f(CW\*(C`lwp\-download\*(C'\fR. .SH "HTTP STYLE COMMUNICATION" .IX Header "HTTP STYLE COMMUNICATION" The libwww-perl library is based on \s-1HTTP\s0 style communication. This section tries to describe what that means. .PP Let us start with this quote from the \s-1HTTP\s0 specification document : .IP "\(bu" 3 The \s-1HTTP\s0 protocol is based on a request/response paradigm. A client establishes a connection with a server and sends a request to the server in the form of a request method, \s-1URI,\s0 and protocol version, followed by a MIME-like message containing request modifiers, client information, and possible body content. The server responds with a status line, including the message's protocol version and a success or error code, followed by a MIME-like message containing server information, entity meta-information, and possible body content. .PP What this means to libwww-perl is that communication always take place through these steps: First a \fIrequest\fR object is created and configured. This object is then passed to a server and we get a \&\fIresponse\fR object in return that we can examine. A request is always independent of any previous requests, i.e. the service is stateless. The same simple model is used for any kind of service we want to access. .PP For example, if we want to fetch a document from a remote file server, then we send it a request that contains a name for that document and the response will contain the document itself. If we access a search engine, then the content of the request will contain the query parameters and the response will contain the query result. If we want to send a mail message to somebody then we send a request object which contains our message to the mail server and the response object will contain an acknowledgment that tells us that the message has been accepted and will be forwarded to the recipient(s). .PP It is as simple as that! .SS "The Request Object" .IX Subsection "The Request Object" The libwww-perl request object has the class name HTTP::Request. The fact that the class name uses \f(CW\*(C`HTTP::\*(C'\fR as a prefix only implies that we use the \s-1HTTP\s0 model of communication. It does not limit the kind of services we can try to pass this \fIrequest\fR to. For instance, we will send HTTP::Requests both to ftp and gopher servers, as well as to the local file system. .PP The main attributes of the request objects are: .IP "\(bu" 3 \&\fBmethod\fR is a short string that tells what kind of request this is. The most common methods are \fB\s-1GET\s0\fR, \fB\s-1PUT\s0\fR, \&\fB\s-1POST\s0\fR and \fB\s-1HEAD\s0\fR. .IP "\(bu" 3 \&\fBuri\fR is a string denoting the protocol, server and the name of the \*(L"document\*(R" we want to access. The \fBuri\fR might also encode various other parameters. .IP "\(bu" 3 \&\fBheaders\fR contains additional information about the request and can also used to describe the content. The headers are a set of keyword/value pairs. .IP "\(bu" 3 \&\fBcontent\fR is an arbitrary amount of data. .SS "The Response Object" .IX Subsection "The Response Object" The libwww-perl response object has the class name HTTP::Response. The main attributes of objects of this class are: .IP "\(bu" 3 \&\fBcode\fR is a numerical value that indicates the overall outcome of the request. .IP "\(bu" 3 \&\fBmessage\fR is a short, human readable string that corresponds to the \fIcode\fR. .IP "\(bu" 3 \&\fBheaders\fR contains additional information about the response and describe the content. .IP "\(bu" 3 \&\fBcontent\fR is an arbitrary amount of data. .PP Since we don't want to handle all possible \fIcode\fR values directly in our programs, a libwww-perl response object has methods that can be used to query what kind of response this is. The most commonly used response classification methods are: .IP "\fBis_success()\fR" 3 .IX Item "is_success()" The request was successfully received, understood or accepted. .IP "\fBis_error()\fR" 3 .IX Item "is_error()" The request failed. The server or the resource might not be available, access to the resource might be denied or other things might have failed for some reason. .SS "The User Agent" .IX Subsection "The User Agent" Let us assume that we have created a \fIrequest\fR object. What do we actually do with it in order to receive a \fIresponse\fR? .PP The answer is that you pass it to a \fIuser agent\fR object and this object takes care of all the things that need to be done (like low-level communication and error handling) and returns a \fIresponse\fR object. The user agent represents your application on the network and provides you with an interface that can accept \fIrequests\fR and return \fIresponses\fR. .PP The user agent is an interface layer between your application code and the network. Through this interface you are able to access the various servers on the network. .PP The class name for the user agent is LWP::UserAgent. Every libwww-perl application that wants to communicate should create at least one object of this class. The main method provided by this object is \fBrequest()\fR. This method takes an HTTP::Request object as argument and (eventually) returns a HTTP::Response object. .PP The user agent has many other attributes that let you configure how it will interact with the network and with your application. .IP "\(bu" 3 \&\fBtimeout\fR specifies how much time we give remote servers to respond before the library disconnects and creates an internal \fItimeout\fR response. .IP "\(bu" 3 \&\fBagent\fR specifies the name that your application uses when it presents itself on the network. .IP "\(bu" 3 \&\fBfrom\fR can be set to the e\-mail address of the person responsible for running the application. If this is set, then the address will be sent to the servers with every request. .IP "\(bu" 3 \&\fBparse_head\fR specifies whether we should initialize response headers from the \f(CW\*(C`\*(C'\fR section of \s-1HTML\s0 documents. .IP "\(bu" 3 \&\fBproxy\fR and \fBno_proxy\fR specify if and when to go through a proxy server. .IP "\(bu" 3 \&\fBcredentials\fR provides a way to set up user names and passwords needed to access certain services. .PP Many applications want even more control over how they interact with the network and they get this by sub-classing LWP::UserAgent. The library includes a sub-class, LWP::RobotUA, for robot applications. .SS "An Example" .IX Subsection "An Example" This example shows how the user agent, a request and a response are represented in actual perl code: .PP .Vb 4 \& # Create a user agent object \& use LWP::UserAgent; \& my $ua = LWP::UserAgent\->new; \& $ua\->agent("MyApp/0.1 "); \& \& # Create a request \& my $req = HTTP::Request\->new(POST => \*(Aqhttp://search.cpan.org/search\*(Aq); \& $req\->content_type(\*(Aqapplication/x\-www\-form\-urlencoded\*(Aq); \& $req\->content(\*(Aqquery=libwww\-perl&mode=dist\*(Aq); \& \& # Pass request to the user agent and get a response back \& my $res = $ua\->request($req); \& \& # Check the outcome of the response \& if ($res\->is_success) { \& print $res\->content; \& } \& else { \& print $res\->status_line, "\en"; \& } .Ve .PP The \f(CW$ua\fR is created once when the application starts up. New request objects should normally created for each request sent. .SH "NETWORK SUPPORT" .IX Header "NETWORK SUPPORT" This section discusses the various protocol schemes and the \s-1HTTP\s0 style methods that headers may be used for each. .PP For all requests, a \*(L"User-Agent\*(R" header is added and initialized from the \f(CW\*(C`$ua\->agent\*(C'\fR attribute before the request is handed to the network layer. In the same way, a \*(L"From\*(R" header is initialized from the \&\f(CW$ua\fR\->from attribute. .PP For all responses, the library adds a header called \*(L"Client-Date\*(R". This header holds the time when the response was received by your application. The format and semantics of the header are the same as the server created \*(L"Date\*(R" header. You may also encounter other \&\*(L"Client-XXX\*(R" headers. They are all generated by the library internally and are not received from the servers. .SS "\s-1HTTP\s0 Requests" .IX Subsection "HTTP Requests" \&\s-1HTTP\s0 requests are just handed off to an \s-1HTTP\s0 server and it decides what happens. Few servers implement methods beside the usual \&\*(L"\s-1GET\*(R", \*(L"HEAD\*(R", \*(L"POST\*(R"\s0 and \*(L"\s-1PUT\*(R",\s0 but CGI-scripts may implement any method they like. .PP If the server is not available then the library will generate an internal error response. .PP The library automatically adds a \*(L"Host\*(R" and a \*(L"Content-Length\*(R" header to the \s-1HTTP\s0 request before it is sent over the network. .PP For a \s-1GET\s0 request you might want to add a \*(L"If-Modified-Since\*(R" or \&\*(L"If-None-Match\*(R" header to make the request conditional. .PP For a \s-1POST\s0 request you should add the \*(L"Content-Type\*(R" header. When you try to emulate \s-1HTML\s0 <\s-1FORM\s0> handling you should usually let the value of the \*(L"Content-Type\*(R" header be \*(L"application/x\-www\-form\-urlencoded\*(R". See lwpcook for examples of this. .PP The libwww-perl \s-1HTTP\s0 implementation currently support the \s-1HTTP/1.1\s0 and \s-1HTTP/1.0\s0 protocol. .PP The library allows you to access proxy server through \s-1HTTP.\s0 This means that you can set up the library to forward all types of request through the \s-1HTTP\s0 protocol module. See LWP::UserAgent for documentation of this. .SS "\s-1HTTPS\s0 Requests" .IX Subsection "HTTPS Requests" \&\s-1HTTPS\s0 requests are \s-1HTTP\s0 requests over an encrypted network connection using the \s-1SSL\s0 protocol developed by Netscape. Everything about \s-1HTTP\s0 requests above also apply to \s-1HTTPS\s0 requests. In addition the library will add the headers \*(L"Client-SSL-Cipher\*(R", \*(L"Client-SSL-Cert-Subject\*(R" and \&\*(L"Client-SSL-Cert-Issuer\*(R" to the response. These headers denote the encryption method used and the name of the server owner. .PP The request can contain the header \*(L"If-SSL-Cert-Subject\*(R" in order to make the request conditional on the content of the server certificate. If the certificate subject does not match, no request is sent to the server and an internally generated error response is returned. The value of the \*(L"If-SSL-Cert-Subject\*(R" header is interpreted as a Perl regular expression. .SS "\s-1FTP\s0 Requests" .IX Subsection "FTP Requests" The library currently supports \s-1GET, HEAD\s0 and \s-1PUT\s0 requests. \s-1GET\s0 retrieves a file or a directory listing from an \s-1FTP\s0 server. \s-1PUT\s0 stores a file on a ftp server. .PP You can specify a ftp account for servers that want this in addition to user name and password. This is specified by including an \*(L"Account\*(R" header in the request. .PP User name/password can be specified using basic authorization or be encoded in the \s-1URL.\s0 Failed logins return an \s-1UNAUTHORIZED\s0 response with \&\*(L"WWW-Authenticate: Basic\*(R" and can be treated like basic authorization for \s-1HTTP.\s0 .PP The library supports ftp \s-1ASCII\s0 transfer mode by specifying the \*(L"type=a\*(R" parameter in the \s-1URL.\s0 It also supports transfer of ranges for \s-1FTP\s0 transfers using the \*(L"Range\*(R" header. .PP Directory listings are by default returned unprocessed (as returned from the ftp server) with the content media type reported to be \&\*(L"text/ftp\-dir\-listing\*(R". The File::Listing module provides methods for parsing of these directory listing. .PP The ftp module is also able to convert directory listings to \s-1HTML\s0 and this can be requested via the standard \s-1HTTP\s0 content negotiation mechanisms (add an \*(L"Accept: text/html\*(R" header in the request if you want this). .PP For normal file retrievals, the \*(L"Content-Type\*(R" is guessed based on the file name suffix. See LWP::MediaTypes. .PP The \*(L"If-Modified-Since\*(R" request header works for servers that implement the \f(CW\*(C`MDTM\*(C'\fR command. It will probably not work for directory listings though. .PP Example: .PP .Vb 2 \& $req = HTTP::Request\->new(GET => \*(Aqftp://me:passwd@ftp.some.where.com/\*(Aq); \& $req\->header(Accept => "text/html, */*;q=0.1"); .Ve .SS "News Requests" .IX Subsection "News Requests" Access to the \s-1USENET\s0 News system is implemented through the \s-1NNTP\s0 protocol. The name of the news server is obtained from the \&\s-1NNTP_SERVER\s0 environment variable and defaults to \*(L"news\*(R". It is not possible to specify the hostname of the \s-1NNTP\s0 server in news: URLs. .PP The library supports \s-1GET\s0 and \s-1HEAD\s0 to retrieve news articles through the \&\s-1NNTP\s0 protocol. You can also post articles to newsgroups by using (surprise!) the \s-1POST\s0 method. .PP \&\s-1GET\s0 on newsgroups is not implemented yet. .PP Examples: .PP .Vb 1 \& $req = HTTP::Request\->new(GET => \*(Aqnews:abc1234@a.sn.no\*(Aq); \& \& $req = HTTP::Request\->new(POST => \*(Aqnews:comp.lang.perl.test\*(Aq); \& $req\->header(Subject => \*(AqThis is a test\*(Aq, \& From => \*(Aqme@some.where.org\*(Aq); \& $req\->content(<new(GET => \*(Aqgopher://gopher.sn.no/\*(Aq); .Ve .SS "File Request" .IX Subsection "File Request" The library supports \s-1GET\s0 and \s-1HEAD\s0 methods for file requests. The \&\*(L"If-Modified-Since\*(R" header is supported. All other headers are ignored. The \fIhost\fR component of the file \s-1URL\s0 must be empty or set to \*(L"localhost\*(R". Any other \fIhost\fR value will be treated as an error. .PP Directories are always converted to an \s-1HTML\s0 document. For normal files, the \*(L"Content-Type\*(R" and \*(L"Content-Encoding\*(R" in the response are guessed based on the file suffix. .PP Example: .PP .Vb 1 \& $req = HTTP::Request\->new(GET => \*(Aqfile:/etc/passwd\*(Aq); .Ve .SS "Mailto Request" .IX Subsection "Mailto Request" You can send (aka \*(L"\s-1POST\*(R"\s0) mail messages using the library. All headers specified for the request are passed on to the mail system. The \*(L"To\*(R" header is initialized from the mail address in the \s-1URL.\s0 .PP Example: .PP .Vb 3 \& $req = HTTP::Request\->new(POST => \*(Aqmailto:libwww@perl.org\*(Aq); \& $req\->header(Subject => "subscribe"); \& $req\->content("Please subscribe me to the libwww\-perl mailing list!\en"); .Ve .SS "\s-1CPAN\s0 Requests" .IX Subsection "CPAN Requests" URLs with scheme \f(CW\*(C`cpan:\*(C'\fR are redirected to a suitable \s-1CPAN\s0 mirror. If you have your own local mirror of \s-1CPAN\s0 you might tell \s-1LWP\s0 to use it for \f(CW\*(C`cpan:\*(C'\fR URLs by an assignment like this: .PP .Vb 1 \& $LWP::Protocol::cpan::CPAN = "file:/local/CPAN/"; .Ve .PP Suitable \s-1CPAN\s0 mirrors are also picked up from the configuration for the \s-1CPAN\s0.pm, so if you have used that module a suitable mirror should be picked automatically. If neither of these apply, then a redirect to the generic \s-1CPAN\s0 http location is issued. .PP Example request to download the newest perl: .PP .Vb 1 \& $req = HTTP::Request\->new(GET => "cpan:src/latest.tar.gz"); .Ve .SH "OVERVIEW OF CLASSES AND PACKAGES" .IX Header "OVERVIEW OF CLASSES AND PACKAGES" This table should give you a quick overview of the classes provided by the library. Indentation shows class inheritance. .PP .Vb 8 \& LWP::MemberMixin \-\- Access to member variables of Perl5 classes \& LWP::UserAgent \-\- WWW user agent class \& LWP::RobotUA \-\- When developing a robot applications \& LWP::Protocol \-\- Interface to various protocol schemes \& LWP::Protocol::http \-\- http:// access \& LWP::Protocol::file \-\- file:// access \& LWP::Protocol::ftp \-\- ftp:// access \& ... \& \& LWP::Authen::Basic \-\- Handle 401 and 407 responses \& LWP::Authen::Digest \& \& HTTP::Headers \-\- MIME/RFC822 style header (used by HTTP::Message) \& HTTP::Message \-\- HTTP style message \& HTTP::Request \-\- HTTP request \& HTTP::Response \-\- HTTP response \& HTTP::Daemon \-\- A HTTP server class \& \& WWW::RobotRules \-\- Parse robots.txt files \& WWW::RobotRules::AnyDBM_File \-\- Persistent RobotRules \& \& Net::HTTP \-\- Low level HTTP client .Ve .PP The following modules provide various functions and definitions. .PP .Vb 8 \& LWP \-\- This file. Library version number and documentation. \& LWP::MediaTypes \-\- MIME types configuration (text/html etc.) \& LWP::Simple \-\- Simplified procedural interface for common functions \& HTTP::Status \-\- HTTP status code (200 OK etc) \& HTTP::Date \-\- Date parsing module for HTTP date formats \& HTTP::Negotiate \-\- HTTP content negotiation calculation \& File::Listing \-\- Parse directory listings \& HTML::Form \-\- Processing for s in HTML documents .Ve .SH "MORE DOCUMENTATION" .IX Header "MORE DOCUMENTATION" All modules contain detailed information on the interfaces they provide. The lwpcook manpage is the libwww-perl cookbook that contain examples of typical usage of the library. You might want to take a look at how the scripts lwp-request, lwp-download, lwp-dump and lwp-mirror are implemented. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" The following environment variables are used by \s-1LWP:\s0 .IP "\s-1HOME\s0" 4 .IX Item "HOME" The LWP::MediaTypes functions will look for the \fI.media.types\fR and \&\fI.mime.types\fR files relative to you home directory. .IP "http_proxy" 4 .IX Item "http_proxy" .PD 0 .IP "ftp_proxy" 4 .IX Item "ftp_proxy" .IP "xxx_proxy" 4 .IX Item "xxx_proxy" .IP "no_proxy" 4 .IX Item "no_proxy" .PD These environment variables can be set to enable communication through a proxy server. See the description of the \f(CW\*(C`env_proxy\*(C'\fR method in LWP::UserAgent. .IP "\s-1PERL_LWP_ENV_PROXY\s0" 4 .IX Item "PERL_LWP_ENV_PROXY" If set to a \s-1TRUE\s0 value, then the LWP::UserAgent will by default call \&\f(CW\*(C`env_proxy\*(C'\fR during initialization. This makes \s-1LWP\s0 honor the proxy variables described above. .IP "\s-1PERL_LWP_SSL_VERIFY_HOSTNAME\s0" 4 .IX Item "PERL_LWP_SSL_VERIFY_HOSTNAME" The default \f(CW\*(C`verify_hostname\*(C'\fR setting for LWP::UserAgent. If not set the default will be 1. Set it as 0 to disable hostname verification (the default prior to libwww-perl 5.840. .IP "\s-1PERL_LWP_SSL_CA_FILE\s0" 4 .IX Item "PERL_LWP_SSL_CA_FILE" .PD 0 .IP "\s-1PERL_LWP_SSL_CA_PATH\s0" 4 .IX Item "PERL_LWP_SSL_CA_PATH" .PD The file and/or directory where the trusted Certificate Authority certificates is located. See LWP::UserAgent for details. .IP "\s-1PERL_HTTP_URI_CLASS\s0" 4 .IX Item "PERL_HTTP_URI_CLASS" Used to decide what \s-1URI\s0 objects to instantiate. The default is \s-1URI\s0. You might want to set it to \s-1URI::URL\s0 for compatibility with old times. .SH "AUTHORS" .IX Header "AUTHORS" \&\s-1LWP\s0 was made possible by contributions from Adam Newby, Albert Dvornik, Alexandre Duret-Lutz, Andreas Gustafsson, Andreas König, Andrew Pimlott, Andy Lester, Ben Coleman, Benjamin Low, Ben Low, Ben Tilly, Blair Zajac, Bob Dalgleish, BooK, Brad Hughes, Brian J. Murrell, Brian McCauley, Charles C. Fu, Charles Lane, Chris Nandor, Christian Gilmore, Chris W. Unger, Craig Macdonald, Dale Couch, Dan Kubb, Dave Dunkin, Dave W. Smith, David Coppit, David Dick, David D. Kilzer, Doug MacEachern, Edward Avis, erik, Gary Shea, Gisle Aas, Graham Barr, Gurusamy Sarathy, Hans de Graaff, Harald Joerg, Harry Bochner, Hugo, Ilya Zakharevich, \s-1INOUE\s0 Yoshinari, Ivan Panchenko, Jack Shirazi, James Tillman, Jan Dubois, Jared Rhine, Jim Stern, Joao Lopes, John Klar, Johnny Lee, Josh Kronengold, Josh Rai, Joshua Chamas, Joshua Hoblitt, Kartik Subbarao, Keiichiro Nagano, Ken Williams, \s-1KONISHI\s0 Katsuhiro, Lee T Lindley, Liam Quinn, Marc Hedlund, Marc Langheinrich, Mark D. Anderson, Marko Asplund, Mark Stosberg, Markus B Krüger, Markus Laker, Martijn Koster, Martin Thurn, Matthew Eldridge, Matthew.van.Eerde, Matt Sergeant, Michael A. Chase, Michael Quaranta, Michael Thompson, Mike Schilli, Moshe Kaminsky, Nathan Torkington, Nicolai Langfeldt, Norton Allen, Olly Betts, Paul J. Schinder, peterm, Philip Guenther, Daniel Buenzli, Pon Hwa Lin, Radoslaw Zielinski, Radu Greab, Randal L. Schwartz, Richard Chen, Robin Barker, Roy Fielding, Sander van Zoest, Sean M. Burke, shildreth, Slaven Rezic, Steve A Fink, Steve Hay, Steven Butler, Steve_Kilbane, Takanori Ugai, Thomas Lotterer, Tim Bunce, Tom Hughes, Tony Finch, Ville Skyttä, Ward Vandewege, William York, Yale Huang, and Yitzchak Scott-Thoennes. .PP \&\s-1LWP\s0 owes a lot in motivation, design, and code, to the libwww-perl library for Perl4 by Roy Fielding, which included work from Alberto Accomazzi, James Casey, Brooks Cutter, Martijn Koster, Oscar Nierstrasz, Mel Melchner, Gertjan van Oosten, Jared Rhine, Jack Shirazi, Gene Spafford, Marc VanHeyningen, Steven E. Brenner, Marion Hakanson, Waldemar Kebsch, Tony Sanders, and Larry Wall; see the libwww\-perl\-0.40 library for details. .SH "COPYRIGHT" .IX Header "COPYRIGHT" .Vb 2 \& Copyright 1995\-2009, Gisle Aas \& Copyright 1995, Martijn Koster .Ve .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "AVAILABILITY" .IX Header "AVAILABILITY" The latest version of this library is likely to be available from \s-1CPAN\s0 as well as: .PP .Vb 1 \& http://github.com/libwww\-perl/libwww\-perl .Ve .PP The best place to discuss this code is on the mailing list. man/man3/JSON::backportPP::Compat5005.3pm000044400000005204152462503210013362 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::backportPP::Compat5005 3" .TH JSON::backportPP::Compat5005 3 "2021-01-17" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::PP5005 \- Helper module in using JSON::PP in Perl 5.005 .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1JSON::PP\s0 calls internally. .SH "AUTHOR" .IX Header "AUTHOR" Makamaka Hannyaharamitu, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2007\-2012 by Makamaka Hannyaharamitu .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::Gofer::Transport::Base.3pm000044400000005445152462503210013431 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Transport::Base 3" .TH DBI::Gofer::Transport::Base 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Transport::Base \- Base class for Gofer transports .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is the base class for server-side Gofer transports. .PP It's also the base class for the client-side base class DBD::Gofer::Transport::Base. .PP This is an internal class. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/DBI.3pm000044400001105370152462503210007201 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI 3" .TH DBI 3 "2020-01-31" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI \- Database independent interface for Perl .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use DBI; \& \& @driver_names = DBI\->available_drivers; \& %drivers = DBI\->installed_drivers; \& @data_sources = DBI\->data_sources($driver_name, \e%attr); \& \& $dbh = DBI\->connect($data_source, $username, $auth, \e%attr); \& \& $rv = $dbh\->do($statement); \& $rv = $dbh\->do($statement, \e%attr); \& $rv = $dbh\->do($statement, \e%attr, @bind_values); \& \& $ary_ref = $dbh\->selectall_arrayref($statement); \& $hash_ref = $dbh\->selectall_hashref($statement, $key_field); \& \& $ary_ref = $dbh\->selectcol_arrayref($statement); \& $ary_ref = $dbh\->selectcol_arrayref($statement, \e%attr); \& \& @row_ary = $dbh\->selectrow_array($statement); \& $ary_ref = $dbh\->selectrow_arrayref($statement); \& $hash_ref = $dbh\->selectrow_hashref($statement); \& \& $sth = $dbh\->prepare($statement); \& $sth = $dbh\->prepare_cached($statement); \& \& $rc = $sth\->bind_param($p_num, $bind_value); \& $rc = $sth\->bind_param($p_num, $bind_value, $bind_type); \& $rc = $sth\->bind_param($p_num, $bind_value, \e%attr); \& \& $rv = $sth\->execute; \& $rv = $sth\->execute(@bind_values); \& $rv = $sth\->execute_array(\e%attr, ...); \& \& $rc = $sth\->bind_col($col_num, \e$col_variable); \& $rc = $sth\->bind_columns(@list_of_refs_to_vars_to_bind); \& \& @row_ary = $sth\->fetchrow_array; \& $ary_ref = $sth\->fetchrow_arrayref; \& $hash_ref = $sth\->fetchrow_hashref; \& \& $ary_ref = $sth\->fetchall_arrayref; \& $ary_ref = $sth\->fetchall_arrayref( $slice, $max_rows ); \& \& $hash_ref = $sth\->fetchall_hashref( $key_field ); \& \& $rv = $sth\->rows; \& \& $rc = $dbh\->begin_work; \& $rc = $dbh\->commit; \& $rc = $dbh\->rollback; \& \& $quoted_string = $dbh\->quote($string); \& \& $rc = $h\->err; \& $str = $h\->errstr; \& $rv = $h\->state; \& \& $rc = $dbh\->disconnect; .Ve .PP \&\fIThe synopsis above only lists the major methods and parameters.\fR .SS "\s-1GETTING HELP\s0" .IX Subsection "GETTING HELP" \fIGeneral\fR .IX Subsection "General" .PP Before asking any questions, reread this document, consult the archives and read the \s-1DBI FAQ.\s0 The archives are listed at the end of this document and on the \s-1DBI\s0 home page .PP You might also like to read the Advanced \s-1DBI\s0 Tutorial at .PP To help you make the best use of the dbi-users mailing list, and any other lists or forums you may use, I recommend that you read \&\*(L"Getting Answers\*(R" by Mike Ash: . .PP \fIMailing Lists\fR .IX Subsection "Mailing Lists" .PP If you have questions about \s-1DBI,\s0 or \s-1DBD\s0 driver modules, you can get help from the \fIdbi\-users@perl.org\fR mailing list. This is the best way to get help. You don't have to subscribe to the list in order to post, though I'd recommend it. You can get help on subscribing and using the list by emailing \&\fIdbi\-users\-help@perl.org\fR. .PP Please note that Tim Bunce does not maintain the mailing lists or the web pages (generous volunteers do that). So please don't send mail directly to him; he just doesn't have the time to answer questions personally. The \fIdbi-users\fR mailing list has lots of experienced people who should be able to help you if you need it. If you do email Tim he is very likely to just forward it to the mailing list. .PP \fI\s-1IRC\s0\fR .IX Subsection "IRC" .PP \&\s-1DBI IRC\s0 Channel: #dbi on irc.perl.org () .PP \fIOnline\fR .IX Subsection "Online" .PP StackOverflow has a \s-1DBI\s0 tag with over 800 questions. .PP The \s-1DBI\s0 home page at and the \s-1DBI FAQ\s0 at may be worth a visit. They include links to other resources, but \fIare rather out-dated\fR. .PP \fIReporting a Bug\fR .IX Subsection "Reporting a Bug" .PP If you think you've found a bug then please read \&\*(L"How to Report Bugs Effectively\*(R" by Simon Tatham: . .PP If you think you've found a memory leak then read \*(L"Memory Leaks\*(R". .PP Your problem is most likely related to the specific \s-1DBD\s0 driver module you're using. If that's the case then click on the 'Bugs' link on the page for your driver. Only submit a bug report against the \s-1DBI\s0 itself if you're sure that your issue isn't related to the driver you're using. .SS "\s-1NOTES\s0" .IX Subsection "NOTES" This is the \s-1DBI\s0 specification that corresponds to \s-1DBI\s0 version 1.642 (see DBI::Changes for details). .PP The \s-1DBI\s0 is evolving at a steady pace, so it's good to check that you have the latest copy. .PP The significant user-visible changes in each release are documented in the DBI::Changes module so you can read them by executing \&\f(CW\*(C`perldoc DBI::Changes\*(C'\fR. .PP Some \s-1DBI\s0 changes require changes in the drivers, but the drivers can take some time to catch up. Newer versions of the \s-1DBI\s0 have added features that may not yet be supported by the drivers you use. Talk to the authors of your drivers if you need a new feature that is not yet supported. .PP Features added after \s-1DBI 1.21\s0 (February 2002) are marked in the text with the version number of the \s-1DBI\s0 release they first appeared in. .PP Extensions to the \s-1DBI API\s0 often use the \f(CW\*(C`DBIx::*\*(C'\fR namespace. See \*(L"Naming Conventions and Name Space\*(R". \s-1DBI\s0 extension modules can be found at . And all modules related to the \s-1DBI\s0 can be found at . .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \s-1DBI\s0 is a database access module for the Perl programming language. It defines a set of methods, variables, and conventions that provide a consistent database interface, independent of the actual database being used. .PP It is important to remember that the \s-1DBI\s0 is just an interface. The \s-1DBI\s0 is a layer of \*(L"glue\*(R" between an application and one or more database \fIdriver\fR modules. It is the driver modules which do most of the real work. The \s-1DBI\s0 provides a standard interface and framework for the drivers to operate within. .PP This document often uses terms like \fIreferences\fR, \fIobjects\fR, \&\fImethods\fR. If you're not familiar with those terms then it would be a good idea to read at least the following perl manuals first: perlreftut, perldsc, perllol, and perlboot. .SS "Architecture of a \s-1DBI\s0 Application" .IX Subsection "Architecture of a DBI Application" .Vb 11 \& |<\- Scope of DBI \->| \& .\-. .\-\-\-\-\-\-\-\-\-\-\-\-\-\-. .\-\-\-\-\-\-\-\-\-\-\-\-\-. \& .\-\-\-\-\-\-\-. | |\-\-\-| XYZ Driver |\-\-\-| XYZ Engine | \& | Perl | | | \`\-\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq \`\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq \& | script| |A| |D| .\-\-\-\-\-\-\-\-\-\-\-\-\-\-. .\-\-\-\-\-\-\-\-\-\-\-\-\-. \& | using |\-\-|P|\-\-|B|\-\-\-|Oracle Driver |\-\-\-|Oracle Engine| \& | DBI | |I| |I| \`\-\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq \`\-\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq \& | API | | |... \& |methods| | |... Other drivers \& \`\-\-\-\-\-\-\-\*(Aq | |... \& \`\-\*(Aq .Ve .PP The \s-1API,\s0 or Application Programming Interface, defines the call interface and variables for Perl scripts to use. The \s-1API\s0 is implemented by the Perl \s-1DBI\s0 extension. .PP The \s-1DBI\s0 \*(L"dispatches\*(R" the method calls to the appropriate driver for actual execution. The \s-1DBI\s0 is also responsible for the dynamic loading of drivers, error checking and handling, providing default implementations for methods, and many other non-database specific duties. .PP Each driver contains implementations of the \s-1DBI\s0 methods using the private interface functions of the corresponding database engine. Only authors of sophisticated/multi\-database applications or generic library functions need be concerned with drivers. .SS "Notation and Conventions" .IX Subsection "Notation and Conventions" The following conventions are used in this document: .PP .Vb 11 \& $dbh Database handle object \& $sth Statement handle object \& $drh Driver handle object (rarely seen or used in applications) \& $h Any of the handle types above ($dbh, $sth, or $drh) \& $rc General Return Code (boolean: true=ok, false=error) \& $rv General Return Value (typically an integer) \& @ary List of values returned from the database, typically a row of data \& $rows Number of rows processed (if available, else \-1) \& $fh A filehandle \& undef NULL values are represented by undefined values in Perl \& \e%attr Reference to a hash of attribute values passed to methods .Ve .PP Note that Perl will automatically destroy database and statement handle objects if all references to them are deleted. .SS "Outline Usage" .IX Subsection "Outline Usage" To use \s-1DBI,\s0 first you need to load the \s-1DBI\s0 module: .PP .Vb 2 \& use DBI; \& use strict; .Ve .PP (The \f(CW\*(C`use strict;\*(C'\fR isn't required but is strongly recommended.) .PP Then you need to \*(L"connect\*(R" to your data source and get a \fIhandle\fR for that connection: .PP .Vb 2 \& $dbh = DBI\->connect($dsn, $user, $password, \& { RaiseError => 1, AutoCommit => 0 }); .Ve .PP Since connecting can be expensive, you generally just connect at the start of your program and disconnect at the end. .PP Explicitly defining the required \f(CW\*(C`AutoCommit\*(C'\fR behaviour is strongly recommended and may become mandatory in a later version. This determines whether changes are automatically committed to the database when executed, or need to be explicitly committed later. .PP The \s-1DBI\s0 allows an application to \*(L"prepare\*(R" statements for later execution. A prepared statement is identified by a statement handle held in a Perl variable. We'll call the Perl variable \f(CW$sth\fR in our examples. .PP The typical method call sequence for a \f(CW\*(C`SELECT\*(C'\fR statement is: .PP .Vb 4 \& prepare, \& execute, fetch, fetch, ... \& execute, fetch, fetch, ... \& execute, fetch, fetch, ... .Ve .PP for example: .PP .Vb 1 \& $sth = $dbh\->prepare("SELECT foo, bar FROM table WHERE baz=?"); \& \& $sth\->execute( $baz ); \& \& while ( @row = $sth\->fetchrow_array ) { \& print "@row\en"; \& } .Ve .PP For queries that are not executed many times at once, it is often cleaner to use the higher level select wrappers: .PP .Vb 1 \& $row_hashref = $dbh\->selectrow_hashref("SELECT foo, bar FROM table WHERE baz=?", undef, $baz); \& \& $arrayref_of_row_hashrefs = $dbh\->selectall_arrayref( \& "SELECT foo, bar FROM table WHERE baz BETWEEN ? AND ?", \& { Slice => {} }, $baz_min, $baz_max); .Ve .PP The typical method call sequence for a \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statement is: .PP .Vb 4 \& prepare, \& execute, \& execute, \& execute. .Ve .PP for example: .PP .Vb 1 \& $sth = $dbh\->prepare("INSERT INTO table(foo,bar,baz) VALUES (?,?,?)"); \& \& while() { \& chomp; \& my ($foo,$bar,$baz) = split /,/; \& $sth\->execute( $foo, $bar, $baz ); \& } .Ve .PP The \f(CW\*(C`do()\*(C'\fR method is a wrapper of prepare and execute that can be simpler for non repeated \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statements (or with drivers that don't support placeholders): .PP .Vb 1 \& $rows_affected = $dbh\->do("UPDATE your_table SET foo = foo + 1"); \& \& $rows_affected = $dbh\->do("DELETE FROM table WHERE foo = ?", undef, $foo); .Ve .PP To commit your changes to the database (when \*(L"AutoCommit\*(R" is off): .PP .Vb 1 \& $dbh\->commit; # or call $dbh\->rollback; to undo changes .Ve .PP Finally, when you have finished working with the data source, you should \&\*(L"disconnect\*(R" from it: .PP .Vb 1 \& $dbh\->disconnect; .Ve .SS "General Interface Rules & Caveats" .IX Subsection "General Interface Rules & Caveats" The \s-1DBI\s0 does not have a concept of a \*(L"current session\*(R". Every session has a handle object (i.e., a \f(CW$dbh\fR) returned from the \f(CW\*(C`connect\*(C'\fR method. That handle object is used to invoke database related methods. .PP Most data is returned to the Perl script as strings. (Null values are returned as \f(CW\*(C`undef\*(C'\fR.) This allows arbitrary precision numeric data to be handled without loss of accuracy. Beware that Perl may not preserve the same accuracy when the string is used as a number. .PP Dates and times are returned as character strings in the current default format of the corresponding database engine. Time zone effects are database/driver dependent. .PP Perl supports binary data in Perl strings, and the \s-1DBI\s0 will pass binary data to and from the driver without change. It is up to the driver implementors to decide how they wish to handle such binary data. .PP Perl supports two kinds of strings: Unicode (utf8 internally) and non-Unicode (defaults to iso\-8859\-1 if forced to assume an encoding). Drivers should accept both kinds of strings and, if required, convert them to the character set of the database being used. Similarly, when fetching from the database character data that isn't iso\-8859\-1 the driver should convert it into utf8. .PP Multiple \s-1SQL\s0 statements may not be combined in a single statement handle (\f(CW$sth\fR), although some databases and drivers do support this (notably Sybase and \s-1SQL\s0 Server). .PP Non-sequential record reads are not supported in this version of the \s-1DBI.\s0 In other words, records can only be fetched in the order that the database returned them, and once fetched they are forgotten. .PP Positioned updates and deletes are not directly supported by the \s-1DBI.\s0 See the description of the \f(CW\*(C`CursorName\*(C'\fR attribute for an alternative. .PP Individual driver implementors are free to provide any private functions and/or handle attributes that they feel are useful. Private driver functions can be invoked using the \s-1DBI\s0 \f(CW\*(C`func()\*(C'\fR method. Private driver attributes are accessed just like standard attributes. .PP Many methods have an optional \f(CW\*(C`\e%attr\*(C'\fR parameter which can be used to pass information to the driver implementing the method. Except where specifically documented, the \f(CW\*(C`\e%attr\*(C'\fR parameter can only be used to pass driver specific hints. In general, you can ignore \f(CW\*(C`\e%attr\*(C'\fR parameters or pass it as \f(CW\*(C`undef\*(C'\fR. .SS "Naming Conventions and Name Space" .IX Subsection "Naming Conventions and Name Space" The \s-1DBI\s0 package and all packages below it (\f(CW\*(C`DBI::*\*(C'\fR) are reserved for use by the \s-1DBI.\s0 Extensions and related modules use the \f(CW\*(C`DBIx::\*(C'\fR namespace (see ). Package names beginning with \f(CW\*(C`DBD::\*(C'\fR are reserved for use by \s-1DBI\s0 database drivers. All environment variables used by the \s-1DBI\s0 or by individual DBDs begin with "\f(CW\*(C`DBI_\*(C'\fR\*(L" or \*(R"\f(CW\*(C`DBD_\*(C'\fR". .PP The letter case used for attribute names is significant and plays an important part in the portability of \s-1DBI\s0 scripts. The case of the attribute name is used to signify who defined the meaning of that name and its values. .PP .Vb 5 \& Case of name Has a meaning defined by \& \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& UPPER_CASE Standards, e.g., X/Open, ISO SQL92 etc (portable) \& MixedCase DBI API (portable), underscores are not used. \& lower_case Driver or database engine specific (non\-portable) .Ve .PP It is of the utmost importance that Driver developers only use lowercase attribute names when defining private attributes. Private attribute names must be prefixed with the driver name or suitable abbreviation (e.g., "\f(CW\*(C`ora_\*(C'\fR\*(L" for Oracle, \*(R"\f(CW\*(C`ing_\*(C'\fR" for Ingres, etc). .SS "\s-1SQL\s0 \- A Query Language" .IX Subsection "SQL - A Query Language" Most \s-1DBI\s0 drivers require applications to use a dialect of \s-1SQL\s0 (Structured Query Language) to interact with the database engine. The \*(L"Standards Reference Information\*(R" section provides links to useful information about \s-1SQL.\s0 .PP The \s-1DBI\s0 itself does not mandate or require any particular language to be used; it is language independent. In \s-1ODBC\s0 terms, the \s-1DBI\s0 is in \&\*(L"pass-thru\*(R" mode, although individual drivers might not be. The only requirement is that queries and other statements must be expressed as a single string of characters passed as the first argument to the \*(L"prepare\*(R" or \&\*(L"do\*(R" methods. .PP For an interesting diversion on the \fIreal\fR history of \s-1RDBMS\s0 and \s-1SQL,\s0 from the people who made it happen, see: .PP .Vb 1 \& http://www.mcjones.org/System_R/SQL_Reunion_95/sqlr95.html .Ve .PP Follow the \*(L"Full Contents\*(R" then \*(L"Intergalactic dataspeak\*(R" links for the \&\s-1SQL\s0 history. .SS "Placeholders and Bind Values" .IX Subsection "Placeholders and Bind Values" Some drivers support placeholders and bind values. \&\fIPlaceholders\fR, also called parameter markers, are used to indicate values in a database statement that will be supplied later, before the prepared statement is executed. For example, an application might use the following to insert a row of data into the \s-1SALES\s0 table: .PP .Vb 1 \& INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) .Ve .PP or the following, to select the description for a product: .PP .Vb 1 \& SELECT description FROM products WHERE product_code = ? .Ve .PP The \f(CW\*(C`?\*(C'\fR characters are the placeholders. The association of actual values with placeholders is known as \fIbinding\fR, and the values are referred to as \fIbind values\fR. Note that the \f(CW\*(C`?\*(C'\fR is not enclosed in quotation marks, even when the placeholder represents a string. .PP Some drivers also allow placeholders like \f(CW\*(C`:\*(C'\fR\fIname\fR and \f(CW\*(C`:\*(C'\fR\fIN\fR (e.g., \&\f(CW\*(C`:1\*(C'\fR, \f(CW\*(C`:2\*(C'\fR, and so on) in addition to \f(CW\*(C`?\*(C'\fR, but their use is not portable. .PP If the \f(CW\*(C`:\*(C'\fR\fIN\fR form of placeholder is supported by the driver you're using, then you should be able to use either \*(L"bind_param\*(R" or \*(L"execute\*(R" to bind values. Check your driver documentation. .PP Some drivers allow you to prevent the recognition of a placeholder by placing a single backslash character (\f(CW\*(C`\e\*(C'\fR) immediately before it. The driver will remove the backslash character and ignore the placeholder, passing it unchanged to the backend. If the driver supports this then \*(L"get_info\*(R"(9000) will return true. .PP With most drivers, placeholders can't be used for any element of a statement that would prevent the database server from validating the statement and creating a query execution plan for it. For example: .PP .Vb 2 \& "SELECT name, age FROM ?" # wrong (will probably fail) \& "SELECT name, ? FROM people" # wrong (but may not \*(Aqfail\*(Aq) .Ve .PP Also, placeholders can only represent single scalar values. For example, the following statement won't work as expected for more than one value: .PP .Vb 2 \& "SELECT name, age FROM people WHERE name IN (?)" # wrong \& "SELECT name, age FROM people WHERE name IN (?,?)" # two names .Ve .PP When using placeholders with the \s-1SQL\s0 \f(CW\*(C`LIKE\*(C'\fR qualifier, you must remember that the placeholder substitutes for the whole string. So you should use "\f(CW\*(C`... LIKE ? ...\*(C'\fR" and include any wildcard characters in the value that you bind to the placeholder. .PP \&\fB\s-1NULL\s0 Values\fR .PP Undefined values, or \f(CW\*(C`undef\*(C'\fR, are used to indicate \s-1NULL\s0 values. You can insert and update columns with a \s-1NULL\s0 value as you would a non-NULL value. These examples insert and update the column \&\f(CW\*(C`age\*(C'\fR with a \s-1NULL\s0 value: .PP .Vb 4 \& $sth = $dbh\->prepare(qq{ \& INSERT INTO people (fullname, age) VALUES (?, ?) \& }); \& $sth\->execute("Joe Bloggs", undef); \& \& $sth = $dbh\->prepare(qq{ \& UPDATE people SET age = ? WHERE fullname = ? \& }); \& $sth\->execute(undef, "Joe Bloggs"); .Ve .PP However, care must be taken when trying to use \s-1NULL\s0 values in a \&\f(CW\*(C`WHERE\*(C'\fR clause. Consider: .PP .Vb 1 \& SELECT fullname FROM people WHERE age = ? .Ve .PP Binding an \f(CW\*(C`undef\*(C'\fR (\s-1NULL\s0) to the placeholder will \fInot\fR select rows which have a \s-1NULL\s0 \f(CW\*(C`age\*(C'\fR! At least for database engines that conform to the \s-1SQL\s0 standard. Refer to the \s-1SQL\s0 manual for your database engine or any \s-1SQL\s0 book for the reasons for this. To explicitly select NULLs you have to say "\f(CW\*(C`WHERE age IS NULL\*(C'\fR". .PP A common issue is to have a code fragment handle a value that could be either \f(CW\*(C`defined\*(C'\fR or \f(CW\*(C`undef\*(C'\fR (non-NULL or \s-1NULL\s0) at runtime. A simple technique is to prepare the appropriate statement as needed, and substitute the placeholder for non-NULL cases: .PP .Vb 5 \& $sql_clause = defined $age? "age = ?" : "age IS NULL"; \& $sth = $dbh\->prepare(qq{ \& SELECT fullname FROM people WHERE $sql_clause \& }); \& $sth\->execute(defined $age ? $age : ()); .Ve .PP The following technique illustrates qualifying a \f(CW\*(C`WHERE\*(C'\fR clause with several columns, whose associated values (\f(CW\*(C`defined\*(C'\fR or \f(CW\*(C`undef\*(C'\fR) are in a hash \f(CW%h:\fR .PP .Vb 10 \& for my $col ("age", "phone", "email") { \& if (defined $h{$col}) { \& push @sql_qual, "$col = ?"; \& push @sql_bind, $h{$col}; \& } \& else { \& push @sql_qual, "$col IS NULL"; \& } \& } \& $sql_clause = join(" AND ", @sql_qual); \& $sth = $dbh\->prepare(qq{ \& SELECT fullname FROM people WHERE $sql_clause \& }); \& $sth\->execute(@sql_bind); .Ve .PP The techniques above call prepare for the \s-1SQL\s0 statement with each call to execute. Because calls to \fBprepare()\fR can be expensive, performance can suffer when an application iterates many times over statements like the above. .PP A better solution is a single \f(CW\*(C`WHERE\*(C'\fR clause that supports both \&\s-1NULL\s0 and non-NULL comparisons. Its \s-1SQL\s0 statement would need to be prepared only once for all cases, thus improving performance. Several examples of \f(CW\*(C`WHERE\*(C'\fR clauses that support this are presented below. But each example lacks portability, robustness, or simplicity. Whether an example is supported on your database engine depends on what \s-1SQL\s0 extensions it provides, and where it supports the \f(CW\*(C`?\*(C'\fR placeholder in a statement. .PP .Vb 7 \& 0) age = ? \& 1) NVL(age, xx) = NVL(?, xx) \& 2) ISNULL(age, xx) = ISNULL(?, xx) \& 3) DECODE(age, ?, 1, 0) = 1 \& 4) age = ? OR (age IS NULL AND ? IS NULL) \& 5) age = ? OR (age IS NULL AND SP_ISNULL(?) = 1) \& 6) age = ? OR (age IS NULL AND ? = 1) .Ve .PP Statements formed with the above \f(CW\*(C`WHERE\*(C'\fR clauses require execute statements as follows. The arguments are required, whether their values are \f(CW\*(C`defined\*(C'\fR or \f(CW\*(C`undef\*(C'\fR. .PP .Vb 3 \& 0,1,2,3) $sth\->execute($age); \& 4,5) $sth\->execute($age, $age); \& 6) $sth\->execute($age, defined($age) ? 0 : 1); .Ve .PP Example 0 should not work (as mentioned earlier), but may work on a few database engines anyway (e.g. Sybase). Example 0 is part of examples 4, 5, and 6, so if example 0 works, these other examples may work, even if the engine does not properly support the right hand side of the \f(CW\*(C`OR\*(C'\fR expression. .PP Examples 1 and 2 are not robust: they require that you provide a valid column value xx (e.g. '~') which is not present in any row. That means you must have some notion of what data won't be stored in the column, and expect clients to adhere to that. .PP Example 5 requires that you provide a stored procedure (\s-1SP_ISNULL\s0 in this example) that acts as a function: it checks whether a value is null, and returns 1 if it is, or 0 if not. .PP Example 6, the least simple, is probably the most portable, i.e., it should work with most, if not all, database engines. .PP Here is a table that indicates which examples above are known to work on various database engines: .PP .Vb 10 \& \-\-\-\-\-Examples\-\-\-\-\-\- \& 0 1 2 3 4 5 6 \& \- \- \- \- \- \- \- \& Oracle 9 N Y N Y Y ? Y \& Informix IDS 9 N N N Y N Y Y \& MS SQL N N Y N Y ? Y \& Sybase Y N N N N N Y \& AnyData,DBM,CSV Y N N N Y Y* Y \& SQLite 3.3 N N N N Y N N \& MSAccess N N N N Y N Y .Ve .PP * Works only because Example 0 works. .PP \&\s-1DBI\s0 provides a sample perl script that will test the examples above on your database engine and tell you which ones work. It is located in the \fIex/\fR subdirectory of the \s-1DBI\s0 source distribution, or here: Please use the script to help us fill-in and maintain this table. .PP \&\fBPerformance\fR .PP Without using placeholders, the insert statement shown previously would have to contain the literal values to be inserted and would have to be re-prepared and re-executed for each row. With placeholders, the insert statement only needs to be prepared once. The bind values for each row can be given to the \f(CW\*(C`execute\*(C'\fR method each time it's called. By avoiding the need to re-prepare the statement for each row, the application typically runs many times faster. Here's an example: .PP .Vb 9 \& my $sth = $dbh\->prepare(q{ \& INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?) \& }) or die $dbh\->errstr; \& while (<>) { \& chomp; \& my ($product_code, $qty, $price) = split /,/; \& $sth\->execute($product_code, $qty, $price) or die $dbh\->errstr; \& } \& $dbh\->commit or die $dbh\->errstr; .Ve .PP See \*(L"execute\*(R" and \*(L"bind_param\*(R" for more details. .PP The \f(CW\*(C`q{...}\*(C'\fR style quoting used in this example avoids clashing with quotes that may be used in the \s-1SQL\s0 statement. Use the double-quote like \&\f(CW\*(C`qq{...}\*(C'\fR operator if you want to interpolate variables into the string. See \*(L"Quote and Quote-like Operators\*(R" in perlop for more details. .PP See also the \*(L"bind_columns\*(R" method, which is used to associate Perl variables with the output columns of a \f(CW\*(C`SELECT\*(C'\fR statement. .SH "THE DBI PACKAGE AND CLASS" .IX Header "THE DBI PACKAGE AND CLASS" In this section, we cover the \s-1DBI\s0 class methods, utility functions, and the dynamic attributes associated with generic \s-1DBI\s0 handles. .SS "\s-1DBI\s0 Constants" .IX Subsection "DBI Constants" Constants representing the values of the \s-1SQL\s0 standard types can be imported individually by name, or all together by importing the special \f(CW\*(C`:sql_types\*(C'\fR tag. .PP The names and values of all the defined \s-1SQL\s0 standard types can be produced like this: .PP .Vb 3 \& foreach (@{ $DBI::EXPORT_TAGS{sql_types} }) { \& printf "%s=%d\en", $_, &{"DBI::$_"}; \& } .Ve .PP These constants are defined by \s-1SQL/CLI, ODBC\s0 or both. \&\f(CW\*(C`SQL_BIGINT\*(C'\fR has conflicting codes in \s-1SQL/CLI\s0 and \s-1ODBC, DBI\s0 uses the \s-1ODBC\s0 one. .PP See the \*(L"type_info\*(R", \*(L"type_info_all\*(R", and \*(L"bind_param\*(R" methods for possible uses. .PP Note that just because the \s-1DBI\s0 defines a named constant for a given data type doesn't mean that drivers will support that data type. .SS "\s-1DBI\s0 Class Methods" .IX Subsection "DBI Class Methods" The following methods are provided by the \s-1DBI\s0 class: .PP \fI\f(CI\*(C`parse_dsn\*(C'\fI\fR .IX Subsection "parse_dsn" .PP .Vb 2 \& ($scheme, $driver, $attr_string, $attr_hash, $driver_dsn) = DBI\->parse_dsn($dsn) \& or die "Can\*(Aqt parse DBI DSN \*(Aq$dsn\*(Aq"; .Ve .PP Breaks apart a \s-1DBI\s0 Data Source Name (\s-1DSN\s0) and returns the individual parts. If \f(CW$dsn\fR doesn't contain a valid \s-1DSN\s0 then \fBparse_dsn()\fR returns an empty list. .PP \&\f(CW$scheme\fR is the first part of the \s-1DSN\s0 and is currently always 'dbi'. \&\f(CW$driver\fR is the driver name, possibly defaulted to \f(CW$ENV\fR{\s-1DBI_DRIVER\s0}, and may be undefined. \f(CW$attr_string\fR is the contents of the optional attribute string, which may be undefined. If \f(CW$attr_string\fR is not empty then \f(CW$attr_hash\fR is a reference to a hash containing the parsed attribute names and values. \&\f(CW$driver_dsn\fR is the last part of the \s-1DBI DSN\s0 string. For example: .PP .Vb 7 \& ($scheme, $driver, $attr_string, $attr_hash, $driver_dsn) \& = DBI\->parse_dsn("dbi:MyDriver(RaiseError=>1):db=test;port=42"); \& $scheme = \*(Aqdbi\*(Aq; \& $driver = \*(AqMyDriver\*(Aq; \& $attr_string = \*(AqRaiseError=>1\*(Aq; \& $attr_hash = { \*(AqRaiseError\*(Aq => \*(Aq1\*(Aq }; \& $driver_dsn = \*(Aqdb=test;port=42\*(Aq; .Ve .PP The \fBparse_dsn()\fR method was added in \s-1DBI 1.43.\s0 .PP \fI\f(CI\*(C`connect\*(C'\fI\fR .IX Subsection "connect" .PP .Vb 4 \& $dbh = DBI\->connect($data_source, $username, $password) \& or die $DBI::errstr; \& $dbh = DBI\->connect($data_source, $username, $password, \e%attr) \& or die $DBI::errstr; .Ve .PP Establishes a database connection, or session, to the requested \f(CW$data_source\fR. Returns a database handle object if the connection succeeds. Use \&\f(CW\*(C`$dbh\->disconnect\*(C'\fR to terminate the connection. .PP If the connect fails (see below), it returns \f(CW\*(C`undef\*(C'\fR and sets both \f(CW$DBI::err\fR and \f(CW$DBI::errstr\fR. (It does \fInot\fR explicitly set \f(CW$!\fR.) You should generally test the return status of \f(CW\*(C`connect\*(C'\fR and \f(CW\*(C`print $DBI::errstr\*(C'\fR if it has failed. .PP Multiple simultaneous connections to multiple databases through multiple drivers can be made via the \s-1DBI.\s0 Simply make one \f(CW\*(C`connect\*(C'\fR call for each database and keep a copy of each returned database handle. .PP The \f(CW$data_source\fR value must begin with "\f(CW\*(C`dbi:\*(C'\fR\fIdriver_name\fR\f(CW\*(C`:\*(C'\fR". The \fIdriver_name\fR specifies the driver that will be used to make the connection. (Letter case is significant.) .PP As a convenience, if the \f(CW$data_source\fR parameter is undefined or empty, the \s-1DBI\s0 will substitute the value of the environment variable \f(CW\*(C`DBI_DSN\*(C'\fR. If just the \fIdriver_name\fR part is empty (i.e., the \f(CW$data_source\fR prefix is "\f(CW\*(C`dbi::\*(C'\fR"), the environment variable \f(CW\*(C`DBI_DRIVER\*(C'\fR is used. If neither variable is set, then \f(CW\*(C`connect\*(C'\fR dies. .PP Examples of \f(CW$data_source\fR values are: .PP .Vb 3 \& dbi:DriverName:database_name \& dbi:DriverName:database_name@hostname:port \& dbi:DriverName:database=database_name;host=hostname;port=port .Ve .PP There is \fIno standard\fR for the text following the driver name. Each driver is free to use whatever syntax it wants. The only requirement the \&\s-1DBI\s0 makes is that all the information is supplied in a single string. You must consult the documentation for the drivers you are using for a description of the syntax they require. .PP It is recommended that drivers support the \s-1ODBC\s0 style, shown in the last example above. It is also recommended that they support the three common names '\f(CW\*(C`host\*(C'\fR', '\f(CW\*(C`port\*(C'\fR', and '\f(CW\*(C`database\*(C'\fR' (plus '\f(CW\*(C`db\*(C'\fR' as an alias for \f(CW\*(C`database\*(C'\fR). This simplifies automatic construction of basic DSNs: \f(CW"dbi:$driver:database=$db;host=$host;port=$port"\fR. Drivers should aim to 'do something reasonable' when given a \s-1DSN\s0 in this form, but if any part is meaningless for that driver (such as 'port' for Informix) it should generate an error if that part is not empty. .PP If the environment variable \f(CW\*(C`DBI_AUTOPROXY\*(C'\fR is defined (and the driver in \f(CW$data_source\fR is not "\f(CW\*(C`Proxy\*(C'\fR") then the connect request will automatically be changed to: .PP .Vb 1 \& $ENV{DBI_AUTOPROXY};dsn=$data_source .Ve .PP \&\f(CW\*(C`DBI_AUTOPROXY\*(C'\fR is typically set as "\f(CW\*(C`dbi:Proxy:hostname=...;port=...\*(C'\fR". If \f(CW$ENV\fR{\s-1DBI_AUTOPROXY\s0} doesn't begin with '\f(CW\*(C`dbi:\*(C'\fR' then \*(L"dbi:Proxy:\*(R" will be prepended to it first. See the DBD::Proxy documentation for more details. .PP If \f(CW$username\fR or \f(CW$password\fR are undefined (rather than just empty), then the \s-1DBI\s0 will substitute the values of the \f(CW\*(C`DBI_USER\*(C'\fR and \f(CW\*(C`DBI_PASS\*(C'\fR environment variables, respectively. The \s-1DBI\s0 will warn if the environment variables are not defined. However, the everyday use of these environment variables is not recommended for security reasons. The mechanism is primarily intended to simplify testing. See below for alternative way to specify the username and password. .PP \&\f(CW\*(C`DBI\->connect\*(C'\fR automatically installs the driver if it has not been installed yet. Driver installation either returns a valid driver handle, or it \fIdies\fR with an error message that includes the string "\f(CW\*(C`install_driver\*(C'\fR" and the underlying problem. So \f(CW\*(C`DBI\->connect\*(C'\fR will die on a driver installation failure and will only return \f(CW\*(C`undef\*(C'\fR on a connect failure, in which case \f(CW$DBI::errstr\fR will hold the error message. Use \f(CW\*(C`eval\*(C'\fR if you need to catch the "\f(CW\*(C`install_driver\*(C'\fR" error. .PP The \f(CW$data_source\fR argument (with the "\f(CW\*(C`dbi:...:\*(C'\fR" prefix removed) and the \&\f(CW$username\fR and \f(CW$password\fR arguments are then passed to the driver for processing. The \s-1DBI\s0 does not define any interpretation for the contents of these fields. The driver is free to interpret the \&\f(CW$data_source\fR, \f(CW$username\fR, and \f(CW$password\fR fields in any way, and supply whatever defaults are appropriate for the engine being accessed. (Oracle, for example, uses the \s-1ORACLE_SID\s0 and \s-1TWO_TASK\s0 environment variables if no \f(CW$data_source\fR is specified.) .PP The \f(CW\*(C`AutoCommit\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR attributes for each connection default to \*(L"on\*(R". (See \*(L"AutoCommit\*(R" and \*(L"PrintError\*(R" for more information.) However, it is strongly recommended that you explicitly define \f(CW\*(C`AutoCommit\*(C'\fR rather than rely on the default. The \f(CW\*(C`PrintWarn\*(C'\fR attribute defaults to true. The \f(CW\*(C`RaiseWarn\*(C'\fR attribute defaults to false. .PP The \f(CW\*(C`\e%attr\*(C'\fR parameter can be used to alter the default settings of \&\f(CW\*(C`PrintError\*(C'\fR, \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`AutoCommit\*(C'\fR, and other attributes. For example: .PP .Vb 4 \& $dbh = DBI\->connect($data_source, $user, $pass, { \& PrintError => 0, \& AutoCommit => 0 \& }); .Ve .PP The username and password can also be specified using the attributes \&\f(CW\*(C`Username\*(C'\fR and \f(CW\*(C`Password\*(C'\fR, in which case they take precedence over the \f(CW$username\fR and \f(CW$password\fR parameters. .PP You can also define connection attribute values within the \f(CW$data_source\fR parameter. For example: .PP .Vb 1 \& dbi:DriverName(PrintWarn=>0,PrintError=>0,Taint=>1):... .Ve .PP Individual attributes values specified in this way take precedence over any conflicting values specified via the \f(CW\*(C`\e%attr\*(C'\fR parameter to \f(CW\*(C`connect\*(C'\fR. .PP The \f(CW\*(C`dbi_connect_method\*(C'\fR attribute can be used to specify which driver method should be called to establish the connection. The only useful values are 'connect', 'connect_cached', or some specialized case like \&'Apache::DBI::connect' (which is automatically the default when running within Apache). .PP Where possible, each session (\f(CW$dbh\fR) is independent from the transactions in other sessions. This is useful when you need to hold cursors open across transactions\*(--for example, if you use one session for your long lifespan cursors (typically read-only) and another for your short update transactions. .PP For compatibility with old \s-1DBI\s0 scripts, the driver can be specified by passing its name as the fourth argument to \f(CW\*(C`connect\*(C'\fR (instead of \f(CW\*(C`\e%attr\*(C'\fR): .PP .Vb 1 \& $dbh = DBI\->connect($data_source, $user, $pass, $driver); .Ve .PP In this \*(L"old-style\*(R" form of \f(CW\*(C`connect\*(C'\fR, the \f(CW$data_source\fR should not start with "\f(CW\*(C`dbi:driver_name:\*(C'\fR". (If it does, the embedded driver_name will be ignored). Also note that in this older form of \f(CW\*(C`connect\*(C'\fR, the \f(CW\*(C`$dbh\->{AutoCommit}\*(C'\fR attribute is \fIundefined\fR, the \&\f(CW\*(C`$dbh\->{PrintError}\*(C'\fR attribute is off, and the old \f(CW\*(C`DBI_DBNAME\*(C'\fR environment variable is checked if \f(CW\*(C`DBI_DSN\*(C'\fR is not defined. Beware that this \*(L"old-style\*(R" \&\f(CW\*(C`connect\*(C'\fR will soon be withdrawn in a future version of \s-1DBI.\s0 .PP \fI\f(CI\*(C`connect_cached\*(C'\fI\fR .IX Subsection "connect_cached" .PP .Vb 4 \& $dbh = DBI\->connect_cached($data_source, $username, $password) \& or die $DBI::errstr; \& $dbh = DBI\->connect_cached($data_source, $username, $password, \e%attr) \& or die $DBI::errstr; .Ve .PP \&\f(CW\*(C`connect_cached\*(C'\fR is like \*(L"connect\*(R", except that the database handle returned is also stored in a hash associated with the given parameters. If another call is made to \f(CW\*(C`connect_cached\*(C'\fR with the same parameter values, then the corresponding cached \f(CW$dbh\fR will be returned if it is still valid. The cached database handle is replaced with a new connection if it has been disconnected or if the \f(CW\*(C`ping\*(C'\fR method fails. .PP Note that the behaviour of this method differs in several respects from the behaviour of persistent connections implemented by Apache::DBI. However, if Apache::DBI is loaded then \f(CW\*(C`connect_cached\*(C'\fR will use it. .PP Caching connections can be useful in some applications, but it can also cause problems, such as too many connections, and so should be used with care. In particular, avoid changing the attributes of a database handle created via \fBconnect_cached()\fR because it will affect other code that may be using the same handle. When \fBconnect_cached()\fR returns a handle the attributes will be reset to their initial values. This can cause problems, especially with the \f(CW\*(C`AutoCommit\*(C'\fR attribute. .PP Also, to ensure that the attributes passed are always the same, avoid passing references inline. For example, the \f(CW\*(C`Callbacks\*(C'\fR attribute is specified as a hash reference. Be sure to declare it external to the call to \&\fBconnect_cached()\fR, such that the hash reference is not re-created on every call. A package-level lexical works well: .PP .Vb 4 \& package MyDBH; \& my $cb = { \& \*(Aqconnect_cached.reused\*(Aq => sub { delete $_[4]\->{AutoCommit} }, \& }; \& \& sub dbh { \& DBI\->connect_cached( $dsn, $username, $auth, { Callbacks => $cb }); \& } .Ve .PP Where multiple separate parts of a program are using \fBconnect_cached()\fR to connect to the same database with the same (initial) attributes it is a good idea to add a private attribute to the \fBconnect_cached()\fR call to effectively limit the scope of the caching. For example: .PP .Vb 1 \& DBI\->connect_cached(..., { private_foo_cachekey => "Bar", ... }); .Ve .PP Handles returned from that \fBconnect_cached()\fR call will only be returned by other \fBconnect_cached()\fR call elsewhere in the code if those other calls also pass in the same attribute values, including the private one. (I've used \f(CW\*(C`private_foo_cachekey\*(C'\fR here as an example, you can use any attribute name with a \f(CW\*(C`private_\*(C'\fR prefix.) .PP Taking that one step further, you can limit a particular \fBconnect_cached()\fR call to return handles unique to that one place in the code by setting the private attribute to a unique value for that place: .PP .Vb 1 \& DBI\->connect_cached(..., { private_foo_cachekey => _\|_FILE_\|_._\|_LINE_\|_, ... }); .Ve .PP By using a private attribute you still get connection caching for the individual calls to \fBconnect_cached()\fR but, by making separate database connections for separate parts of the code, the database handles are isolated from any attribute changes made to other handles. .PP The cache can be accessed (and cleared) via the \*(L"CachedKids\*(R" attribute: .PP .Vb 2 \& my $CachedKids_hashref = $dbh\->{Driver}\->{CachedKids}; \& %$CachedKids_hashref = () if $CachedKids_hashref; .Ve .PP \fI\f(CI\*(C`available_drivers\*(C'\fI\fR .IX Subsection "available_drivers" .PP .Vb 2 \& @ary = DBI\->available_drivers; \& @ary = DBI\->available_drivers($quiet); .Ve .PP Returns a list of all available drivers by searching for \f(CW\*(C`DBD::*\*(C'\fR modules through the directories in \f(CW@INC\fR. By default, a warning is given if some drivers are hidden by others of the same name in earlier directories. Passing a true value for \f(CW$quiet\fR will inhibit the warning. .PP \fI\f(CI\*(C`installed_drivers\*(C'\fI\fR .IX Subsection "installed_drivers" .PP .Vb 1 \& %drivers = DBI\->installed_drivers(); .Ve .PP Returns a list of driver name and driver handle pairs for all drivers \&'installed' (loaded) into the current process. The driver name does not include the '\s-1DBD::\s0' prefix. .PP To get a list of all drivers available in your perl installation you can use \&\*(L"available_drivers\*(R". .PP Added in \s-1DBI 1.49.\s0 .PP \fI\f(CI\*(C`installed_versions\*(C'\fI\fR .IX Subsection "installed_versions" .PP .Vb 3 \& DBI\->installed_versions; \& @ary = DBI\->installed_versions; \& $hash = DBI\->installed_versions; .Ve .PP Calls \fBavailable_drivers()\fR and attempts to load each of them in turn using \fBinstall_driver()\fR. For each load that succeeds the driver name and version number are added to a hash. When running under DBI::PurePerl drivers which appear not be pure-perl are ignored. .PP When called in array context the list of successfully loaded drivers is returned (without the '\s-1DBD::\s0' prefix). .PP When called in scalar context an extra entry for the \f(CW\*(C`DBI\*(C'\fR is added (and \&\f(CW\*(C`DBI::PurePerl\*(C'\fR if appropriate) and a reference to the hash is returned. .PP When called in a void context the \fBinstalled_versions()\fR method will print out a formatted list of the hash contents, one per line, along with some other information about the \s-1DBI\s0 version and \s-1OS.\s0 .PP Due to the potentially high memory cost and unknown risks of loading in an unknown number of drivers that just happen to be installed on the system, this method is not recommended for general use. Use \fBavailable_drivers()\fR instead. .PP The \fBinstalled_versions()\fR method is primarily intended as a quick way to see from the command line what's installed. For example: .PP .Vb 1 \& perl \-MDBI \-e \*(AqDBI\->installed_versions\*(Aq .Ve .PP The \fBinstalled_versions()\fR method was added in \s-1DBI 1.38.\s0 .PP \fI\f(CI\*(C`data_sources\*(C'\fI\fR .IX Subsection "data_sources" .PP .Vb 2 \& @ary = DBI\->data_sources($driver); \& @ary = DBI\->data_sources($driver, \e%attr); .Ve .PP Returns a list of data sources (databases) available via the named driver. If \f(CW$driver\fR is empty or \f(CW\*(C`undef\*(C'\fR, then the value of the \&\f(CW\*(C`DBI_DRIVER\*(C'\fR environment variable is used. .PP The driver will be loaded if it hasn't been already. Note that if the driver loading fails then \fBdata_sources()\fR \fIdies\fR with an error message that includes the string "\f(CW\*(C`install_driver\*(C'\fR" and the underlying problem. .PP Data sources are returned in a form suitable for passing to the \&\*(L"connect\*(R" method (that is, they will include the "\f(CW\*(C`dbi:$driver:\*(C'\fR" prefix). .PP Note that many drivers have no way of knowing what data sources might be available for it. These drivers return an empty or incomplete list or may require driver-specific attributes. .PP There is also a \fBdata_sources()\fR method defined for database handles. .PP \fI\f(CI\*(C`trace\*(C'\fI\fR .IX Subsection "trace" .PP .Vb 4 \& DBI\->trace($trace_setting) \& DBI\->trace($trace_setting, $trace_filename) \& DBI\->trace($trace_setting, $trace_filehandle) \& $trace_setting = DBI\->trace; .Ve .PP The \f(CW\*(C`DBI\->trace\*(C'\fR method sets the \fIglobal default\fR trace settings and returns the \fIprevious\fR trace settings. It can also be used to change where the trace output is sent. .PP There's a similar method, \f(CW\*(C`$h\->trace\*(C'\fR, which sets the trace settings for the specific handle it's called on. .PP See the \*(L"\s-1TRACING\*(R"\s0 section for full details about the \s-1DBI\s0's powerful tracing facilities. .PP \fI\f(CI\*(C`visit_handles\*(C'\fI\fR .IX Subsection "visit_handles" .PP .Vb 2 \& DBI\->visit_handles( $coderef ); \& DBI\->visit_handles( $coderef, $info ); .Ve .PP Where \f(CW$coderef\fR is a reference to a subroutine and \f(CW$info\fR is an arbitrary value which, if undefined, defaults to a reference to an empty hash. Returns \f(CW$info\fR. .PP For each installed driver handle, if any, \f(CW$coderef\fR is invoked as: .PP .Vb 1 \& $coderef\->($driver_handle, $info); .Ve .PP If the execution of \f(CW$coderef\fR returns a true value then \*(L"visit_child_handles\*(R" is called on that child handle and passed the returned value as \f(CW$info\fR. .PP For example: .PP .Vb 5 \& my $info = $dbh\->{Driver}\->visit_child_handles(sub { \& my ($h, $info) = @_; \& ++$info\->{ $h\->{Type} }; # count types of handles (dr/db/st) \& return $info; # visit kids \& }); .Ve .PP See also \*(L"visit_child_handles\*(R". .SS "\s-1DBI\s0 Utility Functions" .IX Subsection "DBI Utility Functions" In addition to the \s-1DBI\s0 methods listed in the previous section, the \s-1DBI\s0 package also provides several utility functions. .PP These can be imported into your code by listing them in the \f(CW\*(C`use\*(C'\fR statement. For example: .PP .Vb 1 \& use DBI qw(neat data_diff); .Ve .PP Alternatively, all these utility functions (except hash) can be imported using the \f(CW\*(C`:utils\*(C'\fR import tag. For example: .PP .Vb 1 \& use DBI qw(:utils); .Ve .PP \fI\f(CI\*(C`data_string_desc\*(C'\fI\fR .IX Subsection "data_string_desc" .PP .Vb 1 \& $description = data_string_desc($string); .Ve .PP Returns an informal description of the string. For example: .PP .Vb 5 \& UTF8 off, ASCII, 42 characters 42 bytes \& UTF8 off, non\-ASCII, 42 characters 42 bytes \& UTF8 on, non\-ASCII, 4 characters 6 bytes \& UTF8 on but INVALID encoding, non\-ASCII, 4 characters 6 bytes \& UTF8 off, undef .Ve .PP The initial \f(CW\*(C`UTF8\*(C'\fR on/off refers to Perl's internal SvUTF8 flag. If \f(CW$string\fR has the SvUTF8 flag set but the sequence of bytes it contains are not a valid \s-1UTF\-8\s0 encoding then \fBdata_string_desc()\fR will report \f(CW\*(C`UTF8 on but INVALID encoding\*(C'\fR. .PP The \f(CW\*(C`ASCII\*(C'\fR vs \f(CW\*(C`non\-ASCII\*(C'\fR portion shows \f(CW\*(C`ASCII\*(C'\fR if \fIall\fR the characters in the string are \s-1ASCII\s0 (have code points <= 127). .PP The \fBdata_string_desc()\fR function was added in \s-1DBI 1.46.\s0 .PP \fI\f(CI\*(C`data_string_diff\*(C'\fI\fR .IX Subsection "data_string_diff" .PP .Vb 1 \& $diff = data_string_diff($a, $b); .Ve .PP Returns an informal description of the first character difference between the strings. If both \f(CW$a\fR and \f(CW$b\fR contain the same sequence of characters then \fBdata_string_diff()\fR returns an empty string. For example: .PP .Vb 6 \& Params a & b Result \& \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\- \& \*(Aqaaa\*(Aq, \*(Aqaaa\*(Aq \*(Aq\*(Aq \& \*(Aqaaa\*(Aq, \*(Aqabc\*(Aq \*(AqStrings differ at index 2: a[2]=a, b[2]=b\*(Aq \& \*(Aqaaa\*(Aq, undef \*(AqString b is undef, string a has 3 characters\*(Aq \& \*(Aqaaa\*(Aq, \*(Aqaa\*(Aq \*(AqString b truncated after 2 characters\*(Aq .Ve .PP Unicode characters are reported in \f(CW\*(C`\ex{XXXX}\*(C'\fR format. Unicode code points in the range U+0800 to U+08FF are unassigned and most likely to occur due to double-encoding. Characters in this range are reported as \f(CW\*(C`\ex{08XX}=\*(AqC\*(Aq\*(C'\fR where \f(CW\*(C`C\*(C'\fR is the corresponding latin\-1 character. .PP The \fBdata_string_diff()\fR function only considers logical \fIcharacters\fR and not the underlying encoding. See \*(L"data_diff\*(R" for an alternative. .PP The \fBdata_string_diff()\fR function was added in \s-1DBI 1.46.\s0 .PP \fI\f(CI\*(C`data_diff\*(C'\fI\fR .IX Subsection "data_diff" .PP .Vb 2 \& $diff = data_diff($a, $b); \& $diff = data_diff($a, $b, $logical); .Ve .PP Returns an informal description of the difference between two strings. It calls \*(L"data_string_desc\*(R" and \*(L"data_string_diff\*(R" and returns the combined results as a multi-line string. .PP For example, \f(CW\*(C`data_diff("abc", "ab\ex{263a}")\*(C'\fR will return: .PP .Vb 3 \& a: UTF8 off, ASCII, 3 characters 3 bytes \& b: UTF8 on, non\-ASCII, 3 characters 5 bytes \& Strings differ at index 2: a[2]=c, b[2]=\ex{263A} .Ve .PP If \f(CW$a\fR and \f(CW$b\fR are identical in both the characters they contain \fIand\fR their physical encoding then \fBdata_diff()\fR returns an empty string. If \f(CW$logical\fR is true then physical encoding differences are ignored (but are still reported if there is a difference in the characters). .PP The \fBdata_diff()\fR function was added in \s-1DBI 1.46.\s0 .PP \fI\f(CI\*(C`neat\*(C'\fI\fR .IX Subsection "neat" .PP .Vb 2 \& $str = neat($value); \& $str = neat($value, $maxlen); .Ve .PP Return a string containing a neat (and tidy) representation of the supplied value. .PP Strings will be quoted, although internal quotes will \fInot\fR be escaped. Values known to be numeric will be unquoted. Undefined (\s-1NULL\s0) values will be shown as \f(CW\*(C`undef\*(C'\fR (without quotes). .PP If the string is flagged internally as utf8 then double quotes will be used, otherwise single quotes are used and unprintable characters will be replaced by dot (.). .PP For result strings longer than \f(CW$maxlen\fR the result string will be truncated to \f(CW\*(C`$maxlen\-4\*(C'\fR and "\f(CW\*(C`...\*(Aq\*(C'\fR" will be appended. If \f(CW$maxlen\fR is 0 or \f(CW\*(C`undef\*(C'\fR, it defaults to \f(CW$DBI::neat_maxlen\fR which, in turn, defaults to 400. .PP This function is designed to format values for human consumption. It is used internally by the \s-1DBI\s0 for \*(L"trace\*(R" output. It should typically \fInot\fR be used for formatting values for database use. (See also \*(L"quote\*(R".) .PP \fI\f(CI\*(C`neat_list\*(C'\fI\fR .IX Subsection "neat_list" .PP .Vb 1 \& $str = neat_list(\e@listref, $maxlen, $field_sep); .Ve .PP Calls \f(CW\*(C`neat\*(C'\fR on each element of the list and returns a string containing the results joined with \f(CW$field_sep\fR. \f(CW$field_sep\fR defaults to \f(CW", "\fR. .PP \fI\f(CI\*(C`looks_like_number\*(C'\fI\fR .IX Subsection "looks_like_number" .PP .Vb 1 \& @bool = looks_like_number(@array); .Ve .PP Returns true for each element that looks like a number. Returns false for each element that does not look like a number. Returns \f(CW\*(C`undef\*(C'\fR for each element that is undefined or empty. .PP \fI\f(CI\*(C`hash\*(C'\fI\fR .IX Subsection "hash" .PP .Vb 1 \& $hash_value = DBI::hash($buffer, $type); .Ve .PP Return a 32\-bit integer 'hash' value corresponding to the contents of \f(CW$buffer\fR. The \f(CW$type\fR parameter selects which kind of hash algorithm should be used. .PP For the technically curious, type 0 (which is the default if \f(CW$type\fR isn't specified) is based on the Perl 5.1 hash except that the value is forced to be negative (for obscure historical reasons). Type 1 is the better \*(L"Fowler / Noll / Vo\*(R" (\s-1FNV\s0) hash. See for more information. Both types are implemented in C and are very fast. .PP This function doesn't have much to do with databases, except that it can sometimes be handy to store such values in a database. It also doesn't have much to do with perl hashes, like \f(CW%foo\fR. .PP \fI\f(CI\*(C`sql_type_cast\*(C'\fI\fR .IX Subsection "sql_type_cast" .PP .Vb 1 \& $sts = DBI::sql_type_cast($sv, $sql_type, $flags); .Ve .PP sql_type_cast attempts to cast \f(CW$sv\fR to the \s-1SQL\s0 type (see \s-1DBI\s0 Constants) specified in \f(CW$sql_type\fR. At present only the \s-1SQL\s0 types \&\f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DOUBLE\*(C'\fR and \f(CW\*(C`SQL_NUMERIC\*(C'\fR are supported. .PP For \f(CW\*(C`SQL_INTEGER\*(C'\fR the effect is similar to using the value in an expression that requires an integer. It gives the perl scalar an 'integer aspect'. (Technically the value gains an \s-1IV,\s0 or possibly a \s-1UV\s0 or \s-1NV\s0 if the value is too large for an \s-1IV.\s0) .PP For \f(CW\*(C`SQL_DOUBLE\*(C'\fR the effect is similar to using the value in an expression that requires a general numeric value. It gives the perl scalar a 'numeric aspect'. (Technically the value gains an \s-1NV.\s0) .PP \&\f(CW\*(C`SQL_NUMERIC\*(C'\fR is similar to \f(CW\*(C`SQL_INTEGER\*(C'\fR or \f(CW\*(C`SQL_DOUBLE\*(C'\fR but more general and more cautious. It will look at the string first and if it looks like an integer (that will fit in an \s-1IV\s0 or \s-1UV\s0) it will act like \&\f(CW\*(C`SQL_INTEGER\*(C'\fR, if it looks like a floating point value it will act like \f(CW\*(C`SQL_DOUBLE\*(C'\fR, if it looks like neither then it will do nothing \- and thereby avoid the warnings that would be generated by \&\f(CW\*(C`SQL_INTEGER\*(C'\fR and \f(CW\*(C`SQL_DOUBLE\*(C'\fR when given non-numeric data. .PP \&\f(CW$flags\fR may be: .ie n .IP """DBIstcf_DISCARD_STRING""" 4 .el .IP "\f(CWDBIstcf_DISCARD_STRING\fR" 4 .IX Item "DBIstcf_DISCARD_STRING" If this flag is specified then when the driver successfully casts the bound perl scalar to a non-string type then the string portion of the scalar will be discarded. .ie n .IP """DBIstcf_STRICT""" 4 .el .IP "\f(CWDBIstcf_STRICT\fR" 4 .IX Item "DBIstcf_STRICT" If \f(CW$sv\fR cannot be cast to the requested \f(CW$sql_type\fR then by default it is left untouched and no error is generated. If you specify \&\f(CW\*(C`DBIstcf_STRICT\*(C'\fR and the cast fails, this will generate an error. .PP The returned \f(CW$sts\fR value is: .PP .Vb 5 \& \-2 sql_type is not handled \& \-1 sv is undef so unchanged \& 0 sv could not be cast cleanly and DBIstcf_STRICT was used \& 1 sv could not be cast and DBIstcf_STRICT was not used \& 2 sv was cast successfully .Ve .PP This method is exported by the :utils tag and was introduced in \s-1DBI 1.611.\s0 .SS "\s-1DBI\s0 Dynamic Attributes" .IX Subsection "DBI Dynamic Attributes" Dynamic attributes are always associated with the \fIlast handle used\fR (that handle is represented by \f(CW$h\fR in the descriptions below). .PP Where an attribute is equivalent to a method call, then refer to the method call for all related documentation. .PP Warning: these attributes are provided as a convenience but they do have limitations. Specifically, they have a short lifespan: because they are associated with the last handle used, they should only be used \fIimmediately\fR after calling the method that \*(L"sets\*(R" them. If in any doubt, use the corresponding method call. .PP \fI\f(CI$DBI::err\fI\fR .IX Subsection "$DBI::err" .PP Equivalent to \f(CW\*(C`$h\->err\*(C'\fR. .PP \fI\f(CI$DBI::errstr\fI\fR .IX Subsection "$DBI::errstr" .PP Equivalent to \f(CW\*(C`$h\->errstr\*(C'\fR. .PP \fI\f(CI$DBI::state\fI\fR .IX Subsection "$DBI::state" .PP Equivalent to \f(CW\*(C`$h\->state\*(C'\fR. .PP \fI\f(CI$DBI::rows\fI\fR .IX Subsection "$DBI::rows" .PP Equivalent to \f(CW\*(C`$h\->rows\*(C'\fR. Please refer to the documentation for the \*(L"rows\*(R" method. .PP \fI\f(CI$DBI::lasth\fI\fR .IX Subsection "$DBI::lasth" .PP Returns the \s-1DBI\s0 object handle used for the most recent \s-1DBI\s0 method call. If the last \s-1DBI\s0 method call was a \s-1DESTROY\s0 then \f(CW$DBI::lasth\fR will return the handle of the parent of the destroyed handle, if there is one. .SH "METHODS COMMON TO ALL HANDLES" .IX Header "METHODS COMMON TO ALL HANDLES" The following methods can be used by all types of \s-1DBI\s0 handles. .PP \fI\f(CI\*(C`err\*(C'\fI\fR .IX Subsection "err" .PP .Vb 1 \& $rv = $h\->err; .Ve .PP Returns the \fInative\fR database engine error code from the last driver method called. The code is typically an integer but you should not assume that. .PP The \s-1DBI\s0 resets \f(CW$h\fR\->err to undef before almost all \s-1DBI\s0 method calls, so the value only has a short lifespan. Also, for most drivers, the statement handles share the same error variable as the parent database handle, so calling a method on one handle may reset the error on the related handles. .PP (Methods which don't reset err before being called include \fBerr()\fR and \fBerrstr()\fR, obviously, \fBstate()\fR, \fBrows()\fR, \fBfunc()\fR, \fBtrace()\fR, \fBtrace_msg()\fR, \fBping()\fR, and the tied hash attribute \s-1\fBFETCH\s0()\fR and \s-1\fBSTORE\s0()\fR methods.) .PP If you need to test for specific error conditions \fIand\fR have your program be portable to different database engines, then you'll need to determine what the corresponding error codes are for all those engines and test for all of them. .PP The \s-1DBI\s0 uses the value of \f(CW$DBI::stderr\fR as the \f(CW\*(C`err\*(C'\fR value for internal errors. Drivers should also do likewise. The default value for \f(CW$DBI::stderr\fR is 2000000000. .PP A driver may return \f(CW0\fR from \fBerr()\fR to indicate a warning condition after a method call. Similarly, a driver may return an empty string to indicate a 'success with information' condition. In both these cases the value is false but not undef. The \fBerrstr()\fR and \fBstate()\fR methods may be used to retrieve extra information in these cases. .PP See \*(L"set_err\*(R" for more information. .PP \fI\f(CI\*(C`errstr\*(C'\fI\fR .IX Subsection "errstr" .PP .Vb 1 \& $str = $h\->errstr; .Ve .PP Returns the native database engine error message from the last \s-1DBI\s0 method called. This has the same lifespan issues as the \*(L"err\*(R" method described above. .PP The returned string may contain multiple messages separated by newline characters. .PP The \fBerrstr()\fR method should not be used to test for errors, use \fBerr()\fR for that, because drivers may return 'success with information' or warning messages via \fBerrstr()\fR for methods that have not 'failed'. .PP See \*(L"set_err\*(R" for more information. .PP \fI\f(CI\*(C`state\*(C'\fI\fR .IX Subsection "state" .PP .Vb 1 \& $str = $h\->state; .Ve .PP Returns a state code in the standard \s-1SQLSTATE\s0 five character format. Note that the specific success code \f(CW00000\fR is translated to any empty string (false). If the driver does not support \s-1SQLSTATE\s0 (and most don't), then \fBstate()\fR will return \f(CW\*(C`S1000\*(C'\fR (General Error) for all errors. .PP The driver is free to return any value via \f(CW\*(C`state\*(C'\fR, e.g., warning codes, even if it has not declared an error by returning a true value via the \*(L"err\*(R" method described above. .PP The \fBstate()\fR method should not be used to test for errors, use \fBerr()\fR for that, because drivers may return a 'success with information' or warning state code via \fBstate()\fR for methods that have not 'failed'. .PP \fI\f(CI\*(C`set_err\*(C'\fI\fR .IX Subsection "set_err" .PP .Vb 4 \& $rv = $h\->set_err($err, $errstr); \& $rv = $h\->set_err($err, $errstr, $state); \& $rv = $h\->set_err($err, $errstr, $state, $method); \& $rv = $h\->set_err($err, $errstr, $state, $method, $rv); .Ve .PP Set the \f(CW\*(C`err\*(C'\fR, \f(CW\*(C`errstr\*(C'\fR, and \f(CW\*(C`state\*(C'\fR values for the handle. This method is typically only used by \s-1DBI\s0 drivers and \s-1DBI\s0 subclasses. .PP If the \*(L"HandleSetErr\*(R" attribute holds a reference to a subroutine it is called first. The subroutine can alter the \f(CW$err\fR, \f(CW$errstr\fR, \f(CW$state\fR, and \f(CW$method\fR values. See \*(L"HandleSetErr\*(R" for full details. If the subroutine returns a true value then the handle \f(CW\*(C`err\*(C'\fR, \&\f(CW\*(C`errstr\*(C'\fR, and \f(CW\*(C`state\*(C'\fR values are not altered and \fBset_err()\fR returns an empty list (it normally returns \f(CW$rv\fR which defaults to undef, see below). .PP Setting \f(CW\*(C`err\*(C'\fR to a \fItrue\fR value indicates an error and will trigger the normal \s-1DBI\s0 error handling mechanisms, such as \f(CW\*(C`RaiseError\*(C'\fR and \&\f(CW\*(C`HandleError\*(C'\fR, if they are enabled, when execution returns from the \s-1DBI\s0 back to the application. .PP Setting \f(CW\*(C`err\*(C'\fR to \f(CW""\fR indicates an 'information' state, and setting it to \f(CW"0"\fR indicates a 'warning' state. Setting \f(CW\*(C`err\*(C'\fR to \f(CW\*(C`undef\*(C'\fR also sets \f(CW\*(C`errstr\*(C'\fR to undef, and \f(CW\*(C`state\*(C'\fR to \f(CW""\fR, irrespective of the values of the \f(CW$errstr\fR and \f(CW$state\fR parameters. .PP The \f(CW$method\fR parameter provides an alternate method name for the \&\f(CW\*(C`RaiseError\*(C'\fR/\f(CW\*(C`PrintError\*(C'\fR/\f(CW\*(C`RaiseWarn\*(C'\fR/\f(CW\*(C`PrintWarn\*(C'\fR error string instead of the fairly unhelpful '\f(CW\*(C`set_err\*(C'\fR'. .PP The \f(CW\*(C`set_err\*(C'\fR method normally returns undef. The \f(CW$rv\fR parameter provides an alternate return value. .PP Some special rules apply if the \f(CW\*(C`err\*(C'\fR or \f(CW\*(C`errstr\*(C'\fR values for the handle are \fIalready\fR set... .PP If \f(CW\*(C`errstr\*(C'\fR is true then: "\f(CW\*(C` [err was %s now %s]\*(C'\fR" is appended if \f(CW$err\fR is true and \f(CW\*(C`err\*(C'\fR is already true and the new err value differs from the original one. Similarly "\f(CW\*(C` [state was %s now %s]\*(C'\fR" is appended if \f(CW$state\fR is true and \f(CW\*(C`state\*(C'\fR is already true and the new state value differs from the original one. Finally "\f(CW\*(C`\en\*(C'\fR" and the new \f(CW$errstr\fR are appended if \f(CW$errstr\fR differs from the existing errstr value. Obviously the \f(CW%s\fR's above are replaced by the corresponding values. .PP The handle \f(CW\*(C`err\*(C'\fR value is set to \f(CW$err\fR if: \f(CW$err\fR is true; or handle \&\f(CW\*(C`err\*(C'\fR value is undef; or \f(CW$err\fR is defined and the length is greater than the handle \f(CW\*(C`err\*(C'\fR length. The effect is that an 'information' state only overrides undef; a 'warning' overrides undef or 'information', and an 'error' state overrides anything. .PP The handle \f(CW\*(C`state\*(C'\fR value is set to \f(CW$state\fR if \f(CW$state\fR is true and the handle \f(CW\*(C`err\*(C'\fR value was set (by the rules above). .PP Support for warning and information states was added in \s-1DBI 1.41.\s0 .PP \fI\f(CI\*(C`trace\*(C'\fI\fR .IX Subsection "trace" .PP .Vb 3 \& $h\->trace($trace_settings); \& $h\->trace($trace_settings, $trace_filename); \& $trace_settings = $h\->trace; .Ve .PP The \fBtrace()\fR method is used to alter the trace settings for a handle (and any future children of that handle). It can also be used to change where the trace output is sent. .PP There's a similar method, \f(CW\*(C`DBI\->trace\*(C'\fR, which sets the global default trace settings. .PP See the \*(L"\s-1TRACING\*(R"\s0 section for full details about the \s-1DBI\s0's powerful tracing facilities. .PP \fI\f(CI\*(C`trace_msg\*(C'\fI\fR .IX Subsection "trace_msg" .PP .Vb 2 \& $h\->trace_msg($message_text); \& $h\->trace_msg($message_text, $min_level); .Ve .PP Writes \f(CW$message_text\fR to the trace file if the trace level is greater than or equal to \f(CW$min_level\fR (which defaults to 1). Can also be called as \f(CW\*(C`DBI\->trace_msg($msg)\*(C'\fR. .PP See \*(L"\s-1TRACING\*(R"\s0 for more details. .PP \fI\f(CI\*(C`func\*(C'\fI\fR .IX Subsection "func" .PP .Vb 1 \& $h\->func(@func_arguments, $func_name) or die ...; .Ve .PP The \f(CW\*(C`func\*(C'\fR method can be used to call private non-standard and non-portable methods implemented by the driver. Note that the function name is given as the \fIlast\fR argument. .PP It's also important to note that the \fBfunc()\fR method does not clear a previous error ($DBI::err etc.) and it does not trigger automatic error detection (RaiseError etc.) so you must check the return status and/or \f(CW$h\fR\->err to detect errors. .PP (This method is not directly related to calling stored procedures. Calling stored procedures is currently not defined by the \s-1DBI.\s0 Some drivers, such as DBD::Oracle, support it in non-portable ways. See driver documentation for more details.) .PP See also \fBinstall_method()\fR in \s-1DBI::DBD\s0 for how you can avoid needing to use \fBfunc()\fR and gain direct access to driver-private methods. .PP \fI\f(CI\*(C`can\*(C'\fI\fR .IX Subsection "can" .PP .Vb 1 \& $is_implemented = $h\->can($method_name); .Ve .PP Returns true if \f(CW$method_name\fR is implemented by the driver or a default method is provided by the \s-1DBI\s0's driver base class. It returns false where a driver hasn't implemented a method and the default method is provided by the \s-1DBI\s0's driver base class is just an empty stub. .PP \fI\f(CI\*(C`parse_trace_flags\*(C'\fI\fR .IX Subsection "parse_trace_flags" .PP .Vb 1 \& $trace_settings_integer = $h\->parse_trace_flags($trace_settings); .Ve .PP Parses a string containing trace settings and returns the corresponding integer value used internally by the \s-1DBI\s0 and drivers. .PP The \f(CW$trace_settings\fR argument is a string containing a trace level between 0 and 15 and/or trace flag names separated by vertical bar ("\f(CW\*(C`|\*(C'\fR\*(L") or comma (\*(R"\f(CW\*(C`,\*(C'\fR") characters. For example: \f(CW"SQL|3|foo"\fR. .PP It uses the \fBparse_trace_flag()\fR method, described below, to process the individual trace flag names. .PP The \fBparse_trace_flags()\fR method was added in \s-1DBI 1.42.\s0 .PP \fI\f(CI\*(C`parse_trace_flag\*(C'\fI\fR .IX Subsection "parse_trace_flag" .PP .Vb 1 \& $bit_flag = $h\->parse_trace_flag($trace_flag_name); .Ve .PP Returns the bit flag corresponding to the trace flag name in \&\f(CW$trace_flag_name\fR. Drivers are expected to override this method and check if \f(CW$trace_flag_name\fR is a driver specific trace flags and, if not, then call the \s-1DBI\s0's default \fBparse_trace_flag()\fR. .PP The \fBparse_trace_flag()\fR method was added in \s-1DBI 1.42.\s0 .PP \fI\f(CI\*(C`private_attribute_info\*(C'\fI\fR .IX Subsection "private_attribute_info" .PP .Vb 1 \& $hash_ref = $h\->private_attribute_info(); .Ve .PP Returns a reference to a hash whose keys are the names of driver-private handle attributes available for the kind of handle (driver, database, statement) that the method was called on. .PP For example, the return value when called with a DBD::Sybase \f(CW$dbh\fR could look like this: .PP .Vb 6 \& { \& syb_dynamic_supported => undef, \& syb_oc_version => undef, \& syb_server_version => undef, \& syb_server_version_string => undef, \& } .Ve .PP and when called with a DBD::Sybase \f(CW$sth\fR they could look like this: .PP .Vb 5 \& { \& syb_types => undef, \& syb_proc_status => undef, \& syb_result_type => undef, \& } .Ve .PP The values should be undef. Meanings may be assigned to particular values in future. .PP \fI\f(CI\*(C`swap_inner_handle\*(C'\fI\fR .IX Subsection "swap_inner_handle" .PP .Vb 2 \& $rc = $h1\->swap_inner_handle( $h2 ); \& $rc = $h1\->swap_inner_handle( $h2, $allow_reparent ); .Ve .PP Brain transplants for handles. You don't need to know about this unless you want to become a handle surgeon. .PP A \s-1DBI\s0 handle is a reference to a tied hash. A tied hash has an \&\fIinner\fR hash that actually holds the contents. The \fBswap_inner_handle()\fR method swaps the inner hashes between two handles. The \f(CW$h1\fR and \f(CW$h2\fR handles still point to the same tied hashes, but what those hashes are tied to has been swapped. In effect \f(CW$h1\fR \fIbecomes\fR \f(CW$h2\fR and vice-versa. This is powerful stuff, expect problems. Use with care. .PP As a small safety measure, the two handles, \f(CW$h1\fR and \f(CW$h2\fR, have to share the same parent unless \f(CW$allow_reparent\fR is true. .PP The \fBswap_inner_handle()\fR method was added in \s-1DBI 1.44.\s0 .PP Here's a quick kind of 'diagram' as a worked example to help think about what's happening: .PP .Vb 4 \& Original state: \& dbh1o \-> dbh1i \& sthAo \-> sthAi(dbh1i) \& dbh2o \-> dbh2i \& \& swap_inner_handle dbh1o with dbh2o: \& dbh2o \-> dbh1i \& sthAo \-> sthAi(dbh1i) \& dbh1o \-> dbh2i \& \& create new sth from dbh1o: \& dbh2o \-> dbh1i \& sthAo \-> sthAi(dbh1i) \& dbh1o \-> dbh2i \& sthBo \-> sthBi(dbh2i) \& \& swap_inner_handle sthAo with sthBo: \& dbh2o \-> dbh1i \& sthBo \-> sthAi(dbh1i) \& dbh1o \-> dbh2i \& sthAo \-> sthBi(dbh2i) .Ve .PP \fI\f(CI\*(C`visit_child_handles\*(C'\fI\fR .IX Subsection "visit_child_handles" .PP .Vb 2 \& $h\->visit_child_handles( $coderef ); \& $h\->visit_child_handles( $coderef, $info ); .Ve .PP Where \f(CW$coderef\fR is a reference to a subroutine and \f(CW$info\fR is an arbitrary value which, if undefined, defaults to a reference to an empty hash. Returns \f(CW$info\fR. .PP For each child handle of \f(CW$h\fR, if any, \f(CW$coderef\fR is invoked as: .PP .Vb 1 \& $coderef\->($child_handle, $info); .Ve .PP If the execution of \f(CW$coderef\fR returns a true value then \f(CW\*(C`visit_child_handles\*(C'\fR is called on that child handle and passed the returned value as \f(CW$info\fR. .PP For example: .PP .Vb 7 \& # count database connections with names (DSN) matching a pattern \& my $connections = 0; \& $dbh\->{Driver}\->visit_child_handles(sub { \& my ($h, $info) = @_; \& ++$connections if $h\->{Name} =~ /foo/; \& return 0; # don\*(Aqt visit kids \& }) .Ve .PP See also \*(L"visit_handles\*(R". .SH "ATTRIBUTES COMMON TO ALL HANDLES" .IX Header "ATTRIBUTES COMMON TO ALL HANDLES" These attributes are common to all types of \s-1DBI\s0 handles. .PP Some attributes are inherited by child handles. That is, the value of an inherited attribute in a newly created statement handle is the same as the value in the parent database handle. Changes to attributes in the new statement handle do not affect the parent database handle and changes to the database handle do not affect existing statement handles, only future ones. .PP Attempting to set or get the value of an unknown attribute generates a warning, except for private driver specific attributes (which all have names starting with a lowercase letter). .PP Example: .PP .Vb 2 \& $h\->{AttributeName} = ...; # set/write \& ... = $h\->{AttributeName}; # get/read .Ve .PP \fI\f(CI\*(C`Warn\*(C'\fI\fR .IX Subsection "Warn" .PP Type: boolean, inherited .PP The \f(CW\*(C`Warn\*(C'\fR attribute enables useful warnings for certain bad practices. It is enabled by default and should only be disabled in rare circumstances. Since warnings are generated using the Perl \&\f(CW\*(C`warn\*(C'\fR function, they can be intercepted using the Perl \f(CW$SIG{_\|_WARN_\|_}\fR hook. .PP The \f(CW\*(C`Warn\*(C'\fR attribute is not related to the \f(CW\*(C`PrintWarn\*(C'\fR attribute. .PP \fI\f(CI\*(C`Active\*(C'\fI\fR .IX Subsection "Active" .PP Type: boolean, read-only .PP The \f(CW\*(C`Active\*(C'\fR attribute is true if the handle object is \*(L"active\*(R". This is rarely used in applications. The exact meaning of active is somewhat vague at the moment. For a database handle it typically means that the handle is connected to a database (\f(CW\*(C`$dbh\->disconnect\*(C'\fR sets \f(CW\*(C`Active\*(C'\fR off). For a statement handle it typically means that the handle is a \f(CW\*(C`SELECT\*(C'\fR that may have more data to fetch. (Fetching all the data or calling \f(CW\*(C`$sth\->finish\*(C'\fR sets \f(CW\*(C`Active\*(C'\fR off.) .PP \fI\f(CI\*(C`Executed\*(C'\fI\fR .IX Subsection "Executed" .PP Type: boolean .PP The \f(CW\*(C`Executed\*(C'\fR attribute is true if the handle object has been \*(L"executed\*(R". Currently only the \f(CW$dbh\fR \fBdo()\fR method and the \f(CW$sth\fR \fBexecute()\fR, \fBexecute_array()\fR, and \fBexecute_for_fetch()\fR methods set the \f(CW\*(C`Executed\*(C'\fR attribute. .PP When it's set on a handle it is also set on the parent handle at the same time. So calling \fBexecute()\fR on a \f(CW$sth\fR also sets the \f(CW\*(C`Executed\*(C'\fR attribute on the parent \f(CW$dbh\fR. .PP The \f(CW\*(C`Executed\*(C'\fR attribute for a database handle is cleared by the \fBcommit()\fR and \&\fBrollback()\fR methods (even if they fail). The \f(CW\*(C`Executed\*(C'\fR attribute of a statement handle is not cleared by the \s-1DBI\s0 under any circumstances and so acts as a permanent record of whether the statement handle was ever used. .PP The \f(CW\*(C`Executed\*(C'\fR attribute was added in \s-1DBI 1.41.\s0 .PP \fI\f(CI\*(C`Kids\*(C'\fI\fR .IX Subsection "Kids" .PP Type: integer, read-only .PP For a driver handle, \f(CW\*(C`Kids\*(C'\fR is the number of currently existing database handles that were created from that driver handle. For a database handle, \f(CW\*(C`Kids\*(C'\fR is the number of currently existing statement handles that were created from that database handle. For a statement handle, the value is zero. .PP \fI\f(CI\*(C`ActiveKids\*(C'\fI\fR .IX Subsection "ActiveKids" .PP Type: integer, read-only .PP Like \f(CW\*(C`Kids\*(C'\fR, but only counting those that are \f(CW\*(C`Active\*(C'\fR (as above). .PP \fI\f(CI\*(C`CachedKids\*(C'\fI\fR .IX Subsection "CachedKids" .PP Type: hash ref .PP For a database handle, \f(CW\*(C`CachedKids\*(C'\fR returns a reference to the cache (hash) of statement handles created by the \*(L"prepare_cached\*(R" method. For a driver handle, returns a reference to the cache (hash) of database handles created by the \*(L"connect_cached\*(R" method. .PP \fI\f(CI\*(C`Type\*(C'\fI\fR .IX Subsection "Type" .PP Type: scalar, read-only .PP The \f(CW\*(C`Type\*(C'\fR attribute identifies the type of a \s-1DBI\s0 handle. Returns \&\*(L"dr\*(R" for driver handles, \*(L"db\*(R" for database handles and \*(L"st\*(R" for statement handles. .PP \fI\f(CI\*(C`ChildHandles\*(C'\fI\fR .IX Subsection "ChildHandles" .PP Type: array ref .PP The ChildHandles attribute contains a reference to an array of all the handles created by this handle which are still accessible. The contents of the array are weak-refs and will become undef when the handle goes out of scope. (They're cleared out occasionally.) .PP \&\f(CW\*(C`ChildHandles\*(C'\fR returns undef if your perl version does not support weak references (check the Scalar::Util module). The referenced array returned should be treated as read-only. .PP For example, to enumerate all driver handles, database handles and statement handles: .PP .Vb 6 \& sub show_child_handles { \& my ($h, $level) = @_; \& printf "%sh %s %s\en", $h\->{Type}, "\et" x $level, $h; \& show_child_handles($_, $level + 1) \& for (grep { defined } @{$h\->{ChildHandles}}); \& } \& \& my %drivers = DBI\->installed_drivers(); \& show_child_handles($_, 0) for (values %drivers); .Ve .PP \fI\f(CI\*(C`CompatMode\*(C'\fI\fR .IX Subsection "CompatMode" .PP Type: boolean, inherited .PP The \f(CW\*(C`CompatMode\*(C'\fR attribute is used by emulation layers (such as Oraperl) to enable compatible behaviour in the underlying driver (e.g., DBD::Oracle) for this handle. Not normally set by application code. .PP It also has the effect of disabling the 'quick \s-1FETCH\s0' of attribute values from the handles attribute cache. So all attribute values are handled by the drivers own \s-1FETCH\s0 method. This makes them slightly slower but is useful for special-purpose drivers like DBD::Multiplex. .PP \fI\f(CI\*(C`InactiveDestroy\*(C'\fI\fR .IX Subsection "InactiveDestroy" .PP Type: boolean .PP The default value, false, means a handle will be fully destroyed as normal when the last reference to it is removed, just as you'd expect. .PP If set true then the handle will be treated by the \s-1DESTROY\s0 as if it was no longer Active, and so the \fIdatabase engine\fR related effects of DESTROYing a handle will be skipped. Think of the name as meaning 'treat the handle as not-Active in the \s-1DESTROY\s0 method'. .PP For a database handle, this attribute does not disable an \fIexplicit\fR call to the disconnect method, only the implicit call from \s-1DESTROY\s0 that happens if the handle is still marked as \f(CW\*(C`Active\*(C'\fR. .PP This attribute is specifically designed for use in Unix applications that \*(L"fork\*(R" child processes. For some drivers, when the child process exits the destruction of inherited handles cause the corresponding handles in the parent process to cease working. .PP Either the parent or the child process, but not both, should set \&\f(CW\*(C`InactiveDestroy\*(C'\fR true on all their shared handles. Alternatively, and preferably, the \*(L"AutoInactiveDestroy\*(R" can be set in the parent on connect. .PP To help tracing applications using fork the process id is shown in the trace log whenever a \s-1DBI\s0 or handle \fBtrace()\fR method is called. The process id also shown for \fIevery\fR method call if the \s-1DBI\s0 trace level (not handle trace level) is set high enough to show the trace from the \s-1DBI\s0's method dispatcher, e.g. >= 9. .PP \fI\f(CI\*(C`AutoInactiveDestroy\*(C'\fI\fR .IX Subsection "AutoInactiveDestroy" .PP Type: boolean, inherited .PP The \*(L"InactiveDestroy\*(R" attribute, described above, needs to be explicitly set in the child process after a \fBfork()\fR, on every active database and statement handle. This is a problem if the code that performs the \fBfork()\fR is not under your control, perhaps in a third-party module. Use \f(CW\*(C`AutoInactiveDestroy\*(C'\fR to get around this situation. .PP If set true, the \s-1DESTROY\s0 method will check the process id of the handle and, if different from the current process id, it will set the \fIInactiveDestroy\fR attribute. It is strongly recommended that \f(CW\*(C`AutoInactiveDestroy\*(C'\fR is enabled on all new code (it's only not enabled by default to avoid backwards compatibility problems). .PP This is the example it's designed to deal with: .PP .Vb 4 \& my $dbh = DBI\->connect(...); \& some_code_that_forks(); # Perhaps without your knowledge \& # Child process dies, destroying the inherited dbh \& $dbh\->do(...); # Breaks because parent $dbh is now broken .Ve .PP The \f(CW\*(C`AutoInactiveDestroy\*(C'\fR attribute was added in \s-1DBI 1.614.\s0 .PP \fI\f(CI\*(C`PrintWarn\*(C'\fI\fR .IX Subsection "PrintWarn" .PP Type: boolean, inherited .PP The \f(CW\*(C`PrintWarn\*(C'\fR attribute controls the printing of warnings recorded by the driver. When set to a true value (the default) the \s-1DBI\s0 will check method calls to see if a warning condition has been set. If so, the \s-1DBI\s0 will effectively do a \f(CW\*(C`warn("$class $method warning: $DBI::errstr")\*(C'\fR where \f(CW$class\fR is the driver class and \f(CW$method\fR is the name of the method which failed. E.g., .PP .Vb 1 \& DBD::Oracle::db execute warning: ... warning text here ... .Ve .PP If desired, the warnings can be caught and processed using a \f(CW$SIG{_\|_WARN_\|_}\fR handler or modules like CGI::Carp and CGI::ErrorWrap. .PP See also \*(L"set_err\*(R" for how warnings are recorded and \*(L"HandleSetErr\*(R" for how to influence it. .PP Fetching the full details of warnings can require an extra round-trip to the database server for some drivers. In which case the driver may opt to only fetch the full details of warnings if the \f(CW\*(C`PrintWarn\*(C'\fR attribute is true. If \f(CW\*(C`PrintWarn\*(C'\fR is false then these drivers should still indicate the fact that there were warnings by setting the warning string to, for example: \*(L"3 warnings\*(R". .PP \fI\f(CI\*(C`PrintError\*(C'\fI\fR .IX Subsection "PrintError" .PP Type: boolean, inherited .PP The \f(CW\*(C`PrintError\*(C'\fR attribute can be used to force errors to generate warnings (using \&\f(CW\*(C`warn\*(C'\fR) in addition to returning error codes in the normal way. When set \&\*(L"on\*(R", any method which results in an error occurring will cause the \s-1DBI\s0 to effectively do a \f(CW\*(C`warn("$class $method failed: $DBI::errstr")\*(C'\fR where \f(CW$class\fR is the driver class and \f(CW$method\fR is the name of the method which failed. E.g., .PP .Vb 1 \& DBD::Oracle::db prepare failed: ... error text here ... .Ve .PP By default, \f(CW\*(C`DBI\->connect\*(C'\fR sets \f(CW\*(C`PrintError\*(C'\fR \*(L"on\*(R". .PP If desired, the warnings can be caught and processed using a \f(CW$SIG{_\|_WARN_\|_}\fR handler or modules like CGI::Carp and CGI::ErrorWrap. .PP \fI\f(CI\*(C`RaiseWarn\*(C'\fI\fR .IX Subsection "RaiseWarn" .PP Type: boolean, inherited .PP The \f(CW\*(C`RaiseWarn\*(C'\fR attribute can be used to force warnings to raise exceptions rather then simply printing them. It is \*(L"off\*(R" by default. When set \*(L"on\*(R", any method which sets warning condition will cause the \s-1DBI\s0 to effectively do a \f(CW\*(C`die("$class $method warning: $DBI::errstr")\*(C'\fR, where \f(CW$class\fR is the driver class and \f(CW$method\fR is the name of the method that sets warning condition. E.g., .PP .Vb 1 \& DBD::Oracle::db execute warning: ... warning text here ... .Ve .PP If you turn \f(CW\*(C`RaiseWarn\*(C'\fR on then you'd normally turn \f(CW\*(C`PrintWarn\*(C'\fR off. If \f(CW\*(C`PrintWarn\*(C'\fR is also on, then the \f(CW\*(C`PrintWarn\*(C'\fR is done first (naturally). .PP This attribute was added in \s-1DBI 1.643.\s0 .PP \fI\f(CI\*(C`RaiseError\*(C'\fI\fR .IX Subsection "RaiseError" .PP Type: boolean, inherited .PP The \f(CW\*(C`RaiseError\*(C'\fR attribute can be used to force errors to raise exceptions rather than simply return error codes in the normal way. It is \*(L"off\*(R" by default. When set \*(L"on\*(R", any method which results in an error will cause the \s-1DBI\s0 to effectively do a \f(CW\*(C`die("$class $method failed: $DBI::errstr")\*(C'\fR, where \f(CW$class\fR is the driver class and \f(CW$method\fR is the name of the method that failed. E.g., .PP .Vb 1 \& DBD::Oracle::db prepare failed: ... error text here ... .Ve .PP If you turn \f(CW\*(C`RaiseError\*(C'\fR on then you'd normally turn \f(CW\*(C`PrintError\*(C'\fR off. If \f(CW\*(C`PrintError\*(C'\fR is also on, then the \f(CW\*(C`PrintError\*(C'\fR is done first (naturally). .PP Typically \f(CW\*(C`RaiseError\*(C'\fR is used in conjunction with \f(CW\*(C`eval\*(C'\fR, or a module like Try::Tiny or TryCatch, to catch the exception that's been thrown and handle it. For example: .PP .Vb 1 \& use Try::Tiny; \& \& try { \& ... \& $sth\->execute(); \& ... \& } catch { \& # $sth\->err and $DBI::err will be true if error was from DBI \& warn $_; # print the error (which Try::Tiny puts into $_) \& ... # do whatever you need to deal with the error \& }; .Ve .PP In the catch block the \f(CW$DBI::lasth\fR variable can be useful for diagnosis and reporting if you can't be sure which handle triggered the error. For example, \f(CW$DBI::lasth\fR\->{Type} and \f(CW$DBI::lasth\fR\->{Statement}. .PP See also \*(L"Transactions\*(R". .PP If you want to temporarily turn \f(CW\*(C`RaiseError\*(C'\fR off (inside a library function that is likely to fail, for example), the recommended way is like this: .PP .Vb 4 \& { \& local $h\->{RaiseError}; # localize and turn off for this block \& ... \& } .Ve .PP The original value will automatically and reliably be restored by Perl, regardless of how the block is exited. The same logic applies to other attributes, including \f(CW\*(C`PrintError\*(C'\fR. .PP \fI\f(CI\*(C`HandleError\*(C'\fI\fR .IX Subsection "HandleError" .PP Type: code ref, inherited .PP The \f(CW\*(C`HandleError\*(C'\fR attribute can be used to provide your own alternative behaviour in case of errors. If set to a reference to a subroutine then that subroutine is called when an error is detected (at the same point that \&\f(CW\*(C`RaiseError\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR are handled). It is called also when \&\f(CW\*(C`RaiseWarn\*(C'\fR is enabled and a warning is detected. .PP The subroutine is called with three parameters: the error message string that \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`RaiseWarn\*(C'\fR or \f(CW\*(C`PrintError\*(C'\fR would use, the \s-1DBI\s0 handle being used, and the first value being returned by the method that failed (typically undef). .PP If the subroutine returns a false value then the \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`RaiseWarn\*(C'\fR and/or \f(CW\*(C`PrintError\*(C'\fR attributes are checked and acted upon as normal. .PP For example, to \f(CW\*(C`die\*(C'\fR with a full stack trace for any error: .PP .Vb 2 \& use Carp; \& $h\->{HandleError} = sub { confess(shift) }; .Ve .PP Or to turn errors into exceptions: .PP .Vb 2 \& use Exception; # or your own favourite exception module \& $h\->{HandleError} = sub { Exception\->new(\*(AqDBI\*(Aq)\->raise($_[0]) }; .Ve .PP It is possible to 'stack' multiple HandleError handlers by using closures: .PP .Vb 7 \& sub your_subroutine { \& my $previous_handler = $h\->{HandleError}; \& $h\->{HandleError} = sub { \& return 1 if $previous_handler and &$previous_handler(@_); \& ... your code here ... \& }; \& } .Ve .PP Using a \f(CW\*(C`my\*(C'\fR inside a subroutine to store the previous \f(CW\*(C`HandleError\*(C'\fR value is important. See perlsub and perlref for more information about \fIclosures\fR. .PP It is possible for \f(CW\*(C`HandleError\*(C'\fR to alter the error message that will be used by \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`RaiseWarn\*(C'\fR and \f(CW\*(C`PrintError\*(C'\fR if it returns false. It can do that by altering the value of \f(CW$_\fR[0]. This example appends a stack trace to all errors and, unlike the previous example using Carp::confess, this will work \f(CW\*(C`PrintError\*(C'\fR as well as \f(CW\*(C`RaiseError\*(C'\fR: .PP .Vb 1 \& $h\->{HandleError} = sub { $_[0]=Carp::longmess($_[0]); 0; }; .Ve .PP It is also possible for \f(CW\*(C`HandleError\*(C'\fR to hide an error, to a limited degree, by using \*(L"set_err\*(R" to reset \f(CW$DBI::err\fR and \f(CW$DBI::errstr\fR, and altering the return value of the failed method. For example: .PP .Vb 7 \& $h\->{HandleError} = sub { \& return 0 unless $_[0] =~ /^\eS+ fetchrow_arrayref failed:/; \& return 0 unless $_[1]\->err == 1234; # the error to \*(Aqhide\*(Aq \& $h\->set_err(undef,undef); # turn off the error \& $_[2] = [ ... ]; # supply alternative return value \& return 1; \& }; .Ve .PP This only works for methods which return a single value and is hard to make reliable (avoiding infinite loops, for example) and so isn't recommended for general use! If you find a \fIgood\fR use for it then please let me know. .PP \fI\f(CI\*(C`HandleSetErr\*(C'\fI\fR .IX Subsection "HandleSetErr" .PP Type: code ref, inherited .PP The \f(CW\*(C`HandleSetErr\*(C'\fR attribute can be used to intercept the setting of handle \f(CW\*(C`err\*(C'\fR, \f(CW\*(C`errstr\*(C'\fR, and \f(CW\*(C`state\*(C'\fR values. If set to a reference to a subroutine then that subroutine is called whenever \fBset_err()\fR is called, typically by the driver or a subclass. .PP The subroutine is called with five arguments, the first five that were passed to \fBset_err()\fR: the handle, the \f(CW\*(C`err\*(C'\fR, \f(CW\*(C`errstr\*(C'\fR, and \&\f(CW\*(C`state\*(C'\fR values being set, and the method name. These can be altered by changing the values in the \f(CW@_\fR array. The return value affects \&\fBset_err()\fR behaviour, see \*(L"set_err\*(R" for details. .PP It is possible to 'stack' multiple HandleSetErr handlers by using closures. See \*(L"HandleError\*(R" for an example. .PP The \f(CW\*(C`HandleSetErr\*(C'\fR and \f(CW\*(C`HandleError\*(C'\fR subroutines differ in subtle but significant ways. HandleError is only invoked at the point where the \s-1DBI\s0 is about to return to the application with \f(CW\*(C`err\*(C'\fR set true. It's not invoked by the failure of a method that's been called by another \s-1DBI\s0 method. HandleSetErr, on the other hand, is called whenever \fBset_err()\fR is called with a defined \f(CW\*(C`err\*(C'\fR value, even if false. So it's not just for errors, despite the name, but also warn and info states. The \fBset_err()\fR method, and thus HandleSetErr, may be called multiple times within a method and is usually invoked from deep within driver code. .PP In theory a driver can use the return value from HandleSetErr via \&\fBset_err()\fR to decide whether to continue or not. If \fBset_err()\fR returns an empty list, indicating that the HandleSetErr code has 'handled' the 'error', the driver could then continue instead of failing (if that's a reasonable thing to do). This isn't excepted to be common and any such cases should be clearly marked in the driver documentation and discussed on the dbi-dev mailing list. .PP The \f(CW\*(C`HandleSetErr\*(C'\fR attribute was added in \s-1DBI 1.41.\s0 .PP \fI\f(CI\*(C`ErrCount\*(C'\fI\fR .IX Subsection "ErrCount" .PP Type: unsigned integer .PP The \f(CW\*(C`ErrCount\*(C'\fR attribute is incremented whenever the \fBset_err()\fR method records an error. It isn't incremented by warnings or information states. It is not reset by the \s-1DBI\s0 at any time. .PP The \f(CW\*(C`ErrCount\*(C'\fR attribute was added in \s-1DBI 1.41.\s0 Older drivers may not have been updated to use \fBset_err()\fR to record errors and so this attribute may not be incremented when using them. .PP \fI\f(CI\*(C`ShowErrorStatement\*(C'\fI\fR .IX Subsection "ShowErrorStatement" .PP Type: boolean, inherited .PP The \f(CW\*(C`ShowErrorStatement\*(C'\fR attribute can be used to cause the relevant Statement text to be appended to the error messages generated by the \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`PrintError\*(C'\fR, \f(CW\*(C`RaiseWarn\*(C'\fR and \f(CW\*(C`PrintWarn\*(C'\fR attributes. Only applies to errors on statement handles plus the \fBprepare()\fR, \fBdo()\fR, and the various \f(CW\*(C`select*()\*(C'\fR database handle methods. (The exact format of the appended text is subject to change.) .PP If \f(CW\*(C`$h\->{ParamValues}\*(C'\fR returns a hash reference of parameter (placeholder) values then those are formatted and appended to the end of the Statement text in the error message. .PP \fI\f(CI\*(C`TraceLevel\*(C'\fI\fR .IX Subsection "TraceLevel" .PP Type: integer, inherited .PP The \f(CW\*(C`TraceLevel\*(C'\fR attribute can be used as an alternative to the \&\*(L"trace\*(R" method to set the \s-1DBI\s0 trace level and trace flags for a specific handle. See \*(L"\s-1TRACING\*(R"\s0 for more details. .PP The \f(CW\*(C`TraceLevel\*(C'\fR attribute is especially useful combined with \&\f(CW\*(C`local\*(C'\fR to alter the trace settings for just a single block of code. .PP \fI\f(CI\*(C`FetchHashKeyName\*(C'\fI\fR .IX Subsection "FetchHashKeyName" .PP Type: string, inherited .PP The \f(CW\*(C`FetchHashKeyName\*(C'\fR attribute is used to specify whether the \fBfetchrow_hashref()\fR method should perform case conversion on the field names used for the hash keys. For historical reasons it defaults to '\f(CW\*(C`NAME\*(C'\fR' but it is recommended to set it to '\f(CW\*(C`NAME_lc\*(C'\fR' (convert to lower case) or '\f(CW\*(C`NAME_uc\*(C'\fR' (convert to upper case) according to your preference. It can only be set for driver and database handles. For statement handles the value is frozen when \fBprepare()\fR is called. .PP \fI\f(CI\*(C`ChopBlanks\*(C'\fI\fR .IX Subsection "ChopBlanks" .PP Type: boolean, inherited .PP The \f(CW\*(C`ChopBlanks\*(C'\fR attribute can be used to control the trimming of trailing space characters from fixed width character (\s-1CHAR\s0) fields. No other field types are affected, even where field values have trailing spaces. .PP The default is false (although it is possible that the default may change). Applications that need specific behaviour should set the attribute as needed. .PP Drivers are not required to support this attribute, but any driver which does not support it must arrange to return \f(CW\*(C`undef\*(C'\fR as the attribute value. .PP \fI\f(CI\*(C`LongReadLen\*(C'\fI\fR .IX Subsection "LongReadLen" .PP Type: unsigned integer, inherited .PP The \f(CW\*(C`LongReadLen\*(C'\fR attribute may be used to control the maximum length of 'long' type fields (\s-1LONG, BLOB, CLOB, MEMO,\s0 etc.) which the driver will read from the database automatically when it fetches each row of data. .PP The \f(CW\*(C`LongReadLen\*(C'\fR attribute only relates to fetching and reading long values; it is not involved in inserting or updating them. .PP A value of 0 means not to automatically fetch any long data. Drivers may return undef or an empty string for long fields when \&\f(CW\*(C`LongReadLen\*(C'\fR is 0. .PP The default is typically 0 (zero) or 80 bytes but may vary between drivers. Applications fetching long fields should set this value to slightly larger than the longest long field value to be fetched. .PP Some databases return some long types encoded as pairs of hex digits. For these types, \f(CW\*(C`LongReadLen\*(C'\fR relates to the underlying data length and not the doubled-up length of the encoded string. .PP Changing the value of \f(CW\*(C`LongReadLen\*(C'\fR for a statement handle after it has been \f(CW\*(C`prepare\*(C'\fR'd will typically have no effect, so it's common to set \f(CW\*(C`LongReadLen\*(C'\fR on the \f(CW$dbh\fR before calling \f(CW\*(C`prepare\*(C'\fR. .PP For most drivers the value used here has a direct effect on the memory used by the statement handle while it's active, so don't be too generous. If you can't be sure what value to use you could execute an extra select statement to determine the longest value. For example: .PP .Vb 7 \& $dbh\->{LongReadLen} = $dbh\->selectrow_array(qq{ \& SELECT MAX(OCTET_LENGTH(long_column_name)) \& FROM table WHERE ... \& }); \& $sth = $dbh\->prepare(qq{ \& SELECT long_column_name, ... FROM table WHERE ... \& }); .Ve .PP You may need to take extra care if the table can be modified between the first select and the second being executed. You may also need to use a different function if \s-1\fBOCTET_LENGTH\s0()\fR does not work for long types in your database. For example, for Sybase use \s-1\fBDATALENGTH\s0()\fR and for Oracle use \s-1\fBLENGTHB\s0()\fR. .PP See also \*(L"LongTruncOk\*(R" for information on truncation of long types. .PP \fI\f(CI\*(C`LongTruncOk\*(C'\fI\fR .IX Subsection "LongTruncOk" .PP Type: boolean, inherited .PP The \f(CW\*(C`LongTruncOk\*(C'\fR attribute may be used to control the effect of fetching a long field value which has been truncated (typically because it's longer than the value of the \f(CW\*(C`LongReadLen\*(C'\fR attribute). .PP By default, \f(CW\*(C`LongTruncOk\*(C'\fR is false and so fetching a long value that needs to be truncated will cause the fetch to fail. (Applications should always be sure to check for errors after a fetch loop in case an error, such as a divide by zero or long field truncation, caused the fetch to terminate prematurely.) .PP If a fetch fails due to a long field truncation when \f(CW\*(C`LongTruncOk\*(C'\fR is false, many drivers will allow you to continue fetching further rows. .PP See also \*(L"LongReadLen\*(R". .PP \fI\f(CI\*(C`TaintIn\*(C'\fI\fR .IX Subsection "TaintIn" .PP Type: boolean, inherited .PP If the \f(CW\*(C`TaintIn\*(C'\fR attribute is set to a true value \fIand\fR Perl is running in taint mode (e.g., started with the \f(CW\*(C`\-T\*(C'\fR option), then all the arguments to most \s-1DBI\s0 method calls are checked for being tainted. \fIThis may change.\fR .PP The attribute defaults to off, even if Perl is in taint mode. See perlsec for more about taint mode. If Perl is not running in taint mode, this attribute has no effect. .PP When fetching data that you trust you can turn off the TaintIn attribute, for that statement handle, for the duration of the fetch loop. .PP The \f(CW\*(C`TaintIn\*(C'\fR attribute was added in \s-1DBI 1.31.\s0 .PP \fI\f(CI\*(C`TaintOut\*(C'\fI\fR .IX Subsection "TaintOut" .PP Type: boolean, inherited .PP If the \f(CW\*(C`TaintOut\*(C'\fR attribute is set to a true value \fIand\fR Perl is running in taint mode (e.g., started with the \f(CW\*(C`\-T\*(C'\fR option), then most data fetched from the database is considered tainted. \fIThis may change.\fR .PP The attribute defaults to off, even if Perl is in taint mode. See perlsec for more about taint mode. If Perl is not running in taint mode, this attribute has no effect. .PP When fetching data that you trust you can turn off the TaintOut attribute, for that statement handle, for the duration of the fetch loop. .PP Currently only fetched data is tainted. It is possible that the results of other \s-1DBI\s0 method calls, and the value of fetched attributes, may also be tainted in future versions. That change may well break your applications unless you take great care now. If you use \s-1DBI\s0 Taint mode, please report your experience and any suggestions for changes. .PP The \f(CW\*(C`TaintOut\*(C'\fR attribute was added in \s-1DBI 1.31.\s0 .PP \fI\f(CI\*(C`Taint\*(C'\fI\fR .IX Subsection "Taint" .PP Type: boolean, inherited .PP The \f(CW\*(C`Taint\*(C'\fR attribute is a shortcut for \*(L"TaintIn\*(R" and \*(L"TaintOut\*(R" (it is also present for backwards compatibility). .PP Setting this attribute sets both \*(L"TaintIn\*(R" and \*(L"TaintOut\*(R", and retrieving it returns a true value if and only if \*(L"TaintIn\*(R" and \*(L"TaintOut\*(R" are both set to true values. .PP \fI\f(CI\*(C`Profile\*(C'\fI\fR .IX Subsection "Profile" .PP Type: inherited .PP The \f(CW\*(C`Profile\*(C'\fR attribute enables the collection and reporting of method call timing statistics. See the DBI::Profile module documentation for \fImuch\fR more detail. .PP The \f(CW\*(C`Profile\*(C'\fR attribute was added in \s-1DBI 1.24.\s0 .PP \fI\f(CI\*(C`ReadOnly\*(C'\fI\fR .IX Subsection "ReadOnly" .PP Type: boolean, inherited .PP An application can set the \f(CW\*(C`ReadOnly\*(C'\fR attribute of a handle to a true value to indicate that it will not be attempting to make any changes using that handle or any children of it. .PP Note that the exact definition of 'read only' is rather fuzzy. For more details see the documentation for the driver you're using. .PP If the driver can make the handle truly read-only then it should (unless doing so would have unpleasant side effect, like changing the consistency level from per-statement to per-session). Otherwise the attribute is simply advisory. .PP A driver can set the \f(CW\*(C`ReadOnly\*(C'\fR attribute itself to indicate that the data it is connected to cannot be changed for some reason. .PP If the driver cannot ensure the \f(CW\*(C`ReadOnly\*(C'\fR attribute is adhered to it will record a warning. In this case reading the \f(CW\*(C`ReadOnly\*(C'\fR attribute back after it is set true will return true even if the underlying driver cannot ensure this (so any application knows the application declared itself ReadOnly). .PP Library modules and proxy drivers can use the attribute to influence their behavior. For example, the DBD::Gofer driver considers the \&\f(CW\*(C`ReadOnly\*(C'\fR attribute when making a decision about whether to retry an operation that failed. .PP The attribute should be set to 1 or 0 (or undef). Other values are reserved. .PP \fI\f(CI\*(C`Callbacks\*(C'\fI\fR .IX Subsection "Callbacks" .PP Type: hash ref .PP The \s-1DBI\s0 callback mechanism lets you intercept, and optionally replace, any method call on a \s-1DBI\s0 handle. At the extreme, it lets you become a puppet master, deceiving the application in any way you want. .PP The \f(CW\*(C`Callbacks\*(C'\fR attribute is a hash reference where the keys are \s-1DBI\s0 method names and the values are code references. For each key naming a method, the \&\s-1DBI\s0 will execute the associated code reference before executing the method. .PP The arguments to the code reference will be the same as to the method, including the invocant (a database handle or statement handle). For example, say that to callback to some code on a call to \f(CW\*(C`prepare()\*(C'\fR: .PP .Vb 6 \& $dbh\->{Callbacks} = { \& prepare => sub { \& my ($dbh, $query, $attrs) = @_; \& print "Preparing q{$query}\en" \& }, \& }; .Ve .PP The callback would then be executed when you called the \f(CW\*(C`prepare()\*(C'\fR method: .PP .Vb 1 \& $dbh\->prepare(\*(AqSELECT 1\*(Aq); .Ve .PP And the output of course would be: .PP .Vb 1 \& Preparing q{SELECT 1} .Ve .PP Because callbacks are executed \fIbefore\fR the methods they're associated with, you can modify the arguments before they're passed on to the method call. For example, to make sure that all calls to \f(CW\*(C`prepare()\*(C'\fR are immediately prepared by DBD::Pg, add a callback that makes sure that the \f(CW\*(C`pg_prepare_now\*(C'\fR attribute is always set: .PP .Vb 9 \& my $dbh = DBI\->connect($dsn, $username, $auth, { \& Callbacks => { \& prepare => sub { \& $_[2] ||= {}; \& $_[2]\->{pg_prepare_now} = 1; \& return; # must return nothing \& }, \& } \& }); .Ve .PP Note that we are editing the contents of \f(CW@_\fR directly. In this case we've created the attributes hash if it's not passed to the \f(CW\*(C`prepare\*(C'\fR call. .PP You can also prevent the associated method from ever executing. While a callback executes, \f(CW$_\fR holds the method name. (This allows multiple callbacks to share the same code reference and still know what method was called.) To prevent the method from executing, simply \f(CW\*(C`undef $_\*(C'\fR. For example, if you wanted to disable calls to \&\f(CW\*(C`ping()\*(C'\fR, you could do this: .PP .Vb 8 \& $dbh\->{Callbacks} = { \& ping => sub { \& # tell dispatch to not call the method: \& undef $_; \& # return this value instead: \& return "42 bells"; \& } \& }; .Ve .PP As with other attributes, Callbacks can be specified on a handle or via the attributes to \f(CW\*(C`connect()\*(C'\fR. Callbacks can also be applied to a statement methods on a statement handle. For example: .PP .Vb 5 \& $sth\->{Callbacks} = { \& execute => sub { \& print "Executing ", shift\->{Statement}, "\en"; \& } \& }; .Ve .PP The \f(CW\*(C`Callbacks\*(C'\fR attribute of a database handle isn't copied to any statement handles it creates. So setting callbacks for a statement handle requires you to set the \f(CW\*(C`Callbacks\*(C'\fR attribute on the statement handle yourself, as in the example above, or use the special \f(CW\*(C`ChildCallbacks\*(C'\fR key described below. .PP \&\fBSpecial Keys in Callbacks Attribute\fR .PP In addition to \s-1DBI\s0 handle method names, the \f(CW\*(C`Callbacks\*(C'\fR hash reference supports four additional keys. .PP The first is the \f(CW\*(C`ChildCallbacks\*(C'\fR key. When a statement handle is created from a database handle the \f(CW\*(C`ChildCallbacks\*(C'\fR key of the database handle's \&\f(CW\*(C`Callbacks\*(C'\fR attribute, if any, becomes the new \f(CW\*(C`Callbacks\*(C'\fR attribute of the statement handle. This allows you to define callbacks for all statement handles created from a database handle. For example, if you wanted to count how many times \f(CW\*(C`execute\*(C'\fR was called in your application, you could write: .PP .Vb 8 \& my $exec_count = 0; \& my $dbh = DBI\->connect( $dsn, $username, $auth, { \& Callbacks => { \& ChildCallbacks => { \& execute => sub { $exec_count++; return; } \& } \& } \& }); \& \& END { \& print "The execute method was called $exec_count times\en"; \& } .Ve .PP The other three special keys are \f(CW\*(C`connect_cached.new\*(C'\fR, \&\f(CW\*(C`connect_cached.connected\*(C'\fR, and \f(CW\*(C`connect_cached.reused\*(C'\fR. These keys define callbacks that are called when \f(CW\*(C`connect_cached()\*(C'\fR is called, but allow different behaviors depending on whether a new handle is created or a handle is returned. The callback is invoked with these arguments: \&\f(CW\*(C`$dbh, $dsn, $user, $auth, $attr\*(C'\fR. .PP For example, some applications uses \f(CW\*(C`connect_cached()\*(C'\fR to connect with \&\f(CW\*(C`AutoCommit\*(C'\fR enabled and then disable \f(CW\*(C`AutoCommit\*(C'\fR temporarily for transactions. If \f(CW\*(C`connect_cached()\*(C'\fR is called during a transaction, perhaps in a utility method, then it might select the same cached handle and then force \&\f(CW\*(C`AutoCommit\*(C'\fR on, forcing a commit of the transaction. See the \*(L"connect_cached\*(R" documentation for one way to deal with that. Here we'll describe an alternative approach using a callback. .PP Because the \f(CW\*(C`connect_cached.new\*(C'\fR and \f(CW\*(C`connect_cached.reused\*(C'\fR callbacks are invoked before \f(CW\*(C`connect_cached()\*(C'\fR has applied the connect attributes, you can use them to edit the attributes that will be applied. To prevent a cached handle from having its transactions committed before it's returned, you can eliminate the \f(CW\*(C`AutoCommit\*(C'\fR attribute in a \f(CW\*(C`connect_cached.reused\*(C'\fR callback, like so: .PP .Vb 3 \& my $cb = { \& \*(Aqconnect_cached.reused\*(Aq => sub { delete $_[4]\->{AutoCommit} }, \& }; \& \& sub dbh { \& my $self = shift; \& DBI\->connect_cached( $dsn, $username, $auth, { \& PrintError => 0, \& RaiseError => 1, \& AutoCommit => 1, \& Callbacks => $cb, \& }); \& } .Ve .PP The upshot is that new database handles are created with \f(CW\*(C`AutoCommit\*(C'\fR enabled, while cached database handles are left in whatever transaction state they happened to be in when retrieved from the cache. .PP Note that we've also used a lexical for the callbacks hash reference. This is because \f(CW\*(C`connect_cached()\*(C'\fR returns a new database handle if any of the attributes passed to is have changed. If we used an inline hash reference, \&\f(CW\*(C`connect_cached()\*(C'\fR would return a new database handle every time. Which would rather defeat the purpose. .PP A more common application for callbacks is setting connection state only when a new connection is made (by \fBconnect()\fR or \fBconnect_cached()\fR). Adding a callback to the connected method (when using \f(CW\*(C`connect\*(C'\fR) or via \&\f(CW\*(C`connect_cached.connected\*(C'\fR (when useing \fBconnect_cached()\fR>) makes this easy. The \fBconnected()\fR method is a no-op by default (unless you subclass the \s-1DBI\s0 and change it). The \s-1DBI\s0 calls it to indicate that a new connection has been made and the connection attributes have all been set. You can give it a bit of added functionality by applying a callback to it. For example, to make sure that MySQL understands your application's ANSI-compliant \s-1SQL,\s0 set it up like so: .PP .Vb 10 \& my $dbh = DBI\->connect($dsn, $username, $auth, { \& Callbacks => { \& connected => sub { \& shift\->do(q{ \& SET SESSION sql_mode=\*(Aqansi,strict_trans_tables,no_auto_value_on_zero\*(Aq; \& }); \& return; \& }, \& } \& }); .Ve .PP If you're using \f(CW\*(C`connect_cached()\*(C'\fR, use the \f(CW\*(C`connect_cached.connected\*(C'\fR callback, instead. This is because \f(CW\*(C`connected()\*(C'\fR is called for both new and reused database handles, but you want to execute a callback only the when a new database handle is returned. For example, to set the time zone on connection to a PostgreSQL database, try this: .PP .Vb 5 \& my $cb = { \& \*(Aqconnect_cached.connected\*(Aq => sub { \& shift\->do(\*(AqSET timezone = UTC\*(Aq); \& } \& }; \& \& sub dbh { \& my $self = shift; \& DBI\->connect_cached( $dsn, $username, $auth, { Callbacks => $cb }); \& } .Ve .PP One significant limitation with callbacks is that there can only be one per method per handle. This means it's easy for one use of callbacks to interfere with, or typically simply overwrite, another use of callbacks. For this reason modules using callbacks should document the fact clearly so application authors can tell if use of callbacks by the module will clash with use of callbacks by the application. .PP You might be able to work around this issue by taking a copy of the original callback and calling it within your own. For example: .PP .Vb 8 \& my $prev_cb = $h\->{Callbacks}{method_name}; \& $h\->{Callbacks}{method_name} = sub { \& if ($prev_cb) { \& my @result = $prev_cb\->(@_); \& return @result if not $_; # $prev_cb vetoed call \& } \& ... your callback logic here ... \& }; .Ve .PP \fI\f(CI\*(C`private_your_module_name_*\*(C'\fI\fR .IX Subsection "private_your_module_name_*" .PP The \s-1DBI\s0 provides a way to store extra information in a \s-1DBI\s0 handle as \&\*(L"private\*(R" attributes. The \s-1DBI\s0 will allow you to store and retrieve any attribute which has a name starting with "\f(CW\*(C`private_\*(C'\fR". .PP It is \fIstrongly\fR recommended that you use just \fIone\fR private attribute (e.g., use a hash ref) \fIand\fR give it a long and unambiguous name that includes the module or application name that the attribute relates to (e.g., "\f(CW\*(C`private_YourFullModuleName_thingy\*(C'\fR"). .PP Because of the way the Perl tie mechanism works you cannot reliably use the \f(CW\*(C`||=\*(C'\fR operator directly to initialise the attribute, like this: .PP .Vb 1 \& my $foo = $dbh\->{private_yourmodname_foo} ||= { ... }; # WRONG .Ve .PP you should use a two step approach like this: .PP .Vb 2 \& my $foo = $dbh\->{private_yourmodname_foo}; \& $foo ||= $dbh\->{private_yourmodname_foo} = { ... }; .Ve .PP This attribute is primarily of interest to people sub-classing \s-1DBI,\s0 or for applications to piggy-back extra information onto \s-1DBI\s0 handles. .SH "DBI DATABASE HANDLE OBJECTS" .IX Header "DBI DATABASE HANDLE OBJECTS" This section covers the methods and attributes associated with database handles. .SS "Database Handle Methods" .IX Subsection "Database Handle Methods" The following methods are specified for \s-1DBI\s0 database handles: .PP \fI\f(CI\*(C`clone\*(C'\fI\fR .IX Subsection "clone" .PP .Vb 1 \& $new_dbh = $dbh\->clone(\e%attr); .Ve .PP The \f(CW\*(C`clone\*(C'\fR method duplicates the \f(CW$dbh\fR connection by connecting with the same parameters ($dsn, \f(CW$user\fR, \f(CW$password\fR) as originally used. .PP The attributes for the cloned connect are the same as those used for the \fIoriginal\fR connect, with any other attributes in \f(CW\*(C`\e%attr\*(C'\fR merged over them. Effectively the same as doing: .PP .Vb 1 \& %attributes_used = ( %original_attributes, %attr ); .Ve .PP If \e%attr is not given then it defaults to a hash containing all the attributes in the attribute cache of \f(CW$dbh\fR excluding any non-code references, plus the main boolean attributes (RaiseError, PrintError, AutoCommit, etc.). \fIThis behaviour is unreliable and so use of clone without an argument is deprecated and may cause a warning in a future release.\fR .PP The clone method can be used even if the database handle is disconnected. .PP The \f(CW\*(C`clone\*(C'\fR method was added in \s-1DBI 1.33.\s0 .PP \fI\f(CI\*(C`data_sources\*(C'\fI\fR .IX Subsection "data_sources" .PP .Vb 2 \& @ary = $dbh\->data_sources(); \& @ary = $dbh\->data_sources(\e%attr); .Ve .PP Returns a list of data sources (databases) available via the \f(CW$dbh\fR driver's \fBdata_sources()\fR method, plus any extra data sources that the driver can discover via the connected \f(CW$dbh\fR. Typically the extra data sources are other databases managed by the same server process that the \f(CW$dbh\fR is connected to. .PP Data sources are returned in a form suitable for passing to the \&\*(L"connect\*(R" method (that is, they will include the "\f(CW\*(C`dbi:$driver:\*(C'\fR" prefix). .PP The \fBdata_sources()\fR method, for a \f(CW$dbh\fR, was added in \s-1DBI 1.38.\s0 .PP \fI\f(CI\*(C`do\*(C'\fI\fR .IX Subsection "do" .PP .Vb 3 \& $rows = $dbh\->do($statement) or die $dbh\->errstr; \& $rows = $dbh\->do($statement, \e%attr) or die $dbh\->errstr; \& $rows = $dbh\->do($statement, \e%attr, @bind_values) or die ... .Ve .PP Prepare and execute a single statement. Returns the number of rows affected or \f(CW\*(C`undef\*(C'\fR on error. A return value of \f(CW\*(C`\-1\*(C'\fR means the number of rows is not known, not applicable, or not available. .PP This method is typically most useful for \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statements that either cannot be prepared in advance (due to a limitation of the driver) or do not need to be executed repeatedly. It should not be used for \f(CW\*(C`SELECT\*(C'\fR statements because it does not return a statement handle (so you can't fetch any data). .PP The default \f(CW\*(C`do\*(C'\fR method is logically similar to: .PP .Vb 7 \& sub do { \& my($dbh, $statement, $attr, @bind_values) = @_; \& my $sth = $dbh\->prepare($statement, $attr) or return undef; \& $sth\->execute(@bind_values) or return undef; \& my $rows = $sth\->rows; \& ($rows == 0) ? "0E0" : $rows; # always return true if no error \& } .Ve .PP For example: .PP .Vb 4 \& my $rows_deleted = $dbh\->do(q{ \& DELETE FROM table \& WHERE status = ? \& }, undef, \*(AqDONE\*(Aq) or die $dbh\->errstr; .Ve .PP Using placeholders and \f(CW@bind_values\fR with the \f(CW\*(C`do\*(C'\fR method can be useful because it avoids the need to correctly quote any variables in the \f(CW$statement\fR. But if you'll be executing the statement many times then it's more efficient to \f(CW\*(C`prepare\*(C'\fR it once and call \&\f(CW\*(C`execute\*(C'\fR many times instead. .PP The \f(CW\*(C`q{...}\*(C'\fR style quoting used in this example avoids clashing with quotes that may be used in the \s-1SQL\s0 statement. Use the double-quote-like \&\f(CW\*(C`qq{...}\*(C'\fR operator if you want to interpolate variables into the string. See \*(L"Quote and Quote-like Operators\*(R" in perlop for more details. .PP Note drivers are free to avoid the overhead of creating an \s-1DBI\s0 statement handle for \fBdo()\fR, especially if there are no parameters. In this case error handlers, if invoked during \fBdo()\fR, will be passed the database handle. .PP \fI\f(CI\*(C`last_insert_id\*(C'\fI\fR .IX Subsection "last_insert_id" .PP .Vb 3 \& $rv = $dbh\->last_insert_id(); \& $rv = $dbh\->last_insert_id($catalog, $schema, $table, $field); \& $rv = $dbh\->last_insert_id($catalog, $schema, $table, $field, \e%attr); .Ve .PP Returns a value 'identifying' the row just inserted, if possible. Typically this would be a value assigned by the database server to a column with an \fIauto_increment\fR or \fIserial\fR type. Returns undef if the driver does not support the method or can't determine the value. .PP The \f(CW$catalog\fR, \f(CW$schema\fR, \f(CW$table\fR, and \f(CW$field\fR parameters may be required for some drivers (see below). If you don't know the parameter values and your driver does not need them, then use \f(CW\*(C`undef\*(C'\fR for each. .PP There are several caveats to be aware of with this method if you want to use it for portable applications: .PP \&\fB*\fR For some drivers the value may only available immediately after the insert statement has executed (e.g., mysql, Informix). .PP \&\fB*\fR For some drivers the \f(CW$catalog\fR, \f(CW$schema\fR, \f(CW$table\fR, and \f(CW$field\fR parameters are required, for others they are ignored (e.g., mysql). .PP \&\fB*\fR Drivers may return an indeterminate value if no insert has been performed yet. .PP \&\fB*\fR For some drivers the value may only be available if placeholders have \fInot\fR been used (e.g., Sybase, \s-1MS SQL\s0). In this case the value returned would be from the last non-placeholder insert statement. .PP \&\fB*\fR Some drivers may need driver-specific hints about how to get the value. For example, being told the name of the database 'sequence' object that holds the value. Any such hints are passed as driver-specific attributes in the \e%attr parameter. .PP \&\fB*\fR If the underlying database offers nothing better, then some drivers may attempt to implement this method by executing "\f(CW\*(C`select max($field) from $table\*(C'\fR". Drivers using any approach like this should issue a warning if \f(CW\*(C`AutoCommit\*(C'\fR is true because it is generally unsafe \- another process may have modified the table between your insert and the select. For situations where you know it is safe, such as when you have locked the table, you can silence the warning by passing \f(CW\*(C`Warn\*(C'\fR => 0 in \e%attr. .PP \&\fB*\fR If no insert has been performed yet, or the last insert failed, then the value is implementation defined. .PP Given all the caveats above, it's clear that this method must be used with care. .PP The \f(CW\*(C`last_insert_id\*(C'\fR method was added in \s-1DBI 1.38.\s0 .PP \fI\f(CI\*(C`selectrow_array\*(C'\fI\fR .IX Subsection "selectrow_array" .PP .Vb 3 \& @row_ary = $dbh\->selectrow_array($statement); \& @row_ary = $dbh\->selectrow_array($statement, \e%attr); \& @row_ary = $dbh\->selectrow_array($statement, \e%attr, @bind_values); .Ve .PP This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and \&\*(L"fetchrow_array\*(R" into a single call. If called in a list context, it returns the first row of data from the statement. The \f(CW$statement\fR parameter can be a previously prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. .PP If any method fails, and \*(L"RaiseError\*(R" is not set, \f(CW\*(C`selectrow_array\*(C'\fR will return an empty list. .PP If called in a scalar context for a statement handle that has more than one column, it is undefined whether the driver will return the value of the first column or the last. So don't do that. Also, in a scalar context, an \f(CW\*(C`undef\*(C'\fR is returned if there are no more rows or if an error occurred. That \f(CW\*(C`undef\*(C'\fR can't be distinguished from an \f(CW\*(C`undef\*(C'\fR returned because the first field value was \s-1NULL.\s0 For these reasons you should exercise some caution if you use \&\f(CW\*(C`selectrow_array\*(C'\fR in a scalar context, or just don't do that. .PP \fI\f(CI\*(C`selectrow_arrayref\*(C'\fI\fR .IX Subsection "selectrow_arrayref" .PP .Vb 3 \& $ary_ref = $dbh\->selectrow_arrayref($statement); \& $ary_ref = $dbh\->selectrow_arrayref($statement, \e%attr); \& $ary_ref = $dbh\->selectrow_arrayref($statement, \e%attr, @bind_values); .Ve .PP This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and \&\*(L"fetchrow_arrayref\*(R" into a single call. It returns the first row of data from the statement. The \f(CW$statement\fR parameter can be a previously prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. .PP If any method fails, and \*(L"RaiseError\*(R" is not set, \f(CW\*(C`selectrow_arrayref\*(C'\fR will return undef. .PP \fI\f(CI\*(C`selectrow_hashref\*(C'\fI\fR .IX Subsection "selectrow_hashref" .PP .Vb 3 \& $hash_ref = $dbh\->selectrow_hashref($statement); \& $hash_ref = $dbh\->selectrow_hashref($statement, \e%attr); \& $hash_ref = $dbh\->selectrow_hashref($statement, \e%attr, @bind_values); .Ve .PP This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and \&\*(L"fetchrow_hashref\*(R" into a single call. It returns the first row of data from the statement. The \f(CW$statement\fR parameter can be a previously prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. .PP If any method fails, and \*(L"RaiseError\*(R" is not set, \f(CW\*(C`selectrow_hashref\*(C'\fR will return undef. .PP \fI\f(CI\*(C`selectall_arrayref\*(C'\fI\fR .IX Subsection "selectall_arrayref" .PP .Vb 3 \& $ary_ref = $dbh\->selectall_arrayref($statement); \& $ary_ref = $dbh\->selectall_arrayref($statement, \e%attr); \& $ary_ref = $dbh\->selectall_arrayref($statement, \e%attr, @bind_values); .Ve .PP This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and \&\*(L"fetchall_arrayref\*(R" into a single call. It returns a reference to an array containing a reference to an array (or hash, see below) for each row of data fetched. .PP The \f(CW$statement\fR parameter can be a previously prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. This is recommended if the statement is going to be executed many times. .PP If \*(L"RaiseError\*(R" is not set and any method except \f(CW\*(C`fetchall_arrayref\*(C'\fR fails then \f(CW\*(C`selectall_arrayref\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR; if \&\f(CW\*(C`fetchall_arrayref\*(C'\fR fails then it will return with whatever data has been fetched thus far. You should check \f(CW\*(C`$dbh\->err\*(C'\fR afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the data is complete or was truncated due to an error. .PP The \*(L"fetchall_arrayref\*(R" method called by \f(CW\*(C`selectall_arrayref\*(C'\fR supports a \f(CW$max_rows\fR parameter. You can specify a value for \f(CW$max_rows\fR by including a '\f(CW\*(C`MaxRows\*(C'\fR' attribute in \e%attr. In which case \fBfinish()\fR is called for you after \fBfetchall_arrayref()\fR returns. .PP The \*(L"fetchall_arrayref\*(R" method called by \f(CW\*(C`selectall_arrayref\*(C'\fR also supports a \f(CW$slice\fR parameter. You can specify a value for \f(CW$slice\fR by including a '\f(CW\*(C`Slice\*(C'\fR' or '\f(CW\*(C`Columns\*(C'\fR' attribute in \e%attr. The only difference between the two is that if \f(CW\*(C`Slice\*(C'\fR is not defined and \&\f(CW\*(C`Columns\*(C'\fR is an array ref, then the array is assumed to contain column index values (which count from 1), rather than perl array index values. In which case the array is copied and each value decremented before passing to \f(CW\*(C`/fetchall_arrayref\*(C'\fR. .PP You may often want to fetch an array of rows where each row is stored as a hash. That can be done simply using: .PP .Vb 7 \& my $emps = $dbh\->selectall_arrayref( \& "SELECT ename FROM emp ORDER BY ename", \& { Slice => {} } \& ); \& foreach my $emp ( @$emps ) { \& print "Employee: $emp\->{ename}\en"; \& } .Ve .PP Or, to fetch into an array instead of an array ref: .PP .Vb 1 \& @result = @{ $dbh\->selectall_arrayref($sql, { Slice => {} }) }; .Ve .PP See \*(L"fetchall_arrayref\*(R" method for more details. .PP \fI\f(CI\*(C`selectall_array\*(C'\fI\fR .IX Subsection "selectall_array" .PP .Vb 3 \& @ary = $dbh\->selectall_array($statement); \& @ary = $dbh\->selectall_array($statement, \e%attr); \& @ary = $dbh\->selectall_array($statement, \e%attr, @bind_values); .Ve .PP This is a convenience wrapper around selectall_arrayref that returns the rows directly as a list, rather than a reference to an array of rows. .PP Note that if \*(L"RaiseError\*(R" is not set then you can't tell the difference between returning no rows and an error. Using RaiseError is best practice. .PP The \f(CW\*(C`selectall_array\*(C'\fR method was added in \s-1DBI 1.635.\s0 .PP \fI\f(CI\*(C`selectall_hashref\*(C'\fI\fR .IX Subsection "selectall_hashref" .PP .Vb 3 \& $hash_ref = $dbh\->selectall_hashref($statement, $key_field); \& $hash_ref = $dbh\->selectall_hashref($statement, $key_field, \e%attr); \& $hash_ref = $dbh\->selectall_hashref($statement, $key_field, \e%attr, @bind_values); .Ve .PP This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R" and \&\*(L"fetchall_hashref\*(R" into a single call. It returns a reference to a hash containing one entry, at most, for each row, as returned by \fBfetchall_hashref()\fR. .PP The \f(CW$statement\fR parameter can be a previously prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. This is recommended if the statement is going to be executed many times. .PP The \f(CW$key_field\fR parameter defines which column, or columns, are used as keys in the returned hash. It can either be the name of a single field, or a reference to an array containing multiple field names. Using multiple names yields a tree of nested hashes. .PP If a row has the same key as an earlier row then it replaces the earlier row. .PP If any method except \f(CW\*(C`fetchall_hashref\*(C'\fR fails, and \*(L"RaiseError\*(R" is not set, \&\f(CW\*(C`selectall_hashref\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR. If \f(CW\*(C`fetchall_hashref\*(C'\fR fails and \&\*(L"RaiseError\*(R" is not set, then it will return with whatever data it has fetched thus far. \f(CW$DBI::err\fR should be checked to catch that. .PP See \fBfetchall_hashref()\fR for more details. .PP \fI\f(CI\*(C`selectcol_arrayref\*(C'\fI\fR .IX Subsection "selectcol_arrayref" .PP .Vb 3 \& $ary_ref = $dbh\->selectcol_arrayref($statement); \& $ary_ref = $dbh\->selectcol_arrayref($statement, \e%attr); \& $ary_ref = $dbh\->selectcol_arrayref($statement, \e%attr, @bind_values); .Ve .PP This utility method combines \*(L"prepare\*(R", \*(L"execute\*(R", and fetching one column from all the rows, into a single call. It returns a reference to an array containing the values of the first column from each row. .PP The \f(CW$statement\fR parameter can be a previously prepared statement handle, in which case the \f(CW\*(C`prepare\*(C'\fR is skipped. This is recommended if the statement is going to be executed many times. .PP If any method except \f(CW\*(C`fetch\*(C'\fR fails, and \*(L"RaiseError\*(R" is not set, \&\f(CW\*(C`selectcol_arrayref\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR. If \f(CW\*(C`fetch\*(C'\fR fails and \&\*(L"RaiseError\*(R" is not set, then it will return with whatever data it has fetched thus far. \f(CW$DBI::err\fR should be checked to catch that. .PP The \f(CW\*(C`selectcol_arrayref\*(C'\fR method defaults to pushing a single column value (the first) from each row into the result array. However, it can also push another column, or even multiple columns per row, into the result array. This behaviour can be specified via a '\f(CW\*(C`Columns\*(C'\fR' attribute which must be a ref to an array containing the column number or numbers to use. For example: .PP .Vb 3 \& # get array of id and name pairs: \& my $ary_ref = $dbh\->selectcol_arrayref("select id, name from table", { Columns=>[1,2] }); \& my %hash = @$ary_ref; # build hash from key\-value pairs so $hash{$id} => name .Ve .PP You can specify a maximum number of rows to fetch by including a \&'\f(CW\*(C`MaxRows\*(C'\fR' attribute in \e%attr. .PP \fI\f(CI\*(C`prepare\*(C'\fI\fR .IX Subsection "prepare" .PP .Vb 2 \& $sth = $dbh\->prepare($statement) or die $dbh\->errstr; \& $sth = $dbh\->prepare($statement, \e%attr) or die $dbh\->errstr; .Ve .PP Prepares a statement for later execution by the database engine and returns a reference to a statement handle object. .PP The returned statement handle can be used to get attributes of the statement and invoke the \*(L"execute\*(R" method. See \*(L"Statement Handle Methods\*(R". .PP Drivers for engines without the concept of preparing a statement will typically just store the statement in the returned handle and process it when \f(CW\*(C`$sth\->execute\*(C'\fR is called. Such drivers are unlikely to give much useful information about the statement, such as \f(CW\*(C`$sth\->{NUM_OF_FIELDS}\*(C'\fR, until after \f(CW\*(C`$sth\->execute\*(C'\fR has been called. Portable applications should take this into account. .PP In general, \s-1DBI\s0 drivers do not parse the contents of the statement (other than simply counting any Placeholders). The statement is passed directly to the database engine, sometimes known as pass-thru mode. This has advantages and disadvantages. On the plus side, you can access all the functionality of the engine being used. On the downside, you're limited if you're using a simple engine, and you need to take extra care if writing applications intended to be portable between engines. .PP Portable applications should not assume that a new statement can be prepared and/or executed while still fetching results from a previous statement. .PP Some command-line \s-1SQL\s0 tools use statement terminators, like a semicolon, to indicate the end of a statement. Such terminators should not normally be used with the \s-1DBI.\s0 .PP \fI\f(CI\*(C`prepare_cached\*(C'\fI\fR .IX Subsection "prepare_cached" .PP .Vb 3 \& $sth = $dbh\->prepare_cached($statement) \& $sth = $dbh\->prepare_cached($statement, \e%attr) \& $sth = $dbh\->prepare_cached($statement, \e%attr, $if_active) .Ve .PP Like \*(L"prepare\*(R" except that the statement handle returned will be stored in a hash associated with the \f(CW$dbh\fR. If another call is made to \&\f(CW\*(C`prepare_cached\*(C'\fR with the same \f(CW$statement\fR and \f(CW%attr\fR parameter values, then the corresponding cached \f(CW$sth\fR will be returned without contacting the database server. Be sure to understand the cautions and caveats noted below. .PP The \f(CW$if_active\fR parameter lets you adjust the behaviour if an already cached statement handle is still Active. There are several alternatives: .ie n .IP "\fB0\fR: A warning will be generated, and \fBfinish()\fR will be called on the statement handle before it is returned. This is the default behaviour if $if_active is not passed." 4 .el .IP "\fB0\fR: A warning will be generated, and \fBfinish()\fR will be called on the statement handle before it is returned. This is the default behaviour if \f(CW$if_active\fR is not passed." 4 .IX Item "0: A warning will be generated, and finish() will be called on the statement handle before it is returned. This is the default behaviour if $if_active is not passed." .PD 0 .IP "\fB1\fR: \fBfinish()\fR will be called on the statement handle, but the warning is suppressed." 4 .IX Item "1: finish() will be called on the statement handle, but the warning is suppressed." .IP "\fB2\fR: Disables any checking." 4 .IX Item "2: Disables any checking." .IP "\fB3\fR: The existing active statement handle will be removed from the cache and a new statement handle prepared and cached in its place. This is the safest option because it doesn't affect the state of the old handle, it just removes it from the cache. [Added in \s-1DBI 1.40\s0]" 4 .IX Item "3: The existing active statement handle will be removed from the cache and a new statement handle prepared and cached in its place. This is the safest option because it doesn't affect the state of the old handle, it just removes it from the cache. [Added in DBI 1.40]" .PD .PP Here are some examples of \f(CW\*(C`prepare_cached\*(C'\fR: .PP .Vb 10 \& sub insert_hash { \& my ($table, $field_values) = @_; \& # sort to keep field order, and thus sql, stable for prepare_cached \& my @fields = sort keys %$field_values; \& my @values = @{$field_values}{@fields}; \& my $sql = sprintf "insert into %s (%s) values (%s)", \& $table, join(",", @fields), join(",", ("?")x@fields); \& my $sth = $dbh\->prepare_cached($sql); \& return $sth\->execute(@values); \& } \& \& sub search_hash { \& my ($table, $field_values) = @_; \& # sort to keep field order, and thus sql, stable for prepare_cached \& my @fields = sort keys %$field_values; \& my @values = @{$field_values}{@fields}; \& my $qualifier = ""; \& $qualifier = "where ".join(" and ", map { "$_=?" } @fields) if @fields; \& $sth = $dbh\->prepare_cached("SELECT * FROM $table $qualifier"); \& return $dbh\->selectall_arrayref($sth, {}, @values); \& } .Ve .PP \&\fICaveat emptor:\fR This caching can be useful in some applications, but it can also cause problems and should be used with care. Here is a contrived case where caching would cause a significant problem: .PP .Vb 3 \& my $sth = $dbh\->prepare_cached(\*(AqSELECT * FROM foo WHERE bar=?\*(Aq); \& $sth\->execute(...); \& while (my $data = $sth\->fetchrow_hashref) { \& \& # later, in some other code called within the loop... \& my $sth2 = $dbh\->prepare_cached(\*(AqSELECT * FROM foo WHERE bar=?\*(Aq); \& $sth2\->execute(...); \& while (my $data2 = $sth2\->fetchrow_arrayref) { \& do_stuff(...); \& } \& } .Ve .PP In this example, since both handles are preparing the exact same statement, \&\f(CW$sth2\fR will not be its own statement handle, but a duplicate of \f(CW$sth\fR returned from the cache. The results will certainly not be what you expect. Typically the inner fetch loop will work normally, fetching all the records and terminating when there are no more, but now that \f(CW$sth\fR is the same as \f(CW$sth2\fR the outer fetch loop will also terminate. .PP You'll know if you run into this problem because \fBprepare_cached()\fR will generate a warning by default (when \f(CW$if_active\fR is false). .PP The cache used by \fBprepare_cached()\fR is keyed by both the statement and any attributes so you can also avoid this issue by doing something like: .PP .Vb 1 \& $sth = $dbh\->prepare_cached("...", { dbi_dummy => _\|_FILE_\|_._\|_LINE_\|_ }); .Ve .PP which will ensure that prepare_cached only returns statements cached by that line of code in that source file. .PP Also, to ensure the attributes passed are always the same, avoid passing references inline. For example, the Slice attribute is specified as a reference. Be sure to declare it external to the call to \fBprepare_cached()\fR, such that a new hash reference is not created on every call. See \*(L"connect_cached\*(R" for more details and examples. .PP If you'd like the cache to managed intelligently, you can tie the hashref returned by \f(CW\*(C`CachedKids\*(C'\fR to an appropriate caching module, such as Tie::Cache::LRU: .PP .Vb 3 \& my $cache; \& tie %$cache, \*(AqTie::Cache::LRU\*(Aq, 500; \& $dbh\->{CachedKids} = $cache; .Ve .PP \fI\f(CI\*(C`commit\*(C'\fI\fR .IX Subsection "commit" .PP .Vb 1 \& $rc = $dbh\->commit or die $dbh\->errstr; .Ve .PP Commit (make permanent) the most recent series of database changes if the database supports transactions and AutoCommit is off. .PP If \f(CW\*(C`AutoCommit\*(C'\fR is on, then calling \&\f(CW\*(C`commit\*(C'\fR will issue a \*(L"commit ineffective with AutoCommit\*(R" warning. .PP See also \*(L"Transactions\*(R" in the \*(L"\s-1FURTHER INFORMATION\*(R"\s0 section below. .PP \fI\f(CI\*(C`rollback\*(C'\fI\fR .IX Subsection "rollback" .PP .Vb 1 \& $rc = $dbh\->rollback or die $dbh\->errstr; .Ve .PP Rollback (undo) the most recent series of uncommitted database changes if the database supports transactions and AutoCommit is off. .PP If \f(CW\*(C`AutoCommit\*(C'\fR is on, then calling \&\f(CW\*(C`rollback\*(C'\fR will issue a \*(L"rollback ineffective with AutoCommit\*(R" warning. .PP See also \*(L"Transactions\*(R" in the \*(L"\s-1FURTHER INFORMATION\*(R"\s0 section below. .PP \fI\f(CI\*(C`begin_work\*(C'\fI\fR .IX Subsection "begin_work" .PP .Vb 1 \& $rc = $dbh\->begin_work or die $dbh\->errstr; .Ve .PP Enable transactions (by turning \f(CW\*(C`AutoCommit\*(C'\fR off) until the next call to \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR. After the next \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR, \&\f(CW\*(C`AutoCommit\*(C'\fR will automatically be turned on again. .PP If \f(CW\*(C`AutoCommit\*(C'\fR is already off when \f(CW\*(C`begin_work\*(C'\fR is called then it does nothing except return an error. If the driver does not support transactions then when \f(CW\*(C`begin_work\*(C'\fR attempts to set \f(CW\*(C`AutoCommit\*(C'\fR off the driver will trigger a fatal error. .PP See also \*(L"Transactions\*(R" in the \*(L"\s-1FURTHER INFORMATION\*(R"\s0 section below. .PP \fI\f(CI\*(C`disconnect\*(C'\fI\fR .IX Subsection "disconnect" .PP .Vb 1 \& $rc = $dbh\->disconnect or warn $dbh\->errstr; .Ve .PP Disconnects the database from the database handle. \f(CW\*(C`disconnect\*(C'\fR is typically only used before exiting the program. The handle is of little use after disconnecting. .PP The transaction behaviour of the \f(CW\*(C`disconnect\*(C'\fR method is, sadly, undefined. Some database systems (such as Oracle and Ingres) will automatically commit any outstanding changes, but others (such as Informix) will rollback any outstanding changes. Applications not using \f(CW\*(C`AutoCommit\*(C'\fR should explicitly call \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR before calling \f(CW\*(C`disconnect\*(C'\fR. .PP The database is automatically disconnected by the \f(CW\*(C`DESTROY\*(C'\fR method if still connected when there are no longer any references to the handle. The \f(CW\*(C`DESTROY\*(C'\fR method for each driver should implicitly call \f(CW\*(C`rollback\*(C'\fR to undo any uncommitted changes. This is vital behaviour to ensure that incomplete transactions don't get committed simply because Perl calls \&\f(CW\*(C`DESTROY\*(C'\fR on every object before exiting. Also, do not rely on the order of object destruction during \*(L"global destruction\*(R", as it is undefined. .PP Generally, if you want your changes to be committed or rolled back when you disconnect, then you should explicitly call \*(L"commit\*(R" or \*(L"rollback\*(R" before disconnecting. .PP If you disconnect from a database while you still have active statement handles (e.g., \s-1SELECT\s0 statement handles that may have more data to fetch), you will get a warning. The warning may indicate that a fetch loop terminated early, perhaps due to an uncaught error. To avoid the warning call the \f(CW\*(C`finish\*(C'\fR method on the active handles. .PP \fI\f(CI\*(C`ping\*(C'\fI\fR .IX Subsection "ping" .PP .Vb 1 \& $rc = $dbh\->ping; .Ve .PP Attempts to determine, in a reasonably efficient way, if the database server is still running and the connection to it is still working. Individual drivers should implement this function in the most suitable manner for their database engine. .PP The current \fIdefault\fR implementation always returns true without actually doing anything. Actually, it returns "\f(CW\*(C`0 but true\*(C'\fR" which is true but zero. That way you can tell if the return value is genuine or just the default. Drivers should override this method with one that does the right thing for their type of database. .PP Few applications would have direct use for this method. See the specialized Apache::DBI module for one example usage. .PP \fI\f(CI\*(C`get_info\*(C'\fI\fR .IX Subsection "get_info" .PP .Vb 1 \& $value = $dbh\->get_info( $info_type ); .Ve .PP Returns information about the implementation, i.e. driver and data source capabilities, restrictions etc. It returns \f(CW\*(C`undef\*(C'\fR for unknown or unimplemented information types. For example: .PP .Vb 2 \& $database_version = $dbh\->get_info( 18 ); # SQL_DBMS_VER \& $max_select_tables = $dbh\->get_info( 106 ); # SQL_MAXIMUM_TABLES_IN_SELECT .Ve .PP See \*(L"Standards Reference Information\*(R" for more detailed information about the information types and their meanings and possible return values. .PP The DBI::Const::GetInfoType module exports a \f(CW%GetInfoType\fR hash that can be used to map info type names to numbers. For example: .PP .Vb 1 \& $database_version = $dbh\->get_info( $GetInfoType{SQL_DBMS_VER} ); .Ve .PP The names are a merging of the \s-1ANSI\s0 and \s-1ODBC\s0 standards (which differ in some cases). See DBI::Const::GetInfoType for more details. .PP Because some \s-1DBI\s0 methods make use of \fBget_info()\fR, drivers are strongly encouraged to support \fIat least\fR the following very minimal set of information types to ensure the \s-1DBI\s0 itself works properly: .PP .Vb 7 \& Type Name Example A Example B \& \-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& 17 SQL_DBMS_NAME \*(AqACCESS\*(Aq \*(AqOracle\*(Aq \& 18 SQL_DBMS_VER \*(Aq03.50.0000\*(Aq \*(Aq08.01.0721 ...\*(Aq \& 29 SQL_IDENTIFIER_QUOTE_CHAR \*(Aq\`\*(Aq \*(Aq"\*(Aq \& 41 SQL_CATALOG_NAME_SEPARATOR \*(Aq.\*(Aq \*(Aq@\*(Aq \& 114 SQL_CATALOG_LOCATION 1 2 .Ve .PP Values from 9000 to 9999 for get_info are officially reserved for use by Perl \s-1DBI.\s0 Values in that range which have been assigned a meaning are defined here: .PP \&\f(CW9000\fR: true if a backslash character (\f(CW\*(C`\e\*(C'\fR) before placeholder-like text (e.g. \f(CW\*(C`?\*(C'\fR, \f(CW\*(C`:foo\*(C'\fR) will prevent it being treated as a placeholder by the driver. The backslash will be removed before the text is passed to the backend. .PP \fI\f(CI\*(C`table_info\*(C'\fI\fR .IX Subsection "table_info" .PP .Vb 2 \& $sth = $dbh\->table_info( $catalog, $schema, $table, $type ); \& $sth = $dbh\->table_info( $catalog, $schema, $table, $type, \e%attr ); \& \& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc .Ve .PP Returns an active statement handle that can be used to fetch information about tables and views that exist in the database. .PP The arguments \f(CW$catalog\fR, \f(CW$schema\fR and \f(CW$table\fR may accept search patterns according to the database/driver, for example: \f(CW$table\fR = '%FOO%'; Remember that the underscore character ('\f(CW\*(C`_\*(C'\fR') is a search pattern that means match any character, so 'FOO_%' is the same as 'FOO%' and 'FOO_BAR%' will match names like '\s-1FOO1BAR\s0'. .PP The value of \f(CW$type\fR is a comma-separated list of one or more types of tables to be returned in the result set. Each value may optionally be quoted, e.g.: .PP .Vb 2 \& $type = "TABLE"; \& $type = "\*(AqTABLE\*(Aq,\*(AqVIEW\*(Aq"; .Ve .PP In addition the following special cases may also be supported by some drivers: .IP "\(bu" 4 If the value of \f(CW$catalog\fR is '%' and \f(CW$schema\fR and \f(CW$table\fR name are empty strings, the result set contains a list of catalog names. For example: .Sp .Vb 1 \& $sth = $dbh\->table_info(\*(Aq%\*(Aq, \*(Aq\*(Aq, \*(Aq\*(Aq); .Ve .IP "\(bu" 4 If the value of \f(CW$schema\fR is '%' and \f(CW$catalog\fR and \f(CW$table\fR are empty strings, the result set contains a list of schema names. .IP "\(bu" 4 If the value of \f(CW$type\fR is '%' and \f(CW$catalog\fR, \f(CW$schema\fR, and \f(CW$table\fR are all empty strings, the result set contains a list of table types. .PP If your driver doesn't support one or more of the selection filter parameters then you may get back more than you asked for and can do the filtering yourself. .PP This method can be expensive, and can return a large amount of data. (For example, small Oracle installation returns over 2000 rows.) So it's a good idea to use the filters to limit the data as much as possible. .PP The statement handle returned has at least the following fields in the order show below. Other fields, after these, may also be present. .PP \&\fB\s-1TABLE_CAT\s0\fR: Table catalog identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, which is usually the case. This field is empty if not applicable to the table. .PP \&\fB\s-1TABLE_SCHEM\s0\fR: The name of the schema containing the \s-1TABLE_NAME\s0 value. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to data source, and empty if not applicable to the table. .PP \&\fB\s-1TABLE_NAME\s0\fR: Name of the table (or view, synonym, etc). .PP \&\fB\s-1TABLE_TYPE\s0\fR: One of the following: \*(L"\s-1TABLE\*(R", \*(L"VIEW\*(R", \*(L"SYSTEM TABLE\*(R", \&\*(L"GLOBAL TEMPORARY\*(R", \*(L"LOCAL TEMPORARY\*(R", \*(L"ALIAS\*(R", \*(L"SYNONYM\*(R"\s0 or a type identifier that is specific to the data source. .PP \&\fB\s-1REMARKS\s0\fR: A description of the table. May be \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR). .PP Note that \f(CW\*(C`table_info\*(C'\fR might not return records for all tables. Applications can use any valid table regardless of whether it's returned by \f(CW\*(C`table_info\*(C'\fR. .PP See also \*(L"tables\*(R", \*(L"Catalog Methods\*(R" and \&\*(L"Standards Reference Information\*(R". .PP \fI\f(CI\*(C`column_info\*(C'\fI\fR .IX Subsection "column_info" .PP .Vb 1 \& $sth = $dbh\->column_info( $catalog, $schema, $table, $column ); \& \& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc .Ve .PP Returns an active statement handle that can be used to fetch information about columns in specified tables. .PP The arguments \f(CW$schema\fR, \f(CW$table\fR and \f(CW$column\fR may accept search patterns according to the database/driver, for example: \f(CW$table\fR = '%FOO%'; .PP Note: The support for the selection criteria is driver specific. If the driver doesn't support one or more of them then you may get back more than you asked for and can do the filtering yourself. .PP Note: If your driver does not support column_info an undef is returned. This is distinct from asking for something which does not exist in a driver which supports column_info as a valid statement handle to an empty result-set will be returned in this case. .PP If the arguments don't match any tables then you'll still get a statement handle, it'll just return no rows. .PP The statement handle returned has at least the following fields in the order shown below. Other fields, after these, may also be present. .PP \&\fB\s-1TABLE_CAT\s0\fR: The catalog identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, which is often the case. This field is empty if not applicable to the table. .PP \&\fB\s-1TABLE_SCHEM\s0\fR: The schema identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, and empty if not applicable to the table. .PP \&\fB\s-1TABLE_NAME\s0\fR: The table identifier. Note: A driver may provide column metadata not only for base tables, but also for derived objects like \s-1SYNONYMS\s0 etc. .PP \&\fB\s-1COLUMN_NAME\s0\fR: The column identifier. .PP \&\fB\s-1DATA_TYPE\s0\fR: The concise data type code. .PP \&\fB\s-1TYPE_NAME\s0\fR: A data source dependent data type name. .PP \&\fB\s-1COLUMN_SIZE\s0\fR: The column size. This is the maximum length in characters for character data types, the number of digits or bits for numeric data types or the length in the representation of temporal types. See the relevant specifications for detailed information. .PP \&\fB\s-1BUFFER_LENGTH\s0\fR: The length in bytes of transferred data. .PP \&\fB\s-1DECIMAL_DIGITS\s0\fR: The total number of significant digits to the right of the decimal point. .PP \&\fB\s-1NUM_PREC_RADIX\s0\fR: The radix for numeric precision. The value is 10 or 2 for numeric data types and \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable. .PP \&\fB\s-1NULLABLE\s0\fR: Indicates if a column can accept NULLs. The following values are defined: .PP .Vb 3 \& SQL_NO_NULLS 0 \& SQL_NULLABLE 1 \& SQL_NULLABLE_UNKNOWN 2 .Ve .PP \&\fB\s-1REMARKS\s0\fR: A description of the column. .PP \&\fB\s-1COLUMN_DEF\s0\fR: The default value of the column, in a format that can be used directly in an \s-1SQL\s0 statement. .PP Note that this may be an expression and not simply the text used for the default value in the original \s-1CREATE TABLE\s0 statement. For example, given: .PP .Vb 2 \& col1 char(30) default current_user \-\- a \*(Aqfunction\*(Aq \& col2 char(30) default \*(Aqstring\*(Aq \-\- a string literal .Ve .PP where \*(L"current_user\*(R" is the name of a function, the corresponding \f(CW\*(C`COLUMN_DEF\*(C'\fR values would be: .PP .Vb 5 \& Database col1 col2 \& \-\-\-\-\-\-\-\- \-\-\-\- \-\-\-\- \& Oracle: current_user \*(Aqstring\*(Aq \& Postgres: "current_user"() \*(Aqstring\*(Aq::text \& MS SQL: (user_name()) (\*(Aqstring\*(Aq) .Ve .PP \&\fB\s-1SQL_DATA_TYPE\s0\fR: The \s-1SQL\s0 data type. .PP \&\fB\s-1SQL_DATETIME_SUB\s0\fR: The subtype code for datetime and interval data types. .PP \&\fB\s-1CHAR_OCTET_LENGTH\s0\fR: The maximum length in bytes of a character or binary data type column. .PP \&\fB\s-1ORDINAL_POSITION\s0\fR: The column sequence number (starting with 1). .PP \&\fB\s-1IS_NULLABLE\s0\fR: Indicates if the column can accept NULLs. Possible values are: '\s-1NO\s0', '\s-1YES\s0' and ''. .PP \&\s-1SQL/CLI\s0 defines the following additional columns: .PP .Vb 10 \& CHAR_SET_CAT \& CHAR_SET_SCHEM \& CHAR_SET_NAME \& COLLATION_CAT \& COLLATION_SCHEM \& COLLATION_NAME \& UDT_CAT \& UDT_SCHEM \& UDT_NAME \& DOMAIN_CAT \& DOMAIN_SCHEM \& DOMAIN_NAME \& SCOPE_CAT \& SCOPE_SCHEM \& SCOPE_NAME \& MAX_CARDINALITY \& DTD_IDENTIFIER \& IS_SELF_REF .Ve .PP Drivers capable of supplying any of those values should do so in the corresponding column and supply undef values for the others. .PP Drivers wishing to provide extra database/driver specific information should do so in extra columns beyond all those listed above, and use lowercase field names with the driver-specific prefix (i.e., \&'ora_...'). Applications accessing such fields should do so by name and not by column number. .PP The result set is ordered by \s-1TABLE_CAT, TABLE_SCHEM, TABLE_NAME\s0 and \s-1ORDINAL_POSITION.\s0 .PP Note: There is some overlap with statement handle attributes (in perl) and SQLDescribeCol (in \s-1ODBC\s0). However, SQLColumns provides more metadata. .PP See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". .PP \fI\f(CI\*(C`primary_key_info\*(C'\fI\fR .IX Subsection "primary_key_info" .PP .Vb 1 \& $sth = $dbh\->primary_key_info( $catalog, $schema, $table ); \& \& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc .Ve .PP Returns an active statement handle that can be used to fetch information about columns that make up the primary key for a table. The arguments don't accept search patterns (unlike \fBtable_info()\fR). .PP The statement handle will return one row per column, ordered by \&\s-1TABLE_CAT, TABLE_SCHEM, TABLE_NAME,\s0 and \s-1KEY_SEQ.\s0 If there is no primary key then the statement handle will fetch no rows. .PP Note: The support for the selection criteria, such as \f(CW$catalog\fR, is driver specific. If the driver doesn't support catalogs and/or schemas, it may ignore these criteria. .PP The statement handle returned has at least the following fields in the order shown below. Other fields, after these, may also be present. .PP \&\fB\s-1TABLE_CAT\s0\fR: The catalog identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, which is often the case. This field is empty if not applicable to the table. .PP \&\fB\s-1TABLE_SCHEM\s0\fR: The schema identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, and empty if not applicable to the table. .PP \&\fB\s-1TABLE_NAME\s0\fR: The table identifier. .PP \&\fB\s-1COLUMN_NAME\s0\fR: The column identifier. .PP \&\fB\s-1KEY_SEQ\s0\fR: The column sequence number (starting with 1). Note: This field is named \fB\s-1ORDINAL_POSITION\s0\fR in \s-1SQL/CLI.\s0 .PP \&\fB\s-1PK_NAME\s0\fR: The primary key constraint identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source. .PP See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". .PP \fI\f(CI\*(C`primary_key\*(C'\fI\fR .IX Subsection "primary_key" .PP .Vb 1 \& @key_column_names = $dbh\->primary_key( $catalog, $schema, $table ); .Ve .PP Simple interface to the \fBprimary_key_info()\fR method. Returns a list of the column names that comprise the primary key of the specified table. The list is in primary key column sequence order. If there is no primary key then an empty list is returned. .PP \fI\f(CI\*(C`foreign_key_info\*(C'\fI\fR .IX Subsection "foreign_key_info" .PP .Vb 2 \& $sth = $dbh\->foreign_key_info( $pk_catalog, $pk_schema, $pk_table \& , $fk_catalog, $fk_schema, $fk_table ); \& \& $sth = $dbh\->foreign_key_info( $pk_catalog, $pk_schema, $pk_table \& , $fk_catalog, $fk_schema, $fk_table \& , \e%attr ); \& \& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc .Ve .PP Returns an active statement handle that can be used to fetch information about foreign keys in and/or referencing the specified table(s). The arguments don't accept search patterns (unlike \fBtable_info()\fR). .PP \&\f(CW$pk_catalog\fR, \f(CW$pk_schema\fR, \f(CW$pk_table\fR identify the primary (unique) key table (\fB\s-1PKT\s0\fR). .PP \&\f(CW$fk_catalog\fR, \f(CW$fk_schema\fR, \f(CW$fk_table\fR identify the foreign key table (\fB\s-1FKT\s0\fR). .PP If both \fB\s-1PKT\s0\fR and \fB\s-1FKT\s0\fR are given, the function returns the foreign key, if any, in table \fB\s-1FKT\s0\fR that refers to the primary (unique) key of table \fB\s-1PKT\s0\fR. (Note: In \s-1SQL/CLI,\s0 the result is implementation-defined.) .PP If only \fB\s-1PKT\s0\fR is given, then the result set contains the primary key of that table and all foreign keys that refer to it. .PP If only \fB\s-1FKT\s0\fR is given, then the result set contains all foreign keys in that table and the primary keys to which they refer. (Note: In \s-1SQL/CLI,\s0 the result includes unique keys too.) .PP For example: .PP .Vb 3 \& $sth = $dbh\->foreign_key_info( undef, $user, \*(Aqmaster\*(Aq); \& $sth = $dbh\->foreign_key_info( undef, undef, undef , undef, $user, \*(Aqdetail\*(Aq); \& $sth = $dbh\->foreign_key_info( undef, $user, \*(Aqmaster\*(Aq, undef, $user, \*(Aqdetail\*(Aq); \& \& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc .Ve .PP Note: The support for the selection criteria, such as \f(CW$catalog\fR, is driver specific. If the driver doesn't support catalogs and/or schemas, it may ignore these criteria. .PP The statement handle returned has the following fields in the order shown below. Because \s-1ODBC\s0 never includes unique keys, they define different columns in the result set than \s-1SQL/CLI. SQL/CLI\s0 column names are shown in parentheses. .PP \&\fB\s-1PKTABLE_CAT\s0 ( \s-1UK_TABLE_CAT\s0 )\fR: The primary (unique) key table catalog identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, which is often the case. This field is empty if not applicable to the table. .PP \&\fB\s-1PKTABLE_SCHEM\s0 ( \s-1UK_TABLE_SCHEM\s0 )\fR: The primary (unique) key table schema identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, and empty if not applicable to the table. .PP \&\fB\s-1PKTABLE_NAME\s0 ( \s-1UK_TABLE_NAME\s0 )\fR: The primary (unique) key table identifier. .PP \&\fB\s-1PKCOLUMN_NAME\s0 (\s-1UK_COLUMN_NAME\s0 )\fR: The primary (unique) key column identifier. .PP \&\fB\s-1FKTABLE_CAT\s0 ( \s-1FK_TABLE_CAT\s0 )\fR: The foreign key table catalog identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, which is often the case. This field is empty if not applicable to the table. .PP \&\fB\s-1FKTABLE_SCHEM\s0 ( \s-1FK_TABLE_SCHEM\s0 )\fR: The foreign key table schema identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, and empty if not applicable to the table. .PP \&\fB\s-1FKTABLE_NAME\s0 ( \s-1FK_TABLE_NAME\s0 )\fR: The foreign key table identifier. .PP \&\fB\s-1FKCOLUMN_NAME\s0 ( \s-1FK_COLUMN_NAME\s0 )\fR: The foreign key column identifier. .PP \&\fB\s-1KEY_SEQ\s0 ( \s-1ORDINAL_POSITION\s0 )\fR: The column sequence number (starting with 1). .PP \&\fB\s-1UPDATE_RULE\s0 ( \s-1UPDATE_RULE\s0 )\fR: The referential action for the \s-1UPDATE\s0 rule. The following codes are defined: .PP .Vb 5 \& CASCADE 0 \& RESTRICT 1 \& SET NULL 2 \& NO ACTION 3 \& SET DEFAULT 4 .Ve .PP \&\fB\s-1DELETE_RULE\s0 ( \s-1DELETE_RULE\s0 )\fR: The referential action for the \s-1DELETE\s0 rule. The codes are the same as for \s-1UPDATE_RULE.\s0 .PP \&\fB\s-1FK_NAME\s0 ( \s-1FK_NAME\s0 )\fR: The foreign key name. .PP \&\fB\s-1PK_NAME\s0 ( \s-1UK_NAME\s0 )\fR: The primary (unique) key name. .PP \&\fB\s-1DEFERRABILITY\s0 ( \s-1DEFERABILITY\s0 )\fR: The deferrability of the foreign key constraint. The following codes are defined: .PP .Vb 3 \& INITIALLY DEFERRED 5 \& INITIALLY IMMEDIATE 6 \& NOT DEFERRABLE 7 .Ve .PP \&\fB ( \s-1UNIQUE_OR_PRIMARY\s0 )\fR: This column is necessary if a driver includes all candidate (i.e. primary and alternate) keys in the result set (as specified by \s-1SQL/CLI\s0). The value of this column is \s-1UNIQUE\s0 if the foreign key references an alternate key and \s-1PRIMARY\s0 if the foreign key references a primary key, or it may be undefined if the driver doesn't have access to the information. .PP See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". .PP \fI\f(CI\*(C`statistics_info\*(C'\fI\fR .IX Subsection "statistics_info" .PP \&\fBWarning:\fR This method is experimental and may change. .PP .Vb 1 \& $sth = $dbh\->statistics_info( $catalog, $schema, $table, $unique_only, $quick ); \& \& # then $sth\->fetchall_arrayref or $sth\->fetchall_hashref etc .Ve .PP Returns an active statement handle that can be used to fetch statistical information about a table and its indexes. .PP The arguments don't accept search patterns (unlike \*(L"table_info\*(R"). .PP If the boolean argument \f(CW$unique_only\fR is true, only \s-1UNIQUE\s0 indexes will be returned in the result set, otherwise all indexes will be returned. .PP If the boolean argument \f(CW$quick\fR is set, the actual statistical information columns (\s-1CARDINALITY\s0 and \s-1PAGES\s0) will only be returned if they are readily available from the server, and might not be current. Some databases may return stale statistics or no statistics at all with this flag set. .PP The statement handle will return at most one row per column name per index, plus at most one row for the entire table itself, ordered by \s-1NON_UNIQUE, TYPE, INDEX_QUALIFIER, INDEX_NAME,\s0 and \s-1ORDINAL_POSITION.\s0 .PP Note: The support for the selection criteria, such as \f(CW$catalog\fR, is driver specific. If the driver doesn't support catalogs and/or schemas, it may ignore these criteria. .PP The statement handle returned has at least the following fields in the order shown below. Other fields, after these, may also be present. .PP \&\fB\s-1TABLE_CAT\s0\fR: The catalog identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, which is often the case. This field is empty if not applicable to the table. .PP \&\fB\s-1TABLE_SCHEM\s0\fR: The schema identifier. This field is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not applicable to the data source, and empty if not applicable to the table. .PP \&\fB\s-1TABLE_NAME\s0\fR: The table identifier. .PP \&\fB\s-1NON_UNIQUE\s0\fR: Unique index indicator. Returns 0 for unique indexes, 1 for non-unique indexes .PP \&\fB\s-1INDEX_QUALIFIER\s0\fR: Index qualifier identifier. The identifier that is used to qualify the index name when doing a \&\f(CW\*(C`DROP INDEX\*(C'\fR; \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned if an index qualifier is not supported by the data source. If a non-NULL (defined) value is returned in this column, it must be used to qualify the index name on a \f(CW\*(C`DROP INDEX\*(C'\fR statement; otherwise, the \s-1TABLE_SCHEM\s0 should be used to qualify the index name. .PP \&\fB\s-1INDEX_NAME\s0\fR: The index identifier. .PP \&\fB\s-1TYPE\s0\fR: The type of information being returned. Can be any of the following values: 'table', 'btree', 'clustered', 'content', 'hashed', or 'other'. .PP In the case that this field is 'table', all fields other than \s-1TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TYPE, CARDINALITY,\s0 and \s-1PAGES\s0 will be \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR). .PP \&\fB\s-1ORDINAL_POSITION\s0\fR: Column sequence number (starting with 1). .PP \&\fB\s-1COLUMN_NAME\s0\fR: The column identifier. .PP \&\fB\s-1ASC_OR_DESC\s0\fR: Column sort sequence. \&\f(CW\*(C`A\*(C'\fR for Ascending, \f(CW\*(C`D\*(C'\fR for Descending, or \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) if not supported for this index. .PP \&\fB\s-1CARDINALITY\s0\fR: Cardinality of the table or index. For indexes, this is the number of unique values in the index. For tables, this is the number of rows in the table. If not supported, the value will be \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR). .PP \&\fB\s-1PAGES\s0\fR: Number of storage pages used by this table or index. If not supported, the value will be \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR). .PP \&\fB\s-1FILTER_CONDITION\s0\fR: The index filter condition as a string. If the index is not a filtered index, or it cannot be determined whether the index is a filtered index, this value is \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR). If the index is a filtered index, but the filter condition cannot be determined, this value is the empty string \f(CW\*(Aq\*(Aq\fR. Otherwise it will be the literal filter condition as a string, such as \f(CW\*(C`SALARY <= 4500\*(C'\fR. .PP See also \*(L"Catalog Methods\*(R" and \*(L"Standards Reference Information\*(R". .PP \fI\f(CI\*(C`tables\*(C'\fI\fR .IX Subsection "tables" .PP .Vb 2 \& @names = $dbh\->tables( $catalog, $schema, $table, $type ); \& @names = $dbh\->tables; # deprecated .Ve .PP Simple interface to \fBtable_info()\fR. Returns a list of matching table names, possibly including a catalog/schema prefix. .PP See \*(L"table_info\*(R" for a description of the parameters. .PP If \f(CW\*(C`$dbh\->get_info(29)\*(C'\fR returns true (29 is \s-1SQL_IDENTIFIER_QUOTE_CHAR\s0) then the table names are constructed and quoted by \*(L"quote_identifier\*(R" to ensure they are usable even if they contain whitespace or reserved words etc. This means that the table names returned will include quote characters. .PP \fI\f(CI\*(C`type_info_all\*(C'\fI\fR .IX Subsection "type_info_all" .PP .Vb 1 \& $type_info_all = $dbh\->type_info_all; .Ve .PP Returns a reference to an array which holds information about each data type variant supported by the database and driver. The array and its contents should be treated as read-only. .PP The first item is a reference to an 'index' hash of \f(CW\*(C`Name =\*(C'\fR> \f(CW\*(C`Index\*(C'\fR pairs. The items following that are references to arrays, one per supported data type variant. The leading index hash defines the names and order of the fields within the arrays that follow it. For example: .PP .Vb 10 \& $type_info_all = [ \& { TYPE_NAME => 0, \& DATA_TYPE => 1, \& COLUMN_SIZE => 2, # was PRECISION originally \& LITERAL_PREFIX => 3, \& LITERAL_SUFFIX => 4, \& CREATE_PARAMS => 5, \& NULLABLE => 6, \& CASE_SENSITIVE => 7, \& SEARCHABLE => 8, \& UNSIGNED_ATTRIBUTE=> 9, \& FIXED_PREC_SCALE => 10, # was MONEY originally \& AUTO_UNIQUE_VALUE => 11, # was AUTO_INCREMENT originally \& LOCAL_TYPE_NAME => 12, \& MINIMUM_SCALE => 13, \& MAXIMUM_SCALE => 14, \& SQL_DATA_TYPE => 15, \& SQL_DATETIME_SUB => 16, \& NUM_PREC_RADIX => 17, \& INTERVAL_PRECISION=> 18, \& }, \& [ \*(AqVARCHAR\*(Aq, SQL_VARCHAR, \& undef, "\*(Aq","\*(Aq", undef,0, 1,1,0,0,0,undef,1,255, undef \& ], \& [ \*(AqINTEGER\*(Aq, SQL_INTEGER, \& undef, "", "", undef,0, 0,1,0,0,0,undef,0, 0, 10 \& ], \& ]; .Ve .PP More than one row may have the same value in the \f(CW\*(C`DATA_TYPE\*(C'\fR field if there are different ways to spell the type name and/or there are variants of the type with different attributes (e.g., with and without \f(CW\*(C`AUTO_UNIQUE_VALUE\*(C'\fR set, with and without \f(CW\*(C`UNSIGNED_ATTRIBUTE\*(C'\fR, etc). .PP The rows are ordered by \f(CW\*(C`DATA_TYPE\*(C'\fR first and then by how closely each type maps to the corresponding \s-1ODBC SQL\s0 data type, closest first. .PP The meaning of the fields is described in the documentation for the \*(L"type_info\*(R" method. .PP An 'index' hash is provided so you don't need to rely on index values defined above. However, using \s-1DBD::ODBC\s0 with some old \s-1ODBC\s0 drivers may return older names, shown as comments in the example above. Another issue with the index hash is that the lettercase of the keys is not defined. It is usually uppercase, as show here, but drivers may return names with any lettercase. .PP Drivers are also free to return extra driver-specific columns of information \- though it's recommended that they start at column index 50 to leave room for expansion of the \s-1DBI/ODBC\s0 specification. .PP The \fBtype_info_all()\fR method is not normally used directly. The \*(L"type_info\*(R" method provides a more usable and useful interface to the data. .PP \fI\f(CI\*(C`type_info\*(C'\fI\fR .IX Subsection "type_info" .PP .Vb 1 \& @type_info = $dbh\->type_info($data_type); .Ve .PP Returns a list of hash references holding information about one or more variants of \f(CW$data_type\fR. The list is ordered by \f(CW\*(C`DATA_TYPE\*(C'\fR first and then by how closely each type maps to the corresponding \s-1ODBC SQL\s0 data type, closest first. If called in a scalar context then only the first (best) element is returned. .PP If \f(CW$data_type\fR is undefined or \f(CW\*(C`SQL_ALL_TYPES\*(C'\fR, then the list will contain hashes for all data type variants supported by the database and driver. .PP If \f(CW$data_type\fR is an array reference then \f(CW\*(C`type_info\*(C'\fR returns the information for the \fIfirst\fR type in the array that has any matches. .PP The keys of the hash follow the same letter case conventions as the rest of the \s-1DBI\s0 (see \*(L"Naming Conventions and Name Space\*(R"). The following uppercase items should always exist, though may be undef: .IP "\s-1TYPE_NAME\s0 (string)" 4 .IX Item "TYPE_NAME (string)" Data type name for use in \s-1CREATE TABLE\s0 statements etc. .IP "\s-1DATA_TYPE\s0 (integer)" 4 .IX Item "DATA_TYPE (integer)" \&\s-1SQL\s0 data type number. .IP "\s-1COLUMN_SIZE\s0 (integer)" 4 .IX Item "COLUMN_SIZE (integer)" For numeric types, this is either the total number of digits (if the \&\s-1NUM_PREC_RADIX\s0 value is 10) or the total number of bits allowed in the column (if \s-1NUM_PREC_RADIX\s0 is 2). .Sp For string types, this is the maximum size of the string in characters. .Sp For date and interval types, this is the maximum number of characters needed to display the value. .IP "\s-1LITERAL_PREFIX\s0 (string)" 4 .IX Item "LITERAL_PREFIX (string)" Characters used to prefix a literal. A typical prefix is "\f(CW\*(C`\*(Aq\*(C'\fR\*(L" for characters, or possibly \*(R"\f(CW\*(C`0x\*(C'\fR" for binary values passed as hexadecimal. \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1LITERAL_SUFFIX\s0 (string)" 4 .IX Item "LITERAL_SUFFIX (string)" Characters used to suffix a literal. Typically "\f(CW\*(C`\*(Aq\*(C'\fR" for characters. \&\s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types where this is not applicable. .IP "\s-1CREATE_PARAMS\s0 (string)" 4 .IX Item "CREATE_PARAMS (string)" Parameter names for data type definition. For example, \f(CW\*(C`CREATE_PARAMS\*(C'\fR for a \&\f(CW\*(C`DECIMAL\*(C'\fR would be "\f(CW\*(C`precision,scale\*(C'\fR" if the \s-1DECIMAL\s0 type should be declared as \f(CW\*(C`DECIMAL(\*(C'\fR\fIprecision,scale\fR\f(CW\*(C`)\*(C'\fR where \fIprecision\fR and \fIscale\fR are integer values. For a \f(CW\*(C`VARCHAR\*(C'\fR it would be "\f(CW\*(C`max length\*(C'\fR". \&\s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1NULLABLE\s0 (integer)" 4 .IX Item "NULLABLE (integer)" Indicates whether the data type accepts a \s-1NULL\s0 value: \&\f(CW0\fR or an empty string = no, \f(CW1\fR = yes, \f(CW2\fR = unknown. .IP "\s-1CASE_SENSITIVE\s0 (boolean)" 4 .IX Item "CASE_SENSITIVE (boolean)" Indicates whether the data type is case sensitive in collations and comparisons. .IP "\s-1SEARCHABLE\s0 (integer)" 4 .IX Item "SEARCHABLE (integer)" Indicates how the data type can be used in a \s-1WHERE\s0 clause, as follows: .Sp .Vb 4 \& 0 \- Cannot be used in a WHERE clause \& 1 \- Only with a LIKE predicate \& 2 \- All comparison operators except LIKE \& 3 \- Can be used in a WHERE clause with any comparison operator .Ve .IP "\s-1UNSIGNED_ATTRIBUTE\s0 (boolean)" 4 .IX Item "UNSIGNED_ATTRIBUTE (boolean)" Indicates whether the data type is unsigned. \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1FIXED_PREC_SCALE\s0 (boolean)" 4 .IX Item "FIXED_PREC_SCALE (boolean)" Indicates whether the data type always has the same precision and scale (such as a money type). \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1AUTO_UNIQUE_VALUE\s0 (boolean)" 4 .IX Item "AUTO_UNIQUE_VALUE (boolean)" Indicates whether a column of this data type is automatically set to a unique value whenever a new row is inserted. \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1LOCAL_TYPE_NAME\s0 (string)" 4 .IX Item "LOCAL_TYPE_NAME (string)" Localized version of the \f(CW\*(C`TYPE_NAME\*(C'\fR for use in dialog with users. \&\s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned if a localized name is not available (in which case \f(CW\*(C`TYPE_NAME\*(C'\fR should be used). .IP "\s-1MINIMUM_SCALE\s0 (integer)" 4 .IX Item "MINIMUM_SCALE (integer)" The minimum scale of the data type. If a data type has a fixed scale, then \f(CW\*(C`MAXIMUM_SCALE\*(C'\fR holds the same value. \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1MAXIMUM_SCALE\s0 (integer)" 4 .IX Item "MAXIMUM_SCALE (integer)" The maximum scale of the data type. If a data type has a fixed scale, then \f(CW\*(C`MINIMUM_SCALE\*(C'\fR holds the same value. \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned for data types for which this is not applicable. .IP "\s-1SQL_DATA_TYPE\s0 (integer)" 4 .IX Item "SQL_DATA_TYPE (integer)" This column is the same as the \f(CW\*(C`DATA_TYPE\*(C'\fR column, except for interval and datetime data types. For interval and datetime data types, the \&\f(CW\*(C`SQL_DATA_TYPE\*(C'\fR field will return \f(CW\*(C`SQL_INTERVAL\*(C'\fR or \f(CW\*(C`SQL_DATETIME\*(C'\fR, and the \&\f(CW\*(C`SQL_DATETIME_SUB\*(C'\fR field below will return the subcode for the specific interval or datetime data type. If this field is \s-1NULL,\s0 then the driver does not support or report on interval or datetime subtypes. .IP "\s-1SQL_DATETIME_SUB\s0 (integer)" 4 .IX Item "SQL_DATETIME_SUB (integer)" For interval or datetime data types, where the \f(CW\*(C`SQL_DATA_TYPE\*(C'\fR field above is \f(CW\*(C`SQL_INTERVAL\*(C'\fR or \f(CW\*(C`SQL_DATETIME\*(C'\fR, this field will hold the \fIsubcode\fR for the specific interval or datetime data type. Otherwise it will be \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR). .Sp Although not mentioned explicitly in the standards, it seems there is a simple relationship between these values: .Sp .Vb 1 \& DATA_TYPE == (10 * SQL_DATA_TYPE) + SQL_DATETIME_SUB .Ve .IP "\s-1NUM_PREC_RADIX\s0 (integer)" 4 .IX Item "NUM_PREC_RADIX (integer)" The radix value of the data type. For approximate numeric types, \&\f(CW\*(C`NUM_PREC_RADIX\*(C'\fR contains the value 2 and \f(CW\*(C`COLUMN_SIZE\*(C'\fR holds the number of bits. For exact numeric types, \f(CW\*(C`NUM_PREC_RADIX\*(C'\fR contains the value 10 and \f(CW\*(C`COLUMN_SIZE\*(C'\fR holds the number of decimal digits. \s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) is returned either for data types for which this is not applicable or if the driver cannot report this information. .IP "\s-1INTERVAL_PRECISION\s0 (integer)" 4 .IX Item "INTERVAL_PRECISION (integer)" The interval leading precision for interval types. \s-1NULL\s0 is returned either for data types for which this is not applicable or if the driver cannot report this information. .PP For example, to find the type name for the fields in a select statement you can do: .PP .Vb 1 \& @names = map { scalar $dbh\->type_info($_)\->{TYPE_NAME} } @{ $sth\->{TYPE} } .Ve .PP Since \s-1DBI\s0 and \s-1ODBC\s0 drivers vary in how they map their types into the \&\s-1ISO\s0 standard types you may need to search for more than one type. Here's an example looking for a usable type to store a date: .PP .Vb 1 \& $my_date_type = $dbh\->type_info( [ SQL_DATE, SQL_TIMESTAMP ] ); .Ve .PP Similarly, to more reliably find a type to store small integers, you could use a list starting with \f(CW\*(C`SQL_SMALLINT\*(C'\fR, \f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DECIMAL\*(C'\fR, etc. .PP See also \*(L"Standards Reference Information\*(R". .PP \fI\f(CI\*(C`quote\*(C'\fI\fR .IX Subsection "quote" .PP .Vb 2 \& $sql = $dbh\->quote($value); \& $sql = $dbh\->quote($value, $data_type); .Ve .PP Quote a string literal for use as a literal value in an \s-1SQL\s0 statement, by escaping any special characters (such as quotation marks) contained within the string and adding the required type of outer quotation marks. .PP .Vb 2 \& $sql = sprintf "SELECT foo FROM bar WHERE baz = %s", \& $dbh\->quote("Don\*(Aqt"); .Ve .PP For most database types, at least those that conform to \s-1SQL\s0 standards, quote would return \f(CW\*(AqDon\*(Aq\*(Aqt\*(Aq\fR (including the outer quotation marks). For others it may return something like \f(CW\*(AqDon\e\*(Aqt\*(Aq\fR .PP An undefined \f(CW$value\fR value will be returned as the string \f(CW\*(C`NULL\*(C'\fR (without single quotation marks) to match how NULLs are represented in \s-1SQL.\s0 .PP If \f(CW$data_type\fR is supplied, it is used to try to determine the required quoting behaviour by using the information returned by \*(L"type_info\*(R". As a special case, the standard numeric types are optimized to return \&\f(CW$value\fR without calling \f(CW\*(C`type_info\*(C'\fR. .PP Quote will probably \fInot\fR be able to deal with all possible input (such as binary data or data containing newlines), and is not related in any way with escaping or quoting shell meta-characters. .PP It is valid for the \fBquote()\fR method to return an \s-1SQL\s0 expression that evaluates to the desired string. For example: .PP .Vb 1 \& $quoted = $dbh\->quote("one\entwo\e0three") .Ve .PP may return something like: .PP .Vb 1 \& CONCAT(\*(Aqone\*(Aq, CHAR(12), \*(Aqtwo\*(Aq, CHAR(0), \*(Aqthree\*(Aq) .Ve .PP The \fBquote()\fR method should \fInot\fR be used with \*(L"Placeholders and Bind Values\*(R". .PP \fI\f(CI\*(C`quote_identifier\*(C'\fI\fR .IX Subsection "quote_identifier" .PP .Vb 2 \& $sql = $dbh\->quote_identifier( $name ); \& $sql = $dbh\->quote_identifier( $catalog, $schema, $table, \e%attr ); .Ve .PP Quote an identifier (table name etc.) for use in an \s-1SQL\s0 statement, by escaping any special characters (such as double quotation marks) it contains and adding the required type of outer quotation marks. .PP Undefined names are ignored and the remainder are quoted and then joined together, typically with a dot (\f(CW\*(C`.\*(C'\fR) character. For example: .PP .Vb 1 \& $id = $dbh\->quote_identifier( undef, \*(AqHer schema\*(Aq, \*(AqMy table\*(Aq ); .Ve .PP would, for most database types, return \f(CW"Her schema"."My table"\fR (including all the double quotation marks). .PP If three names are supplied then the first is assumed to be a catalog name and special rules may be applied based on what \*(L"get_info\*(R" returns for \s-1SQL_CATALOG_NAME_SEPARATOR\s0 (41) and \s-1SQL_CATALOG_LOCATION\s0 (114). For example, for Oracle: .PP .Vb 1 \& $id = $dbh\->quote_identifier( \*(Aqlink\*(Aq, \*(Aqschema\*(Aq, \*(Aqtable\*(Aq ); .Ve .PP would return \f(CW"schema"."table"@"link"\fR. .PP \fI\f(CI\*(C`take_imp_data\*(C'\fI\fR .IX Subsection "take_imp_data" .PP .Vb 1 \& $imp_data = $dbh\->take_imp_data; .Ve .PP Leaves the \f(CW$dbh\fR in an almost dead, zombie-like, state and returns a binary string of raw implementation data from the driver which describes the current database connection. Effectively it detaches the underlying database \s-1API\s0 connection data from the \s-1DBI\s0 handle. After calling \fBtake_imp_data()\fR, all other methods except \f(CW\*(C`DESTROY\*(C'\fR will generate a warning and return undef. .PP Why would you want to do this? You don't, forget I even mentioned it. Unless, that is, you're implementing something advanced like a multi-threaded connection pool. See DBI::Pool. .PP The returned \f(CW$imp_data\fR can be passed as a \f(CW\*(C`dbi_imp_data\*(C'\fR attribute to a later \fBconnect()\fR call, even in a separate thread in the same process, where the driver can use it to 'adopt' the existing connection that the implementation data was taken from. .PP Some things to keep in mind... .PP \&\fB*\fR the \f(CW$imp_data\fR holds the only reference to the underlying database \s-1API\s0 connection data. That connection is still 'live' and won't be cleaned up properly unless the \f(CW$imp_data\fR is used to create a new \f(CW$dbh\fR which is then allowed to \fBdisconnect()\fR normally. .PP \&\fB*\fR using the same \f(CW$imp_data\fR to create more than one other new \&\f(CW$dbh\fR at a time may well lead to unpleasant problems. Don't do that. .PP Any child statement handles are effectively destroyed when \fBtake_imp_data()\fR is called. .PP The \f(CW\*(C`take_imp_data\*(C'\fR method was added in \s-1DBI 1.36\s0 but wasn't useful till 1.49. .SS "Database Handle Attributes" .IX Subsection "Database Handle Attributes" This section describes attributes specific to database handles. .PP Changes to these database handle attributes do not affect any other existing or future database handles. .PP Attempting to set or get the value of an unknown attribute generates a warning, except for private driver-specific attributes (which all have names starting with a lowercase letter). .PP Example: .PP .Vb 2 \& $h\->{AutoCommit} = ...; # set/write \& ... = $h\->{AutoCommit}; # get/read .Ve .PP \fI\f(CI\*(C`AutoCommit\*(C'\fI\fR .IX Subsection "AutoCommit" .PP Type: boolean .PP If true, then database changes cannot be rolled-back (undone). If false, then database changes automatically occur within a \*(L"transaction\*(R", which must either be committed or rolled back using the \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR methods. .PP Drivers should always default to \f(CW\*(C`AutoCommit\*(C'\fR mode (an unfortunate choice largely forced on the \s-1DBI\s0 by \s-1ODBC\s0 and \s-1JDBC\s0 conventions.) .PP Attempting to set \f(CW\*(C`AutoCommit\*(C'\fR to an unsupported value is a fatal error. This is an important feature of the \s-1DBI.\s0 Applications that need full transaction behaviour can set \f(CW\*(C`$dbh\->{AutoCommit} = 0\*(C'\fR (or set \f(CW\*(C`AutoCommit\*(C'\fR to 0 via \*(L"connect\*(R") without having to check that the value was assigned successfully. .PP For the purposes of this description, we can divide databases into three categories: .PP .Vb 3 \& Databases which don\*(Aqt support transactions at all. \& Databases in which a transaction is always active. \& Databases in which a transaction must be explicitly started (C<\*(AqBEGIN WORK\*(Aq>). .Ve .PP \&\fB* Databases which don't support transactions at all\fR .PP For these databases, attempting to turn \f(CW\*(C`AutoCommit\*(C'\fR off is a fatal error. \&\f(CW\*(C`commit\*(C'\fR and \f(CW\*(C`rollback\*(C'\fR both issue warnings about being ineffective while \&\f(CW\*(C`AutoCommit\*(C'\fR is in effect. .PP \&\fB* Databases in which a transaction is always active\fR .PP These are typically mainstream commercial relational databases with \&\*(L"\s-1ANSI\s0 standard\*(R" transaction behaviour. If \f(CW\*(C`AutoCommit\*(C'\fR is off, then changes to the database won't have any lasting effect unless \*(L"commit\*(R" is called (but see also \&\*(L"disconnect\*(R"). If \*(L"rollback\*(R" is called then any changes since the last commit are undone. .PP If \f(CW\*(C`AutoCommit\*(C'\fR is on, then the effect is the same as if the \s-1DBI\s0 called \f(CW\*(C`commit\*(C'\fR automatically after every successful database operation. So calling \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR explicitly while \&\f(CW\*(C`AutoCommit\*(C'\fR is on would be ineffective because the changes would have already been committed. .PP Changing \f(CW\*(C`AutoCommit\*(C'\fR from off to on will trigger a \*(L"commit\*(R". .PP For databases which don't support a specific auto-commit mode, the driver has to commit each statement automatically using an explicit \&\f(CW\*(C`COMMIT\*(C'\fR after it completes successfully (and roll it back using an explicit \f(CW\*(C`ROLLBACK\*(C'\fR if it fails). The error information reported to the application will correspond to the statement which was executed, unless it succeeded and the commit or rollback failed. .PP \&\fB* Databases in which a transaction must be explicitly started\fR .PP For these databases, the intention is to have them act like databases in which a transaction is always active (as described above). .PP To do this, the driver will automatically begin an explicit transaction when \f(CW\*(C`AutoCommit\*(C'\fR is turned off, or after a \*(L"commit\*(R" or \&\*(L"rollback\*(R" (or when the application issues the next database operation after one of those events). .PP In this way, the application does not have to treat these databases as a special case. .PP See \*(L"commit\*(R", \*(L"disconnect\*(R" and \*(L"Transactions\*(R" for other important notes about transactions. .PP \fI\f(CI\*(C`Driver\*(C'\fI\fR .IX Subsection "Driver" .PP Type: handle .PP Holds the handle of the parent driver. The only recommended use for this is to find the name of the driver using: .PP .Vb 1 \& $dbh\->{Driver}\->{Name} .Ve .PP \fI\f(CI\*(C`Name\*(C'\fI\fR .IX Subsection "Name" .PP Type: string .PP Holds the \*(L"name\*(R" of the database. Usually (and recommended to be) the same as the "\f(CW\*(C`dbi:DriverName:...\*(C'\fR\*(L" string used to connect to the database, but with the leading \*(R"\f(CW\*(C`dbi:DriverName:\*(C'\fR" removed. .PP \fI\f(CI\*(C`Statement\*(C'\fI\fR .IX Subsection "Statement" .PP Type: string, read-only .PP Returns the statement string passed to the most recent \*(L"prepare\*(R" or \&\*(L"do\*(R" method called in this database handle, even if that method failed. This is especially useful where \f(CW\*(C`RaiseError\*(C'\fR is enabled and the exception handler checks $@ and sees that a 'prepare' method call failed. .PP \fI\f(CI\*(C`RowCacheSize\*(C'\fI\fR .IX Subsection "RowCacheSize" .PP Type: integer .PP A hint to the driver indicating the size of the local row cache that the application would like the driver to use for future \f(CW\*(C`SELECT\*(C'\fR statements. If a row cache is not implemented, then setting \f(CW\*(C`RowCacheSize\*(C'\fR is ignored and getting the value returns \f(CW\*(C`undef\*(C'\fR. .PP Some \f(CW\*(C`RowCacheSize\*(C'\fR values have special meaning, as follows: .PP .Vb 4 \& 0 \- Automatically determine a reasonable cache size for each C. .Ve .PP Note that large cache sizes may require a very large amount of memory (\fIcached rows * maximum size of row\fR). Also, a large cache will cause a longer delay not only for the first fetch, but also whenever the cache needs refilling. .PP See also the \*(L"RowsInCache\*(R" statement handle attribute. .PP \fI\f(CI\*(C`Username\*(C'\fI\fR .IX Subsection "Username" .PP Type: string .PP Returns the username used to connect to the database. .SH "DBI STATEMENT HANDLE OBJECTS" .IX Header "DBI STATEMENT HANDLE OBJECTS" This section lists the methods and attributes associated with \s-1DBI\s0 statement handles. .SS "Statement Handle Methods" .IX Subsection "Statement Handle Methods" The \s-1DBI\s0 defines the following methods for use on \s-1DBI\s0 statement handles: .PP \fI\f(CI\*(C`bind_param\*(C'\fI\fR .IX Subsection "bind_param" .PP .Vb 3 \& $sth\->bind_param($p_num, $bind_value) \& $sth\->bind_param($p_num, $bind_value, \e%attr) \& $sth\->bind_param($p_num, $bind_value, $bind_type) .Ve .PP The \f(CW\*(C`bind_param\*(C'\fR method takes a copy of \f(CW$bind_value\fR and associates it (binds it) with a placeholder, identified by \f(CW$p_num\fR, embedded in the prepared statement. Placeholders are indicated with question mark character (\f(CW\*(C`?\*(C'\fR). For example: .PP .Vb 5 \& $dbh\->{RaiseError} = 1; # save having to check each method call \& $sth = $dbh\->prepare("SELECT name, age FROM people WHERE name LIKE ?"); \& $sth\->bind_param(1, "John%"); # placeholders are numbered from 1 \& $sth\->execute; \& DBI::dump_results($sth); .Ve .PP See \*(L"Placeholders and Bind Values\*(R" for more information. .PP \&\fBData Types for Placeholders\fR .PP The \f(CW\*(C`\e%attr\*(C'\fR parameter can be used to hint at the data type the placeholder should have. This is rarely needed. Typically, the driver is only interested in knowing if the placeholder should be bound as a number or a string. .PP .Vb 1 \& $sth\->bind_param(1, $value, { TYPE => SQL_INTEGER }); .Ve .PP As a short-cut for the common case, the data type can be passed directly, in place of the \f(CW\*(C`\e%attr\*(C'\fR hash reference. This example is equivalent to the one above: .PP .Vb 1 \& $sth\->bind_param(1, $value, SQL_INTEGER); .Ve .PP The \f(CW\*(C`TYPE\*(C'\fR value indicates the standard (non-driver-specific) type for this parameter. To specify the driver-specific type, the driver may support a driver-specific attribute, such as \f(CW\*(C`{ ora_type => 97 }\*(C'\fR. .PP The \s-1SQL_INTEGER\s0 and other related constants can be imported using .PP .Vb 1 \& use DBI qw(:sql_types); .Ve .PP See \*(L"\s-1DBI\s0 Constants\*(R" for more information. .PP The data type is 'sticky' in that bind values passed to \fBexecute()\fR are bound with the data type specified by earlier \fBbind_param()\fR calls, if any. Portable applications should not rely on being able to change the data type after the first \f(CW\*(C`bind_param\*(C'\fR call. .PP Perl only has string and number scalar data types. All database types that aren't numbers are bound as strings and must be in a format the database will understand except where the \fBbind_param()\fR \s-1TYPE\s0 attribute specifies a type that implies a particular format. For example, given: .PP .Vb 1 \& $sth\->bind_param(1, $value, SQL_DATETIME); .Ve .PP the driver should expect \f(CW$value\fR to be in the \s-1ODBC\s0 standard \s-1SQL_DATETIME\s0 format, which is '\s-1YYYY\-MM\-DD HH:MM:SS\s0'. Similarly for \s-1SQL_DATE, SQL_TIME\s0 etc. .PP As an alternative to specifying the data type in the \f(CW\*(C`bind_param\*(C'\fR call, you can let the driver pass the value as the default type (\f(CW\*(C`VARCHAR\*(C'\fR). You can then use an \s-1SQL\s0 function to convert the type within the statement. For example: .PP .Vb 1 \& INSERT INTO price(code, price) VALUES (?, CONVERT(MONEY,?)) .Ve .PP The \f(CW\*(C`CONVERT\*(C'\fR function used here is just an example. The actual function and syntax will vary between different databases and is non-portable. .PP See also \*(L"Placeholders and Bind Values\*(R" for more information. .PP \fI\f(CI\*(C`bind_param_inout\*(C'\fI\fR .IX Subsection "bind_param_inout" .PP .Vb 3 \& $rc = $sth\->bind_param_inout($p_num, \e$bind_value, $max_len) or die $sth\->errstr; \& $rv = $sth\->bind_param_inout($p_num, \e$bind_value, $max_len, \e%attr) or ... \& $rv = $sth\->bind_param_inout($p_num, \e$bind_value, $max_len, $bind_type) or ... .Ve .PP This method acts like \*(L"bind_param\*(R", but also enables values to be updated by the statement. The statement is typically a call to a stored procedure. The \f(CW$bind_value\fR must be passed as a reference to the actual value to be used. .PP Note that unlike \*(L"bind_param\*(R", the \f(CW$bind_value\fR variable is not copied when \f(CW\*(C`bind_param_inout\*(C'\fR is called. Instead, the value in the variable is read at the time \*(L"execute\*(R" is called. .PP The additional \f(CW$max_len\fR parameter specifies the minimum amount of memory to allocate to \f(CW$bind_value\fR for the new value. If the value returned from the database is too big to fit, then the execution should fail. If unsure what value to use, pick a generous length, i.e., a length larger than the longest value that would ever be returned. The only cost of using a larger value than needed is wasted memory. .PP Undefined values or \f(CW\*(C`undef\*(C'\fR are used to indicate null values. See also \*(L"Placeholders and Bind Values\*(R" for more information. .PP \fI\f(CI\*(C`bind_param_array\*(C'\fI\fR .IX Subsection "bind_param_array" .PP .Vb 3 \& $rc = $sth\->bind_param_array($p_num, $array_ref_or_value) \& $rc = $sth\->bind_param_array($p_num, $array_ref_or_value, \e%attr) \& $rc = $sth\->bind_param_array($p_num, $array_ref_or_value, $bind_type) .Ve .PP The \f(CW\*(C`bind_param_array\*(C'\fR method is used to bind an array of values to a placeholder embedded in the prepared statement which is to be executed with \*(L"execute_array\*(R". For example: .PP .Vb 6 \& $dbh\->{RaiseError} = 1; # save having to check each method call \& $sth = $dbh\->prepare("INSERT INTO staff (first_name, last_name, dept) VALUES(?, ?, ?)"); \& $sth\->bind_param_array(1, [ \*(AqJohn\*(Aq, \*(AqMary\*(Aq, \*(AqTim\*(Aq ]); \& $sth\->bind_param_array(2, [ \*(AqBooth\*(Aq, \*(AqTodd\*(Aq, \*(AqRobinson\*(Aq ]); \& $sth\->bind_param_array(3, "SALES"); # scalar will be reused for each row \& $sth\->execute_array( { ArrayTupleStatus => \emy @tuple_status } ); .Ve .PP The \f(CW%attr\fR ($bind_type) argument is the same as defined for \*(L"bind_param\*(R". Refer to \*(L"bind_param\*(R" for general details on using placeholders. .PP (Note that \fBbind_param_array()\fR can \fInot\fR be used to expand a placeholder into a list of values for a statement like \*(L"\s-1SELECT\s0 foo \&\s-1WHERE\s0 bar \s-1IN\s0 (?)\*(R". A placeholder can only ever represent one value per execution.) .PP Scalar values, including \f(CW\*(C`undef\*(C'\fR, may also be bound by \&\f(CW\*(C`bind_param_array\*(C'\fR. In which case the same value will be used for each \&\*(L"execute\*(R" call. Driver-specific implementations may behave differently, e.g., when binding to a stored procedure call, some databases may permit mixing scalars and arrays as arguments. .PP The default implementation provided by \s-1DBI\s0 (for drivers that have not implemented array binding) is to iteratively call \*(L"execute\*(R" for each parameter tuple provided in the bound arrays. Drivers may provide more optimized implementations using whatever bulk operation support the database \s-1API\s0 provides. The default driver behaviour should match the default \s-1DBI\s0 behaviour, but always consult your driver documentation as there may be driver specific issues to consider. .PP Note that the default implementation currently only supports non-data returning statements (\s-1INSERT, UPDATE,\s0 but not \s-1SELECT\s0). Also, \&\f(CW\*(C`bind_param_array\*(C'\fR and \*(L"bind_param\*(R" cannot be mixed in the same statement execution, and \f(CW\*(C`bind_param_array\*(C'\fR must be used with \&\*(L"execute_array\*(R"; using \f(CW\*(C`bind_param_array\*(C'\fR will have no effect for \*(L"execute\*(R". .PP The \f(CW\*(C`bind_param_array\*(C'\fR method was added in \s-1DBI 1.22.\s0 .PP \fI\f(CI\*(C`execute\*(C'\fI\fR .IX Subsection "execute" .PP .Vb 2 \& $rv = $sth\->execute or die $sth\->errstr; \& $rv = $sth\->execute(@bind_values) or die $sth\->errstr; .Ve .PP Perform whatever processing is necessary to execute the prepared statement. An \f(CW\*(C`undef\*(C'\fR is returned if an error occurs. A successful \&\f(CW\*(C`execute\*(C'\fR always returns true regardless of the number of rows affected, even if it's zero (see below). It is always important to check the return status of \f(CW\*(C`execute\*(C'\fR (and most other \s-1DBI\s0 methods) for errors if you're not using \*(L"RaiseError\*(R". .PP For a \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR statement, \f(CW\*(C`execute\*(C'\fR returns the number of rows affected, if known. If no rows were affected, then \f(CW\*(C`execute\*(C'\fR returns "\f(CW0E0\fR", which Perl will treat as 0 but will regard as true. Note that it is \fInot\fR an error for no rows to be affected by a statement. If the number of rows affected is not known, then \f(CW\*(C`execute\*(C'\fR returns \-1. .PP For \f(CW\*(C`SELECT\*(C'\fR statements, execute simply \*(L"starts\*(R" the query within the database engine. Use one of the fetch methods to retrieve the data after calling \f(CW\*(C`execute\*(C'\fR. The \f(CW\*(C`execute\*(C'\fR method does \fInot\fR return the number of rows that will be returned by the query (because most databases can't tell in advance), it simply returns a true value. .PP You can tell if the statement was a \f(CW\*(C`SELECT\*(C'\fR statement by checking if \&\f(CW\*(C`$sth\->{NUM_OF_FIELDS}\*(C'\fR is greater than zero after calling \f(CW\*(C`execute\*(C'\fR. .PP If any arguments are given, then \f(CW\*(C`execute\*(C'\fR will effectively call \&\*(L"bind_param\*(R" for each value before executing the statement. Values bound in this way are usually treated as \f(CW\*(C`SQL_VARCHAR\*(C'\fR types unless the driver can determine the correct type (which is rare), or unless \&\f(CW\*(C`bind_param\*(C'\fR (or \f(CW\*(C`bind_param_inout\*(C'\fR) has already been used to specify the type. .PP Note that passing \f(CW\*(C`execute\*(C'\fR an empty array is the same as passing no arguments at all, which will execute the statement with previously bound values. That's probably not what you want. .PP If \fBexecute()\fR is called on a statement handle that's still active ($sth\->{Active} is true) then it should effectively call \fBfinish()\fR to tidy up the previous execution results before starting this new execution. .PP \fI\f(CI\*(C`execute_array\*(C'\fI\fR .IX Subsection "execute_array" .PP .Vb 2 \& $tuples = $sth\->execute_array(\e%attr) or die $sth\->errstr; \& $tuples = $sth\->execute_array(\e%attr, @bind_values) or die $sth\->errstr; \& \& ($tuples, $rows) = $sth\->execute_array(\e%attr) or die $sth\->errstr; \& ($tuples, $rows) = $sth\->execute_array(\e%attr, @bind_values) or die $sth\->errstr; .Ve .PP Execute the prepared statement once for each parameter tuple (group of values) provided either in the \f(CW@bind_values\fR, or by prior calls to \*(L"bind_param_array\*(R", or via a reference passed in \e%attr. .PP When called in scalar context the \fBexecute_array()\fR method returns the number of tuples executed, or \f(CW\*(C`undef\*(C'\fR if an error occurred. Like \&\fBexecute()\fR, a successful \fBexecute_array()\fR always returns true regardless of the number of tuples executed, even if it's zero. If there were any errors the ArrayTupleStatus array can be used to discover which tuples failed and with what errors. .PP When called in list context the \fBexecute_array()\fR method returns two scalars; \&\f(CW$tuples\fR is the same as calling \fBexecute_array()\fR in scalar context and \f(CW$rows\fR is the number of rows affected for each tuple, if available or \&\-1 if the driver cannot determine this. \s-1NOTE,\s0 some drivers cannot determine the number of rows affected per tuple but can provide the number of rows affected for the batch. If you are doing an update operation the returned rows affected may not be what you expect if, for instance, one or more of the tuples affected the same row multiple times. Some drivers may not yet support list context, in which case \&\f(CW$rows\fR will be undef, or may not be able to provide the number of rows affected when performing this batch operation, in which case \f(CW$rows\fR will be \-1. .PP Bind values for the tuples to be executed may be supplied row-wise by an \f(CW\*(C`ArrayTupleFetch\*(C'\fR attribute, or else column-wise in the \&\f(CW@bind_values\fR argument, or else column-wise by prior calls to \&\*(L"bind_param_array\*(R". .PP Where column-wise binding is used (via the \f(CW@bind_values\fR argument or calls to \fBbind_param_array()\fR) the maximum number of elements in any one of the bound value arrays determines the number of tuples executed. Placeholders with fewer values in their parameter arrays are treated as if padded with undef (\s-1NULL\s0) values. .PP If a scalar value is bound, instead of an array reference, it is treated as a \fIvariable\fR length array with all elements having the same value. It does not influence the number of tuples executed, so if all bound arrays have zero elements then zero tuples will be executed. If \fIall\fR bound values are scalars then one tuple will be executed, making \fBexecute_array()\fR act just like \fBexecute()\fR. .PP The \f(CW\*(C`ArrayTupleFetch\*(C'\fR attribute can be used to specify a reference to a subroutine that will be called to provide the bind values for each tuple execution. The subroutine should return an reference to an array which contains the appropriate number of bind values, or return an undef if there is no more data to execute. .PP As a convenience, the \f(CW\*(C`ArrayTupleFetch\*(C'\fR attribute can also be used to specify a statement handle. In which case the \fBfetchrow_arrayref()\fR method will be called on the given statement handle in order to provide the bind values for each tuple execution. .PP The values specified via \fBbind_param_array()\fR or the \f(CW@bind_values\fR parameter may be either scalars, or arrayrefs. If any \f(CW@bind_values\fR are given, then \f(CW\*(C`execute_array\*(C'\fR will effectively call \*(L"bind_param_array\*(R" for each value before executing the statement. Values bound in this way are usually treated as \f(CW\*(C`SQL_VARCHAR\*(C'\fR types unless the driver can determine the correct type (which is rare), or unless \&\f(CW\*(C`bind_param\*(C'\fR, \f(CW\*(C`bind_param_inout\*(C'\fR, \f(CW\*(C`bind_param_array\*(C'\fR, or \&\f(CW\*(C`bind_param_inout_array\*(C'\fR has already been used to specify the type. See \*(L"bind_param_array\*(R" for details. .PP The \f(CW\*(C`ArrayTupleStatus\*(C'\fR attribute can be used to specify a reference to an array which will receive the execute status of each executed parameter tuple. Note the \f(CW\*(C`ArrayTupleStatus\*(C'\fR attribute was mandatory until \s-1DBI 1.38.\s0 .PP For tuples which are successfully executed, the element at the same ordinal position in the status array is the resulting rowcount (or \-1 if unknown). If the execution of a tuple causes an error, then the corresponding status array element will be set to a reference to an array containing \&\*(L"err\*(R", \*(L"errstr\*(R" and \*(L"state\*(R" set by the failed execution. .PP If \fBany\fR tuple execution returns an error, \f(CW\*(C`execute_array\*(C'\fR will return \f(CW\*(C`undef\*(C'\fR. In that case, the application should inspect the status array to determine which parameter tuples failed. Some databases may not continue executing tuples beyond the first failure. In this case the status array will either hold fewer elements, or the elements beyond the failure will be undef. .PP If all parameter tuples are successfully executed, \f(CW\*(C`execute_array\*(C'\fR returns the number tuples executed. If no tuples were executed, then \fBexecute_array()\fR returns "\f(CW0E0\fR", just like \fBexecute()\fR does, which Perl will treat as 0 but will regard as true. .PP For example: .PP .Vb 10 \& $sth = $dbh\->prepare("INSERT INTO staff (first_name, last_name) VALUES (?, ?)"); \& my $tuples = $sth\->execute_array( \& { ArrayTupleStatus => \emy @tuple_status }, \& \e@first_names, \& \e@last_names, \& ); \& if ($tuples) { \& print "Successfully inserted $tuples records\en"; \& } \& else { \& for my $tuple (0..@last_names\-1) { \& my $status = $tuple_status[$tuple]; \& $status = [0, "Skipped"] unless defined $status; \& next unless ref $status; \& printf "Failed to insert (%s, %s): %s\en", \& $first_names[$tuple], $last_names[$tuple], $status\->[1]; \& } \& } .Ve .PP Support for data returning statements such as \s-1SELECT\s0 is driver-specific and subject to change. At present, the default implementation provided by \s-1DBI\s0 only supports non-data returning statements. .PP Transaction semantics when using array binding are driver and database specific. If \f(CW\*(C`AutoCommit\*(C'\fR is on, the default \s-1DBI\s0 implementation will cause each parameter tuple to be individually committed (or rolled back in the event of an error). If \f(CW\*(C`AutoCommit\*(C'\fR is off, the application is responsible for explicitly committing the entire set of bound parameter tuples. Note that different drivers and databases may have different behaviours when some parameter tuples cause failures. In some cases, the driver or database may automatically rollback the effect of all prior parameter tuples that succeeded in the transaction; other drivers or databases may retain the effect of prior successfully executed parameter tuples. Be sure to check your driver and database for its specific behaviour. .PP Note that, in general, performance will usually be better with \&\f(CW\*(C`AutoCommit\*(C'\fR turned off, and using explicit \f(CW\*(C`commit\*(C'\fR after each \&\f(CW\*(C`execute_array\*(C'\fR call. .PP The \f(CW\*(C`execute_array\*(C'\fR method was added in \s-1DBI 1.22,\s0 and ArrayTupleFetch was added in 1.36. .PP \fI\f(CI\*(C`execute_for_fetch\*(C'\fI\fR .IX Subsection "execute_for_fetch" .PP .Vb 2 \& $tuples = $sth\->execute_for_fetch($fetch_tuple_sub); \& $tuples = $sth\->execute_for_fetch($fetch_tuple_sub, \e@tuple_status); \& \& ($tuples, $rows) = $sth\->execute_for_fetch($fetch_tuple_sub); \& ($tuples, $rows) = $sth\->execute_for_fetch($fetch_tuple_sub, \e@tuple_status); .Ve .PP The \fBexecute_for_fetch()\fR method is used to perform bulk operations and although it is most often used via the \fBexecute_array()\fR method you can use it directly. The main difference between execute_array and execute_for_fetch is the former does column or row-wise binding and the latter uses row-wise binding. .PP The fetch subroutine, referenced by \f(CW$fetch_tuple_sub\fR, is expected to return a reference to an array (known as a 'tuple') or undef. .PP The \fBexecute_for_fetch()\fR method calls \f(CW$fetch_tuple_sub\fR, without any parameters, until it returns a false value. Each tuple returned is used to provide bind values for an \f(CW$sth\fR\->execute(@$tuple) call. .PP In scalar context \fBexecute_for_fetch()\fR returns \f(CW\*(C`undef\*(C'\fR if there were any errors and the number of tuples executed otherwise. Like \fBexecute()\fR and \&\fBexecute_array()\fR a zero is returned as \*(L"0E0\*(R" so \fBexecute_for_fetch()\fR is only false on error. If there were any errors the \f(CW@tuple_status\fR array can be used to discover which tuples failed and with what errors. .PP When called in list context \fBexecute_for_fetch()\fR returns two scalars; \&\f(CW$tuples\fR is the same as calling \fBexecute_for_fetch()\fR in scalar context and \f(CW$rows\fR is the sum of the number of rows affected for each tuple, if available or \-1 if the driver cannot determine this. If you are doing an update operation the returned rows affected may not be what you expect if, for instance, one or more of the tuples affected the same row multiple times. Some drivers may not yet support list context, in which case \&\f(CW$rows\fR will be undef, or may not be able to provide the number of rows affected when performing this batch operation, in which case \f(CW$rows\fR will be \-1. .PP If \e@tuple_status is passed then the execute_for_fetch method uses it to return status information. The tuple_status array holds one element per tuple. If the corresponding \fBexecute()\fR did not fail then the element holds the return value from \fBexecute()\fR, which is typically a row count. If the \fBexecute()\fR did fail then the element holds a reference to an array containing ($sth\->err, \f(CW$sth\fR\->errstr, \f(CW$sth\fR\->state). .PP If the driver detects an error that it knows means no further tuples can be executed then it may return, with an error status, even though \f(CW$fetch_tuple_sub\fR may still have more tuples to be executed. .PP Although each tuple returned by \f(CW$fetch_tuple_sub\fR is effectively used to call \f(CW$sth\fR\->execute(@$tuple_array_ref) the exact timing may vary. Drivers are free to accumulate sets of tuples to pass to the database server in bulk group operations for more efficient execution. However, the \f(CW$fetch_tuple_sub\fR is specifically allowed to return the same array reference each time (which is what \fBfetchrow_arrayref()\fR usually does). .PP For example: .PP .Vb 2 \& my $sel = $dbh1\->prepare("select foo, bar from table1"); \& $sel\->execute; \& \& my $ins = $dbh2\->prepare("insert into table2 (foo, bar) values (?,?)"); \& my $fetch_tuple_sub = sub { $sel\->fetchrow_arrayref }; \& \& my @tuple_status; \& $rc = $ins\->execute_for_fetch($fetch_tuple_sub, \e@tuple_status); \& my @errors = grep { ref $_ } @tuple_status; .Ve .PP Similarly, if you already have an array containing the data rows to be processed you'd use a subroutine to shift off and return each array ref in turn: .PP .Vb 1 \& $ins\->execute_for_fetch( sub { shift @array_of_arrays }, \e@tuple_status); .Ve .PP The \f(CW\*(C`execute_for_fetch\*(C'\fR method was added in \s-1DBI 1.38.\s0 .PP \fI\f(CI\*(C`last_insert_id\*(C'\fI\fR .IX Subsection "last_insert_id" .PP .Vb 3 \& $rv = $sth\->last_insert_id(); \& $rv = $sth\->last_insert_id($catalog, $schema, $table, $field); \& $rv = $sth\->last_insert_id($catalog, $schema, $table, $field, \e%attr); .Ve .PP Returns a value 'identifying' the row inserted by last execution of the statement \f(CW$sth\fR, if possible. .PP For some drivers the value may be 'identifying' the row inserted by the last executed statement, not by \f(CW$sth\fR. .PP See database handle method last_insert_id for all details. .PP The \f(CW\*(C`last_insert_id\*(C'\fR statement method was added in \s-1DBI 1.642.\s0 .PP \fI\f(CI\*(C`fetchrow_arrayref\*(C'\fI\fR .IX Subsection "fetchrow_arrayref" .PP .Vb 2 \& $ary_ref = $sth\->fetchrow_arrayref; \& $ary_ref = $sth\->fetch; # alias .Ve .PP Fetches the next row of data and returns a reference to an array holding the field values. Null fields are returned as \f(CW\*(C`undef\*(C'\fR values in the array. This is the fastest way to fetch data, particularly if used with \&\f(CW\*(C`$sth\->bind_columns\*(C'\fR. .PP If there are no more rows or if an error occurs, then \f(CW\*(C`fetchrow_arrayref\*(C'\fR returns an \f(CW\*(C`undef\*(C'\fR. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the \&\f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the \f(CW\*(C`undef\*(C'\fR returned was due to an error. .PP Note that the same array reference is returned for each fetch, so don't store the reference and then use it after a later fetch. Also, the elements of the array are also reused for each row, so take care if you want to take a reference to an element. See also \*(L"bind_columns\*(R". .PP \fI\f(CI\*(C`fetchrow_array\*(C'\fI\fR .IX Subsection "fetchrow_array" .PP .Vb 1 \& @ary = $sth\->fetchrow_array; .Ve .PP An alternative to \f(CW\*(C`fetchrow_arrayref\*(C'\fR. Fetches the next row of data and returns it as a list containing the field values. Null fields are returned as \f(CW\*(C`undef\*(C'\fR values in the list. .PP If there are no more rows or if an error occurs, then \f(CW\*(C`fetchrow_array\*(C'\fR returns an empty list. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the empty list returned was due to an error. .PP If called in a scalar context for a statement handle that has more than one column, it is undefined whether the driver will return the value of the first column or the last. So don't do that. Also, in a scalar context, an \f(CW\*(C`undef\*(C'\fR is returned if there are no more rows or if an error occurred. That \f(CW\*(C`undef\*(C'\fR can't be distinguished from an \f(CW\*(C`undef\*(C'\fR returned because the first field value was \s-1NULL.\s0 For these reasons you should exercise some caution if you use \&\f(CW\*(C`fetchrow_array\*(C'\fR in a scalar context. .PP \fI\f(CI\*(C`fetchrow_hashref\*(C'\fI\fR .IX Subsection "fetchrow_hashref" .PP .Vb 2 \& $hash_ref = $sth\->fetchrow_hashref; \& $hash_ref = $sth\->fetchrow_hashref($name); .Ve .PP An alternative to \f(CW\*(C`fetchrow_arrayref\*(C'\fR. Fetches the next row of data and returns it as a reference to a hash containing field name and field value pairs. Null fields are returned as \f(CW\*(C`undef\*(C'\fR values in the hash. .PP If there are no more rows or if an error occurs, then \f(CW\*(C`fetchrow_hashref\*(C'\fR returns an \f(CW\*(C`undef\*(C'\fR. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the \&\f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the \f(CW\*(C`undef\*(C'\fR returned was due to an error. .PP The optional \f(CW$name\fR parameter specifies the name of the statement handle attribute. For historical reasons it defaults to "\f(CW\*(C`NAME\*(C'\fR\*(L", however using either \*(R"\f(CW\*(C`NAME_lc\*(C'\fR\*(L" or \*(R"\f(CW\*(C`NAME_uc\*(C'\fR" is recommended for portability. .PP The keys of the hash are the same names returned by \f(CW\*(C`$sth\->{$name}\*(C'\fR. If more than one field has the same name, there will only be one entry in the returned hash for those fields, so statements like "\f(CW\*(C`select foo, foo from bar\*(C'\fR" will return only a single key from \f(CW\*(C`fetchrow_hashref\*(C'\fR. In these cases use column aliases or \f(CW\*(C`fetchrow_arrayref\*(C'\fR. Note that it is the database server (and not the \s-1DBD\s0 implementation) which provides the \fIname\fR for fields containing functions like "\f(CWcount(*)\fR\*(L" or \*(R"\f(CW\*(C`max(c_foo)\*(C'\fR" and they may clash with existing column names (most databases don't care about duplicate column names in a result-set). If you want these to return as unique names that are the same across databases, use \fIaliases\fR, as in "\f(CW\*(C`select count(*) as cnt\*(C'\fR\*(L" or \*(R"\f(CW\*(C`select max(c_foo) mx_foo, ...\*(C'\fR" depending on the syntax your database supports. .PP Because of the extra work \f(CW\*(C`fetchrow_hashref\*(C'\fR and Perl have to perform, it is not as efficient as \f(CW\*(C`fetchrow_arrayref\*(C'\fR or \f(CW\*(C`fetchrow_array\*(C'\fR. .PP By default a reference to a new hash is returned for each row. It is likely that a future version of the \s-1DBI\s0 will support an attribute which will enable the same hash to be reused for each row. This will give a significant performance boost, but it won't be enabled by default because of the risk of breaking old code. .PP \fI\f(CI\*(C`fetchall_arrayref\*(C'\fI\fR .IX Subsection "fetchall_arrayref" .PP .Vb 3 \& $tbl_ary_ref = $sth\->fetchall_arrayref; \& $tbl_ary_ref = $sth\->fetchall_arrayref( $slice ); \& $tbl_ary_ref = $sth\->fetchall_arrayref( $slice, $max_rows ); .Ve .PP The \f(CW\*(C`fetchall_arrayref\*(C'\fR method can be used to fetch all the data to be returned from a prepared and executed statement handle. It returns a reference to an array that contains one reference per row. .PP If called on an \fIinactive\fR statement handle, \f(CW\*(C`fetchall_arrayref\*(C'\fR returns undef. .PP If there are no rows left to return from an \fIactive\fR statement handle, \f(CW\*(C`fetchall_arrayref\*(C'\fR returns a reference to an empty array. If an error occurs, \f(CW\*(C`fetchall_arrayref\*(C'\fR returns the data fetched thus far, which may be none. You should check \f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the data is complete or was truncated due to an error. .PP If \f(CW$slice\fR is an array reference, \f(CW\*(C`fetchall_arrayref\*(C'\fR uses \*(L"fetchrow_arrayref\*(R" to fetch each row as an array ref. If the \f(CW$slice\fR array is not empty then it is used as a slice to select individual columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1). .PP With no parameters, or if \f(CW$slice\fR is undefined, \f(CW\*(C`fetchall_arrayref\*(C'\fR acts as if passed an empty array ref. .PP For example, to fetch just the first column of every row: .PP .Vb 1 \& $tbl_ary_ref = $sth\->fetchall_arrayref([0]); .Ve .PP To fetch the second to last and last column of every row: .PP .Vb 1 \& $tbl_ary_ref = $sth\->fetchall_arrayref([\-2,\-1]); .Ve .PP Those two examples both return a reference to an array of array refs. .PP If \f(CW$slice\fR is a hash reference, \f(CW\*(C`fetchall_arrayref\*(C'\fR fetches each row as a hash reference. If the \f(CW$slice\fR hash is empty then the keys in the hashes have whatever name lettercase is returned by default. (See \*(L"FetchHashKeyName\*(R" attribute.) If the \f(CW$slice\fR hash is \fInot\fR empty, then it is used as a slice to select individual columns by name. The values of the hash should be set to 1. The key names of the returned hashes match the letter case of the names in the parameter hash, regardless of the \*(L"FetchHashKeyName\*(R" attribute. .PP For example, to fetch all fields of every row as a hash ref: .PP .Vb 1 \& $tbl_ary_ref = $sth\->fetchall_arrayref({}); .Ve .PP To fetch only the fields called \*(L"foo\*(R" and \*(L"bar\*(R" of every row as a hash ref (with keys named \*(L"foo\*(R" and \*(L"\s-1BAR\*(R",\s0 regardless of the original capitalization): .PP .Vb 1 \& $tbl_ary_ref = $sth\->fetchall_arrayref({ foo=>1, BAR=>1 }); .Ve .PP Those two examples both return a reference to an array of hash refs. .PP If \f(CW$slice\fR is a \fIreference to a hash reference\fR, that hash is used to select and rename columns. The keys are 0\-based column index numbers and the values are the corresponding keys for the returned row hashes. .PP For example, to fetch only the first and second columns of every row as a hash ref (with keys named \*(L"k\*(R" and \*(L"v\*(R" regardless of their original names): .PP .Vb 1 \& $tbl_ary_ref = $sth\->fetchall_arrayref( \e{ 0 => \*(Aqk\*(Aq, 1 => \*(Aqv\*(Aq } ); .Ve .PP If \f(CW$max_rows\fR is defined and greater than or equal to zero then it is used to limit the number of rows fetched before returning. \&\fBfetchall_arrayref()\fR can then be called again to fetch more rows. This is especially useful when you need the better performance of \&\fBfetchall_arrayref()\fR but don't have enough memory to fetch and return all the rows in one go. .PP Here's an example (assumes RaiseError is enabled): .PP .Vb 6 \& my $rows = []; # cache for batches of rows \& while( my $row = ( shift(@$rows) || # get row from cache, or reload cache: \& shift(@{$rows=$sth\->fetchall_arrayref(undef,10_000)||[]}) ) \& ) { \& ... \& } .Ve .PP That \fImight\fR be the fastest way to fetch and process lots of rows using the \s-1DBI,\s0 but it depends on the relative cost of method calls vs memory allocation. .PP A standard \f(CW\*(C`while\*(C'\fR loop with column binding is often faster because the cost of allocating memory for the batch of rows is greater than the saving by reducing method calls. It's possible that the \s-1DBI\s0 may provide a way to reuse the memory of a previous batch in future, which would then shift the balance back towards \fBfetchall_arrayref()\fR. .PP \fI\f(CI\*(C`fetchall_hashref\*(C'\fI\fR .IX Subsection "fetchall_hashref" .PP .Vb 1 \& $hash_ref = $sth\->fetchall_hashref($key_field); .Ve .PP The \f(CW\*(C`fetchall_hashref\*(C'\fR method can be used to fetch all the data to be returned from a prepared and executed statement handle. It returns a reference to a hash containing a key for each distinct value of the \f(CW$key_field\fR column that was fetched. For each key the corresponding value is a reference to a hash containing all the selected columns and their values, as returned by \&\f(CW\*(C`fetchrow_hashref()\*(C'\fR. .PP If there are no rows to return, \f(CW\*(C`fetchall_hashref\*(C'\fR returns a reference to an empty hash. If an error occurs, \f(CW\*(C`fetchall_hashref\*(C'\fR returns the data fetched thus far, which may be none. You should check \&\f(CW\*(C`$sth\->err\*(C'\fR afterwards (or use the \f(CW\*(C`RaiseError\*(C'\fR attribute) to discover if the data is complete or was truncated due to an error. .PP The \f(CW$key_field\fR parameter provides the name of the field that holds the value to be used for the key for the returned hash. For example: .PP .Vb 5 \& $dbh\->{FetchHashKeyName} = \*(AqNAME_lc\*(Aq; \& $sth = $dbh\->prepare("SELECT FOO, BAR, ID, NAME, BAZ FROM TABLE"); \& $sth\->execute; \& $hash_ref = $sth\->fetchall_hashref(\*(Aqid\*(Aq); \& print "Name for id 42 is $hash_ref\->{42}\->{name}\en"; .Ve .PP The \f(CW$key_field\fR parameter can also be specified as an integer column number (counting from 1). If \f(CW$key_field\fR doesn't match any column in the statement, as a name first then as a number, then an error is returned. .PP For queries returning more than one 'key' column, you can specify multiple column names by passing \f(CW$key_field\fR as a reference to an array containing one or more key column names (or index numbers). For example: .PP .Vb 4 \& $sth = $dbh\->prepare("SELECT foo, bar, baz FROM table"); \& $sth\->execute; \& $hash_ref = $sth\->fetchall_hashref( [ qw(foo bar) ] ); \& print "For foo 42 and bar 38, baz is $hash_ref\->{42}\->{38}\->{baz}\en"; .Ve .PP The \fBfetchall_hashref()\fR method is normally used only where the key fields values for each row are unique. If multiple rows are returned with the same values for the key fields then later rows overwrite earlier ones. .PP \fI\f(CI\*(C`finish\*(C'\fI\fR .IX Subsection "finish" .PP .Vb 1 \& $rc = $sth\->finish; .Ve .PP Indicate that no more data will be fetched from this statement handle before it is either executed again or destroyed. You almost certainly do \fInot\fR need to call this method. .PP Adding calls to \f(CW\*(C`finish\*(C'\fR after loop that fetches all rows is a common mistake, don't do it, it can mask genuine problems like uncaught fetch errors. .PP When all the data has been fetched from a \f(CW\*(C`SELECT\*(C'\fR statement, the driver will automatically call \f(CW\*(C`finish\*(C'\fR for you. So you should \fInot\fR call it explicitly \&\fIexcept\fR when you know that you've not fetched all the data from a statement handle \fIand\fR the handle won't be destroyed soon. .PP The most common example is when you only want to fetch just one row, but in that case the \f(CW\*(C`selectrow_*\*(C'\fR methods are usually better anyway. .PP Consider a query like: .PP .Vb 1 \& SELECT foo FROM table WHERE bar=? ORDER BY baz .Ve .PP on a very large table. When executed, the database server will have to use temporary buffer space to store the sorted rows. If, after executing the handle and selecting just a few rows, the handle won't be re-executed for some time and won't be destroyed, the \f(CW\*(C`finish\*(C'\fR method can be used to tell the server that the buffer space can be freed. .PP Calling \f(CW\*(C`finish\*(C'\fR resets the \*(L"Active\*(R" attribute for the statement. It may also make some statement handle attributes (such as \f(CW\*(C`NAME\*(C'\fR and \f(CW\*(C`TYPE\*(C'\fR) unavailable if they have not already been accessed (and thus cached). .PP The \f(CW\*(C`finish\*(C'\fR method does not affect the transaction status of the database connection. It has nothing to do with transactions. It's mostly an internal \*(L"housekeeping\*(R" method that is rarely needed. See also \*(L"disconnect\*(R" and the \*(L"Active\*(R" attribute. .PP The \f(CW\*(C`finish\*(C'\fR method should have been called \f(CW\*(C`discard_pending_rows\*(C'\fR. .PP \fI\f(CI\*(C`rows\*(C'\fI\fR .IX Subsection "rows" .PP .Vb 1 \& $rv = $sth\->rows; .Ve .PP Returns the number of rows affected by the last row affecting command, or \-1 if the number of rows is not known or not available. .PP Generally, you can only rely on a row count after a \fInon\fR\-\f(CW\*(C`SELECT\*(C'\fR \&\f(CW\*(C`execute\*(C'\fR (for some specific operations like \f(CW\*(C`UPDATE\*(C'\fR and \f(CW\*(C`DELETE\*(C'\fR), or after fetching all the rows of a \f(CW\*(C`SELECT\*(C'\fR statement. .PP For \f(CW\*(C`SELECT\*(C'\fR statements, it is generally not possible to know how many rows will be returned except by fetching them all. Some drivers will return the number of rows the application has fetched so far, but others may return \-1 until all rows have been fetched. So use of the \&\f(CW\*(C`rows\*(C'\fR method or \f(CW$DBI::rows\fR with \f(CW\*(C`SELECT\*(C'\fR statements is not recommended. .PP One alternative method to get a row count for a \f(CW\*(C`SELECT\*(C'\fR is to execute a \&\*(L"\s-1SELECT COUNT\s0(*) \s-1FROM ...\*(R" SQL\s0 statement with the same \*(L"...\*(R" as your query and then fetch the row count from that. .PP \fI\f(CI\*(C`bind_col\*(C'\fI\fR .IX Subsection "bind_col" .PP .Vb 3 \& $rc = $sth\->bind_col($column_number, \e$var_to_bind); \& $rc = $sth\->bind_col($column_number, \e$var_to_bind, \e%attr ); \& $rc = $sth\->bind_col($column_number, \e$var_to_bind, $bind_type ); .Ve .PP Binds a Perl variable and/or some attributes to an output column (field) of a \f(CW\*(C`SELECT\*(C'\fR statement. Column numbers count up from 1. You do not need to bind output columns in order to fetch data. For maximum portability between drivers, \fBbind_col()\fR should be called after \fBexecute()\fR and not before. See also \*(L"bind_columns\*(R" for an example. .PP The binding is performed at a low level using Perl aliasing. Whenever a row is fetched from the database \f(CW$var_to_bind\fR appears to be automatically updated simply because it now refers to the same memory location as the corresponding column value. This makes using bound variables very efficient. Binding a tied variable doesn't work, currently. .PP The \*(L"bind_param\*(R" method performs a similar, but opposite, function for input variables. .PP \&\fBData Types for Column Binding\fR .PP The \f(CW\*(C`\e%attr\*(C'\fR parameter can be used to hint at the data type formatting the column should have. For example, you can use: .PP .Vb 1 \& $sth\->bind_col(1, undef, { TYPE => SQL_DATETIME }); .Ve .PP to specify that you'd like the column (which presumably is some kind of datetime type) to be returned in the standard format for \&\s-1SQL_DATETIME,\s0 which is '\s-1YYYY\-MM\-DD HH:MM:SS\s0', rather than the native formatting the database would normally use. .PP There's no \f(CW$var_to_bind\fR in that example to emphasize the point that \fBbind_col()\fR works on the underlying column and not just a particular bound variable. .PP As a short-cut for the common case, the data type can be passed directly, in place of the \f(CW\*(C`\e%attr\*(C'\fR hash reference. This example is equivalent to the one above: .PP .Vb 1 \& $sth\->bind_col(1, undef, SQL_DATETIME); .Ve .PP The \f(CW\*(C`TYPE\*(C'\fR value indicates the standard (non-driver-specific) type for this parameter. To specify the driver-specific type, the driver may support a driver-specific attribute, such as \f(CW\*(C`{ ora_type => 97 }\*(C'\fR. .PP The \s-1SQL_DATETIME\s0 and other related constants can be imported using .PP .Vb 1 \& use DBI qw(:sql_types); .Ve .PP See \*(L"\s-1DBI\s0 Constants\*(R" for more information. .PP Few drivers support specifying a data type via a \f(CW\*(C`bind_col\*(C'\fR call (most will simply ignore the data type). Fewer still allow the data type to be altered once set. If you do set a column type the type should remain sticky through further calls to bind_col for the same column if the type is not overridden (this is important for instance when you are using a slice in fetchall_arrayref). .PP The \s-1TYPE\s0 attribute for \fBbind_col()\fR was first specified in \s-1DBI 1.41.\s0 .PP From \s-1DBI 1.611,\s0 drivers can use the \f(CW\*(C`TYPE\*(C'\fR attribute to attempt to cast the bound scalar to a perl type which more closely matches \&\f(CW\*(C`TYPE\*(C'\fR. At present \s-1DBI\s0 supports \f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DOUBLE\*(C'\fR and \&\f(CW\*(C`SQL_NUMERIC\*(C'\fR. See \*(L"sql_type_cast\*(R" for details of how types are cast. .PP \&\fBOther attributes for Column Binding\fR .PP The \f(CW\*(C`\e%attr\*(C'\fR parameter may also contain the following attributes: .ie n .IP """StrictlyTyped""" 4 .el .IP "\f(CWStrictlyTyped\fR" 4 .IX Item "StrictlyTyped" If a \f(CW\*(C`TYPE\*(C'\fR attribute is passed to bind_col, then the driver will attempt to change the bound perl scalar to match the type more closely. If the bound value cannot be cast to the requested \f(CW\*(C`TYPE\*(C'\fR then by default it is left untouched and no error is generated. If you specify \f(CW\*(C`StrictlyTyped\*(C'\fR as 1 and the cast fails, this will generate an error. .Sp This attribute was first added in \s-1DBI 1.611.\s0 When 1.611 was released few drivers actually supported this attribute but DBD::Oracle and \&\s-1DBD::ODBC\s0 should from versions 1.24. .ie n .IP """DiscardString""" 4 .el .IP "\f(CWDiscardString\fR" 4 .IX Item "DiscardString" When the \f(CW\*(C`TYPE\*(C'\fR attribute is passed to \*(L"bind_col\*(R" and the driver successfully casts the bound perl scalar to a non-string type then if \f(CW\*(C`DiscardString\*(C'\fR is set to 1, the string portion of the scalar will be discarded. By default, \f(CW\*(C`DiscardString\*(C'\fR is not set. .Sp This attribute was first added in \s-1DBI 1.611.\s0 When 1.611 was released few drivers actually supported this attribute but DBD::Oracle and \&\s-1DBD::ODBC\s0 should from versions 1.24. .PP \fI\f(CI\*(C`bind_columns\*(C'\fI\fR .IX Subsection "bind_columns" .PP .Vb 1 \& $rc = $sth\->bind_columns(@list_of_refs_to_vars_to_bind); .Ve .PP Calls \*(L"bind_col\*(R" for each column of the \f(CW\*(C`SELECT\*(C'\fR statement. .PP The list of references should have the same number of elements as the number of columns in the \f(CW\*(C`SELECT\*(C'\fR statement. If it doesn't then \f(CW\*(C`bind_columns\*(C'\fR will bind the elements given, up to the number of columns, and then return an error. .PP For maximum portability between drivers, \fBbind_columns()\fR should be called after \fBexecute()\fR and not before. .PP For example: .PP .Vb 4 \& $dbh\->{RaiseError} = 1; # do this, or check every call for errors \& $sth = $dbh\->prepare(q{ SELECT region, sales FROM sales_by_region }); \& $sth\->execute; \& my ($region, $sales); \& \& # Bind Perl variables to columns: \& $rv = $sth\->bind_columns(\e$region, \e$sales); \& \& # you can also use Perl\*(Aqs \e(...) syntax (see perlref docs): \& # $sth\->bind_columns(\e($region, $sales)); \& \& # Column binding is the most efficient way to fetch data \& while ($sth\->fetch) { \& print "$region: $sales\en"; \& } .Ve .PP For compatibility with old scripts, the first parameter will be ignored if it is \f(CW\*(C`undef\*(C'\fR or a hash reference. .PP Here's a more fancy example that binds columns to the values \fIinside\fR a hash (thanks to H.Merijn Brand): .PP .Vb 6 \& $sth\->execute; \& my %row; \& $sth\->bind_columns( \e( @row{ @{$sth\->{NAME_lc} } } )); \& while ($sth\->fetch) { \& print "$row{region}: $row{sales}\en"; \& } .Ve .PP \fI\f(CI\*(C`dump_results\*(C'\fI\fR .IX Subsection "dump_results" .PP .Vb 1 \& $rows = $sth\->dump_results($maxlen, $lsep, $fsep, $fh); .Ve .PP Fetches all the rows from \f(CW$sth\fR, calls \f(CW\*(C`DBI::neat_list\*(C'\fR for each row, and prints the results to \f(CW$fh\fR (defaults to \f(CW\*(C`STDOUT\*(C'\fR) separated by \f(CW$lsep\fR (default \f(CW"\en"\fR). \f(CW$fsep\fR defaults to \f(CW", "\fR and \f(CW$maxlen\fR defaults to 35. .PP This method is designed as a handy utility for prototyping and testing queries. Since it uses \*(L"neat_list\*(R" to format and edit the string for reading by humans, it is not recommended for data transfer applications. .SS "Statement Handle Attributes" .IX Subsection "Statement Handle Attributes" This section describes attributes specific to statement handles. Most of these attributes are read-only. .PP Changes to these statement handle attributes do not affect any other existing or future statement handles. .PP Attempting to set or get the value of an unknown attribute generates a warning, except for private driver specific attributes (which all have names starting with a lowercase letter). .PP Example: .PP .Vb 1 \& ... = $h\->{NUM_OF_FIELDS}; # get/read .Ve .PP Some drivers cannot provide valid values for some or all of these attributes until after \f(CW\*(C`$sth\->execute\*(C'\fR has been successfully called. Typically the attribute will be \f(CW\*(C`undef\*(C'\fR in these situations. .PP Some attributes, like \s-1NAME,\s0 are not appropriate to some types of statement, like \s-1SELECT.\s0 Typically the attribute will be \f(CW\*(C`undef\*(C'\fR in these situations. .PP For drivers which support stored procedures and multiple result sets (see \*(L"more_results\*(R") these attributes relate to the \fIcurrent\fR result set. .PP See also \*(L"finish\*(R" to learn more about the effect it may have on some attributes. .PP \fI\f(CI\*(C`NUM_OF_FIELDS\*(C'\fI\fR .IX Subsection "NUM_OF_FIELDS" .PP Type: integer, read-only .PP Number of fields (columns) in the data the prepared statement may return. Statements that don't return rows of data, like \f(CW\*(C`DELETE\*(C'\fR and \f(CW\*(C`CREATE\*(C'\fR set \f(CW\*(C`NUM_OF_FIELDS\*(C'\fR to 0 (though it may be undef in some drivers). .PP \fI\f(CI\*(C`NUM_OF_PARAMS\*(C'\fI\fR .IX Subsection "NUM_OF_PARAMS" .PP Type: integer, read-only .PP The number of parameters (placeholders) in the prepared statement. See \s-1SUBSTITUTION VARIABLES\s0 below for more details. .PP \fI\f(CI\*(C`NAME\*(C'\fI\fR .IX Subsection "NAME" .PP Type: array-ref, read-only .PP Returns a reference to an array of field names for each column. The names may contain spaces but should not be truncated or have any trailing space. Note that the names have the letter case (upper, lower or mixed) as returned by the driver being used. Portable applications should use \*(L"NAME_lc\*(R" or \*(L"NAME_uc\*(R". .PP .Vb 1 \& print "First column name: $sth\->{NAME}\->[0]\en"; .Ve .PP Also note that the name returned for (aggregate) functions like \f(CWcount(*)\fR or \f(CW\*(C`max(c_foo)\*(C'\fR is determined by the database server and not by \f(CW\*(C`DBI\*(C'\fR or the \f(CW\*(C`DBD\*(C'\fR backend. .PP \fI\f(CI\*(C`NAME_lc\*(C'\fI\fR .IX Subsection "NAME_lc" .PP Type: array-ref, read-only .PP Like \f(CW\*(C`/NAME\*(C'\fR but always returns lowercase names. .PP \fI\f(CI\*(C`NAME_uc\*(C'\fI\fR .IX Subsection "NAME_uc" .PP Type: array-ref, read-only .PP Like \f(CW\*(C`/NAME\*(C'\fR but always returns uppercase names. .PP \fI\f(CI\*(C`NAME_hash\*(C'\fI\fR .IX Subsection "NAME_hash" .PP Type: hash-ref, read-only .PP \fI\f(CI\*(C`NAME_lc_hash\*(C'\fI\fR .IX Subsection "NAME_lc_hash" .PP Type: hash-ref, read-only .PP \fI\f(CI\*(C`NAME_uc_hash\*(C'\fI\fR .IX Subsection "NAME_uc_hash" .PP Type: hash-ref, read-only .PP The \f(CW\*(C`NAME_hash\*(C'\fR, \f(CW\*(C`NAME_lc_hash\*(C'\fR, and \f(CW\*(C`NAME_uc_hash\*(C'\fR attributes return column name information as a reference to a hash. .PP The keys of the hash are the names of the columns. The letter case of the keys corresponds to the letter case returned by the \f(CW\*(C`NAME\*(C'\fR, \&\f(CW\*(C`NAME_lc\*(C'\fR, and \f(CW\*(C`NAME_uc\*(C'\fR attributes respectively (as described above). .PP The value of each hash entry is the perl index number of the corresponding column (counting from 0). For example: .PP .Vb 4 \& $sth = $dbh\->prepare("select Id, Name from table"); \& $sth\->execute; \& @row = $sth\->fetchrow_array; \& print "Name $row[ $sth\->{NAME_lc_hash}{name} ]\en"; .Ve .PP \fI\f(CI\*(C`TYPE\*(C'\fI\fR .IX Subsection "TYPE" .PP Type: array-ref, read-only .PP Returns a reference to an array of integer values for each column. The value indicates the data type of the corresponding column. .PP The values correspond to the international standards (\s-1ANSI X3.135\s0 and \s-1ISO/IEC 9075\s0) which, in general terms, means \s-1ODBC.\s0 Driver-specific types that don't exactly match standard types should generally return the same values as an \s-1ODBC\s0 driver supplied by the makers of the database. That might include private type numbers in ranges the vendor has officially registered with the \s-1ISO\s0 working group: .PP .Vb 1 \& ftp://sqlstandards.org/SC32/SQL_Registry/ .Ve .PP Where there's no vendor-supplied \s-1ODBC\s0 driver to be compatible with, the \s-1DBI\s0 driver can use type numbers in the range that is now officially reserved for use by the \s-1DBI:\s0 \-9999 to \-9000. .PP All possible values for \f(CW\*(C`TYPE\*(C'\fR should have at least one entry in the output of the \f(CW\*(C`type_info_all\*(C'\fR method (see \*(L"type_info_all\*(R"). .PP \fI\f(CI\*(C`PRECISION\*(C'\fI\fR .IX Subsection "PRECISION" .PP Type: array-ref, read-only .PP Returns a reference to an array of integer values for each column. .PP For numeric columns, the value is the maximum number of digits (without considering a sign character or decimal point). Note that the \*(L"display size\*(R" for floating point types (\s-1REAL, FLOAT, DOUBLE\s0) can be up to 7 characters greater than the precision (for the sign + decimal point + the letter E + a sign + 2 or 3 digits). .PP For any character type column the value is the \s-1OCTET_LENGTH,\s0 in other words the number of bytes, not characters. .PP (More recent standards refer to this as \s-1COLUMN_SIZE\s0 but we stick with \s-1PRECISION\s0 for backwards compatibility.) .PP \fI\f(CI\*(C`SCALE\*(C'\fI\fR .IX Subsection "SCALE" .PP Type: array-ref, read-only .PP Returns a reference to an array of integer values for each column. \&\s-1NULL\s0 (\f(CW\*(C`undef\*(C'\fR) values indicate columns where scale is not applicable. .PP \fI\f(CI\*(C`NULLABLE\*(C'\fI\fR .IX Subsection "NULLABLE" .PP Type: array-ref, read-only .PP Returns a reference to an array indicating the possibility of each column returning a null. Possible values are \f(CW0\fR (or an empty string) = no, \f(CW1\fR = yes, \f(CW2\fR = unknown. .PP .Vb 1 \& print "First column may return NULL\en" if $sth\->{NULLABLE}\->[0]; .Ve .PP \fI\f(CI\*(C`CursorName\*(C'\fI\fR .IX Subsection "CursorName" .PP Type: string, read-only .PP Returns the name of the cursor associated with the statement handle, if available. If not available or if the database driver does not support the \&\f(CW"where current of ..."\fR \s-1SQL\s0 syntax, then it returns \f(CW\*(C`undef\*(C'\fR. .PP \fI\f(CI\*(C`Database\*(C'\fI\fR .IX Subsection "Database" .PP Type: dbh, read-only .PP Returns the parent \f(CW$dbh\fR of the statement handle. .PP \fI\f(CI\*(C`Statement\*(C'\fI\fR .IX Subsection "Statement" .PP Type: string, read-only .PP Returns the statement string passed to the \*(L"prepare\*(R" method. .PP \fI\f(CI\*(C`ParamValues\*(C'\fI\fR .IX Subsection "ParamValues" .PP Type: hash ref, read-only .PP Returns a reference to a hash containing the values currently bound to placeholders. The keys of the hash are the 'names' of the placeholders, typically integers starting at 1. Returns undef if not supported by the driver. .PP See \*(L"ShowErrorStatement\*(R" for an example of how this is used. .PP * Keys: .PP If the driver supports \f(CW\*(C`ParamValues\*(C'\fR but no values have been bound yet then the driver should return a hash with placeholders names in the keys but all the values undef, but some drivers may return a ref to an empty hash because they can't pre-determine the names. .PP It is possible that the keys in the hash returned by \f(CW\*(C`ParamValues\*(C'\fR are not exactly the same as those implied by the prepared statement. For example, DBD::Oracle translates '\f(CW\*(C`?\*(C'\fR' placeholders into '\f(CW\*(C`:pN\*(C'\fR' where N is a sequence number starting at 1. .PP * Values: .PP It is possible that the values in the hash returned by \f(CW\*(C`ParamValues\*(C'\fR are not \fIexactly\fR the same as those passed to \fBbind_param()\fR or \fBexecute()\fR. The driver may have slightly modified values in some way based on the \&\s-1TYPE\s0 the value was bound with. For example a floating point value bound as an \s-1SQL_INTEGER\s0 type may be returned as an integer. The values returned by \f(CW\*(C`ParamValues\*(C'\fR can be passed to another \&\fBbind_param()\fR method with the same \s-1TYPE\s0 and will be seen by the database as the same value. See also \*(L"ParamTypes\*(R" below. .PP The \f(CW\*(C`ParamValues\*(C'\fR attribute was added in \s-1DBI 1.28.\s0 .PP \fI\f(CI\*(C`ParamTypes\*(C'\fI\fR .IX Subsection "ParamTypes" .PP Type: hash ref, read-only .PP Returns a reference to a hash containing the type information currently bound to placeholders. Returns undef if not supported by the driver. .PP * Keys: .PP See \*(L"ParamValues\*(R" above. .PP * Values: .PP The hash values are hashrefs of type information in the same form as that passed to the various \fBbind_param()\fR methods (See \*(L"bind_param\*(R" for the format and values). .PP It is possible that the values in the hash returned by \f(CW\*(C`ParamTypes\*(C'\fR are not exactly the same as those passed to \fBbind_param()\fR or \fBexecute()\fR. Param attributes specified using the abbreviated form, like this: .PP .Vb 1 \& $sth\->bind_param(1, SQL_INTEGER); .Ve .PP are returned in the expanded form, as if called like this: .PP .Vb 1 \& $sth\->bind_param(1, { TYPE => SQL_INTEGER }); .Ve .PP The driver may have modified the type information in some way based on the bound values, other hints provided by the \fBprepare()\fR'd \&\s-1SQL\s0 statement, or alternate type mappings required by the driver or target database system. The driver may also add private keys (with names beginning with the drivers reserved prefix, e.g., odbc_xxx). .PP * Example: .PP The keys and values in the returned hash can be passed to the various \&\fBbind_param()\fR methods to effectively reproduce a previous param binding. For example: .PP .Vb 7 \& # assuming $sth1 is a previously prepared statement handle \& my $sth2 = $dbh\->prepare( $sth1\->{Statement} ); \& my $ParamValues = $sth1\->{ParamValues} || {}; \& my $ParamTypes = $sth1\->{ParamTypes} || {}; \& $sth2\->bind_param($_, $ParamValues\->{$_}, $ParamTypes\->{$_}) \& for keys %{ {%$ParamValues, %$ParamTypes} }; \& $sth2\->execute(); .Ve .PP The \f(CW\*(C`ParamTypes\*(C'\fR attribute was added in \s-1DBI 1.49.\s0 Implementation is the responsibility of individual drivers; the \s-1DBI\s0 layer default implementation simply returns undef. .PP \fI\f(CI\*(C`ParamArrays\*(C'\fI\fR .IX Subsection "ParamArrays" .PP Type: hash ref, read-only .PP Returns a reference to a hash containing the values currently bound to placeholders with \*(L"execute_array\*(R" or \*(L"bind_param_array\*(R". The keys of the hash are the 'names' of the placeholders, typically integers starting at 1. Returns undef if not supported by the driver or no arrays of parameters are bound. .PP Each key value is an array reference containing a list of the bound parameters for that column. .PP For example: .PP .Vb 8 \& $sth = $dbh\->prepare("INSERT INTO staff (id, name) values (?,?)"); \& $sth\->execute_array({},[1,2], [\*(Aqfred\*(Aq,\*(Aqdave\*(Aq]); \& if ($sth\->{ParamArrays}) { \& foreach $param (keys %{$sth\->{ParamArrays}}) { \& printf "Parameters for %s : %s\en", $param, \& join(",", @{$sth\->{ParamArrays}\->{$param}}); \& } \& } .Ve .PP It is possible that the values in the hash returned by \f(CW\*(C`ParamArrays\*(C'\fR are not \fIexactly\fR the same as those passed to \*(L"bind_param_array\*(R" or \&\*(L"execute_array\*(R". The driver may have slightly modified values in some way based on the \s-1TYPE\s0 the value was bound with. For example a floating point value bound as an \s-1SQL_INTEGER\s0 type may be returned as an integer. .PP It is also possible that the keys in the hash returned by \&\f(CW\*(C`ParamArrays\*(C'\fR are not exactly the same as those implied by the prepared statement. For example, DBD::Oracle translates '\f(CW\*(C`?\*(C'\fR' placeholders into '\f(CW\*(C`:pN\*(C'\fR' where N is a sequence number starting at 1. .PP \fI\f(CI\*(C`RowsInCache\*(C'\fI\fR .IX Subsection "RowsInCache" .PP Type: integer, read-only .PP If the driver supports a local row cache for \f(CW\*(C`SELECT\*(C'\fR statements, then this attribute holds the number of un-fetched rows in the cache. If the driver doesn't, then it returns \f(CW\*(C`undef\*(C'\fR. Note that some drivers pre-fetch rows on execute, whereas others wait till the first fetch. .PP See also the \*(L"RowCacheSize\*(R" database handle attribute. .SH "FURTHER INFORMATION" .IX Header "FURTHER INFORMATION" .SS "Catalog Methods" .IX Subsection "Catalog Methods" An application can retrieve metadata information from the \s-1DBMS\s0 by issuing appropriate queries on the views of the Information Schema. Unfortunately, \&\f(CW\*(C`INFORMATION_SCHEMA\*(C'\fR views are seldom supported by the \s-1DBMS.\s0 Special methods (catalog methods) are available to return result sets for a small but important portion of that metadata: .PP .Vb 5 \& column_info \& foreign_key_info \& primary_key_info \& table_info \& statistics_info .Ve .PP All catalog methods accept arguments in order to restrict the result sets. Passing \f(CW\*(C`undef\*(C'\fR to an optional argument does not constrain the search for that argument. However, an empty string ('') is treated as a regular search criteria and will only match an empty value. .PP \&\fBNote\fR: \s-1SQL/CLI\s0 and \s-1ODBC\s0 differ in the handling of empty strings. An empty string will not restrict the result set in \s-1SQL/CLI.\s0 .PP Most arguments in the catalog methods accept only \fIordinary values\fR, e.g. the arguments of \f(CW\*(C`primary_key_info()\*(C'\fR. Such arguments are treated as a literal string, i.e. the case is significant and quote characters are taken literally. .PP Some arguments in the catalog methods accept \fIsearch patterns\fR (strings containing '_' and/or '%'), e.g. the \f(CW$table\fR argument of \f(CW\*(C`column_info()\*(C'\fR. Passing '%' is equivalent to leaving the argument \f(CW\*(C`undef\*(C'\fR. .PP \&\fBCaveat\fR: The underscore ('_') is valid and often used in \s-1SQL\s0 identifiers. Passing such a value to a search pattern argument may return more rows than expected! To include pattern characters as literals, they must be preceded by an escape character which can be achieved with .PP .Vb 2 \& $esc = $dbh\->get_info( 14 ); # SQL_SEARCH_PATTERN_ESCAPE \& $search_pattern =~ s/([_%])/$esc$1/g; .Ve .PP The \s-1ODBC\s0 and \s-1SQL/CLI\s0 specifications define a way to change the default behaviour described above: All arguments (except \fIlist value arguments\fR) are treated as \fIidentifier\fR if the \f(CW\*(C`SQL_ATTR_METADATA_ID\*(C'\fR attribute is set to \f(CW\*(C`SQL_TRUE\*(C'\fR. \&\fIQuoted identifiers\fR are very similar to \fIordinary values\fR, i.e. their body (the string within the quotes) is interpreted literally. \&\fIUnquoted identifiers\fR are compared in \s-1UPPERCASE.\s0 .PP The \s-1DBI\s0 (currently) does not support the \f(CW\*(C`SQL_ATTR_METADATA_ID\*(C'\fR attribute, i.e. it behaves like an \s-1ODBC\s0 driver where \f(CW\*(C`SQL_ATTR_METADATA_ID\*(C'\fR is set to \&\f(CW\*(C`SQL_FALSE\*(C'\fR. .SS "Transactions" .IX Subsection "Transactions" Transactions are a fundamental part of any robust database system. They protect against errors and database corruption by ensuring that sets of related changes to the database take place in atomic (indivisible, all-or-nothing) units. .PP This section applies to databases that support transactions and where \&\f(CW\*(C`AutoCommit\*(C'\fR is off. See \*(L"AutoCommit\*(R" for details of using \f(CW\*(C`AutoCommit\*(C'\fR with various types of databases. .PP The recommended way to implement robust transactions in Perl applications is to enable \*(L"RaiseError\*(R" and catch the error that's 'thrown' as an exception. For example, using Try::Tiny: .PP .Vb 10 \& use Try::Tiny; \& $dbh\->{AutoCommit} = 0; # enable transactions, if possible \& $dbh\->{RaiseError} = 1; \& try { \& foo(...) # do lots of work here \& bar(...) # including inserts \& baz(...) # and updates \& $dbh\->commit; # commit the changes if we get this far \& } catch { \& warn "Transaction aborted because $_"; # Try::Tiny copies $@ into $_ \& # now rollback to undo the incomplete changes \& # but do it in an eval{} as it may also fail \& eval { $dbh\->rollback }; \& # add other application on\-error\-clean\-up code here \& }; .Ve .PP If the \f(CW\*(C`RaiseError\*(C'\fR attribute is not set, then \s-1DBI\s0 calls would need to be manually checked for errors, typically like this: .PP .Vb 1 \& $h\->method(@args) or die $h\->errstr; .Ve .PP With \f(CW\*(C`RaiseError\*(C'\fR set, the \s-1DBI\s0 will automatically \f(CW\*(C`die\*(C'\fR if any \s-1DBI\s0 method call on that handle (or a child handle) fails, so you don't have to test the return value of each method call. See \*(L"RaiseError\*(R" for more details. .PP A major advantage of the \f(CW\*(C`eval\*(C'\fR approach is that the transaction will be properly rolled back if \fIany\fR code (not just \s-1DBI\s0 calls) in the inner application dies for any reason. The major advantage of using the \&\f(CW\*(C`$h\->{RaiseError}\*(C'\fR attribute is that all \s-1DBI\s0 calls will be checked automatically. Both techniques are strongly recommended. .PP After calling \f(CW\*(C`commit\*(C'\fR or \f(CW\*(C`rollback\*(C'\fR many drivers will not let you fetch from a previously active \f(CW\*(C`SELECT\*(C'\fR statement handle that's a child of the same database handle. A typical way round this is to connect the the database twice and use one connection for \f(CW\*(C`SELECT\*(C'\fR statements. .PP See \*(L"AutoCommit\*(R" and \*(L"disconnect\*(R" for other important information about transactions. .SS "Handling \s-1BLOB / LONG /\s0 Memo Fields" .IX Subsection "Handling BLOB / LONG / Memo Fields" Many databases support \*(L"blob\*(R" (binary large objects), \*(L"long\*(R", or similar datatypes for holding very long strings or large amounts of binary data in a single field. Some databases support variable length long values over 2,000,000,000 bytes in length. .PP Since values of that size can't usually be held in memory, and because databases can't usually know in advance the length of the longest long that will be returned from a \f(CW\*(C`SELECT\*(C'\fR statement (unlike other data types), some special handling is required. .PP In this situation, the value of the \f(CW\*(C`$h\->{LongReadLen}\*(C'\fR attribute is used to determine how much buffer space to allocate when fetching such fields. The \f(CW\*(C`$h\->{LongTruncOk}\*(C'\fR attribute is used to determine how to behave if a fetched value can't fit into the buffer. .PP See the description of \*(L"LongReadLen\*(R" for more information. .PP When trying to insert long or binary values, placeholders should be used since there are often limits on the maximum size of an \f(CW\*(C`INSERT\*(C'\fR statement and the \*(L"quote\*(R" method generally can't cope with binary data. See \*(L"Placeholders and Bind Values\*(R". .SS "Simple Examples" .IX Subsection "Simple Examples" Here's a complete example program to select and fetch some data: .PP .Vb 3 \& my $data_source = "dbi::DriverName:db_name"; \& my $dbh = DBI\->connect($data_source, $user, $password) \& or die "Can\*(Aqt connect to $data_source: $DBI::errstr"; \& \& my $sth = $dbh\->prepare( q{ \& SELECT name, phone \& FROM mytelbook \& }) or die "Can\*(Aqt prepare statement: $DBI::errstr"; \& \& my $rc = $sth\->execute \& or die "Can\*(Aqt execute statement: $DBI::errstr"; \& \& print "Query will return $sth\->{NUM_OF_FIELDS} fields.\en\en"; \& print "Field names: @{ $sth\->{NAME} }\en"; \& \& while (($name, $phone) = $sth\->fetchrow_array) { \& print "$name: $phone\en"; \& } \& # check for problems which may have terminated the fetch early \& die $sth\->errstr if $sth\->err; \& \& $dbh\->disconnect; .Ve .PP Here's a complete example program to insert some data from a file. (This example uses \f(CW\*(C`RaiseError\*(C'\fR to avoid needing to check each call). .PP .Vb 3 \& my $dbh = DBI\->connect("dbi:DriverName:db_name", $user, $password, { \& RaiseError => 1, AutoCommit => 0 \& }); \& \& my $sth = $dbh\->prepare( q{ \& INSERT INTO table (name, phone) VALUES (?, ?) \& }); \& \& open FH, ") { \& chomp; \& my ($name, $phone) = split /,/; \& $sth\->execute($name, $phone); \& } \& close FH; \& \& $dbh\->commit; \& $dbh\->disconnect; .Ve .PP Here's how to convert fetched NULLs (undefined values) into empty strings: .PP .Vb 5 \& while($row = $sth\->fetchrow_arrayref) { \& # this is a fast and simple way to deal with nulls: \& foreach (@$row) { $_ = \*(Aq\*(Aq unless defined } \& print "@$row\en"; \& } .Ve .PP The \f(CW\*(C`q{...}\*(C'\fR style quoting used in these examples avoids clashing with quotes that may be used in the \s-1SQL\s0 statement. Use the double-quote like \&\f(CW\*(C`qq{...}\*(C'\fR operator if you want to interpolate variables into the string. See \*(L"Quote and Quote-like Operators\*(R" in perlop for more details. .SS "Threads and Thread Safety" .IX Subsection "Threads and Thread Safety" Perl 5.7 and later support a new threading model called iThreads. (The old \*(L"5.005 style\*(R" threads are not supported by the \s-1DBI.\s0) .PP In the iThreads model each thread has its own copy of the perl interpreter. When a new thread is created the original perl interpreter is 'cloned' to create a new copy for the new thread. .PP If the \s-1DBI\s0 and drivers are loaded and handles created before the thread is created then it will get a cloned copy of the \s-1DBI,\s0 the drivers and the handles. .PP However, the internal pointer data within the handles will refer to the \s-1DBI\s0 and drivers in the original interpreter. Using those handles in the new interpreter thread is not safe, so the \s-1DBI\s0 detects this and croaks on any method call using handles that don't belong to the current thread (except for \s-1DESTROY\s0). .PP Because of this (possibly temporary) restriction, newly created threads must make their own connections to the database. Handles can't be shared across threads. .PP But \s-1BEWARE,\s0 some underlying database APIs (the code the \s-1DBD\s0 driver uses to talk to the database, often supplied by the database vendor) are not thread safe. If it's not thread safe, then allowing more than one thread to enter the code at the same time may cause subtle/serious problems. In some cases allowing more than one thread to enter the code, even if \fInot\fR at the same time, can cause problems. You have been warned. .PP Using \s-1DBI\s0 with perl threads is not yet recommended for production environments. For more information see .PP Note: There is a bug in perl 5.8.2 when configured with threads and debugging enabled (bug #24463) which causes a \s-1DBI\s0 test to fail. .SS "Signal Handling and Canceling Operations" .IX Subsection "Signal Handling and Canceling Operations" [The following only applies to systems with unix-like signal handling. I'd welcome additions for other systems, especially Windows.] .PP The first thing to say is that signal handling in Perl versions less than 5.8 is \fInot\fR safe. There is always a small risk of Perl crashing and/or core dumping when, or after, handling a signal because the signal could arrive and be handled while internal data structures are being changed. If the signal handling code used those same internal data structures it could cause all manner of subtle and not-so-subtle problems. The risk was reduced with 5.4.4 but was still present in all perls up through 5.8.0. .PP Beginning in perl 5.8.0 perl implements 'safe' signal handling if your system has the \s-1POSIX\s0 \fBsigaction()\fR routine. Now when a signal is delivered perl just makes a note of it but does \fInot\fR run the \&\f(CW%SIG\fR handler. The handling is 'deferred' until a 'safe' moment. .PP Although this change made signal handling safe, it also lead to a problem with signals being deferred for longer than you'd like. If a signal arrived while executing a system call, such as waiting for data on a network connection, the signal is noted and then the system call that was executing returns with an \s-1EINTR\s0 error code to indicate that it was interrupted. All fine so far. .PP The problem comes when the code that made the system call sees the \&\s-1EINTR\s0 code and decides it's going to call it again. Perl doesn't do that, but database code sometimes does. If that happens then the signal handler doesn't get called until later. Maybe much later. .PP Fortunately there are ways around this which we'll discuss below. Unfortunately they make signals unsafe again. .PP The two most common uses of signals in relation to the \s-1DBI\s0 are for canceling operations when the user types Ctrl-C (interrupt), and for implementing a timeout using \f(CW\*(C`alarm()\*(C'\fR and \f(CW$SIG{ALRM}\fR. .IP "Cancel" 4 .IX Item "Cancel" The \s-1DBI\s0 provides a \f(CW\*(C`cancel\*(C'\fR method for statement handles. The \&\f(CW\*(C`cancel\*(C'\fR method should abort the current operation and is designed to be called from a signal handler. For example: .Sp .Vb 1 \& $SIG{INT} = sub { $sth\->cancel }; .Ve .Sp However, few drivers implement this (the \s-1DBI\s0 provides a default method that just returns \f(CW\*(C`undef\*(C'\fR) and, even if implemented, there is still a possibility that the statement handle, and even the parent database handle, will not be usable afterwards. .Sp If \f(CW\*(C`cancel\*(C'\fR returns true, then it has successfully invoked the database engine's own cancel function. If it returns false, then \f(CW\*(C`cancel\*(C'\fR failed. If it returns \f(CW\*(C`undef\*(C'\fR, then the database driver does not have cancel implemented \- very few do. .IP "Timeout" 4 .IX Item "Timeout" The traditional way to implement a timeout is to set \f(CW$SIG{ALRM}\fR to refer to some code that will be executed when an \s-1ALRM\s0 signal arrives and then to call alarm($seconds) to schedule an \s-1ALRM\s0 signal to be delivered \f(CW$seconds\fR in the future. For example: .Sp .Vb 10 \& my $failed; \& eval { \& local $SIG{ALRM} = sub { die "TIMEOUT\en" }; # N.B. \en required \& eval { \& alarm($seconds); \& ... code to execute with timeout here (which may die) ... \& 1; \& } or $failed = 1; \& # outer eval catches alarm that might fire JUST before this alarm(0) \& alarm(0); # cancel alarm (if code ran fast) \& die "$@" if $failed; \& 1; \& } or $failed = 1; \& if ( $failed ) { \& if ( defined $@ and $@ eq "TIMEOUT\en" ) { ... } \& else { ... } # some other error \& } .Ve .Sp The first (outer) eval is used to avoid the unlikely but possible chance that the \*(L"code to execute\*(R" dies and the alarm fires before it is cancelled. Without the outer eval, if this happened your program will die if you have no \s-1ALRM\s0 handler or a non-local alarm handler will be called. .Sp Unfortunately, as described above, this won't always work as expected, depending on your perl version and the underlying database code. .Sp With Oracle for instance (DBD::Oracle), if the system which hosts the database is down the \s-1DBI\-\s0>\fBconnect()\fR call will hang for several minutes before returning an error. .PP The solution on these systems is to use the \f(CW\*(C`POSIX::sigaction()\*(C'\fR routine to gain low level access to how the signal handler is installed. .PP The code would look something like this (for the DBD-Oracle \fBconnect()\fR): .PP .Vb 1 \& use POSIX qw(:signal_h); \& \& my $mask = POSIX::SigSet\->new( SIGALRM ); # signals to mask in the handler \& my $action = POSIX::SigAction\->new( \& sub { die "connect timeout\en" }, # the handler code ref \& $mask, \& # not using (perl 5.8.2 and later) \*(Aqsafe\*(Aq switch or sa_flags \& ); \& my $oldaction = POSIX::SigAction\->new(); \& sigaction( SIGALRM, $action, $oldaction ); \& my $dbh; \& my $failed; \& eval { \& eval { \& alarm(5); # seconds before time out \& $dbh = DBI\->connect("dbi:Oracle:$dsn" ... ); \& 1; \& } or $failed = 1; \& alarm(0); # cancel alarm (if connect worked fast) \& die "$@\en" if $failed; # connect died \& 1; \& } or $failed = 1; \& sigaction( SIGALRM, $oldaction ); # restore original signal handler \& if ( $failed ) { \& if ( defined $@ and $@ eq "connect timeout\en" ) {...} \& else { # connect died } \& } .Ve .PP See previous example for the reasoning around the double eval. .PP Similar techniques can be used for canceling statement execution. .PP Unfortunately, this solution is somewhat messy, and it does \fInot\fR work with perl versions less than perl 5.8 where \f(CW\*(C`POSIX::sigaction()\*(C'\fR appears to be broken. .PP For a cleaner implementation that works across perl versions, see Lincoln Baxter's Sys::SigAction module at Sys::SigAction. The documentation for Sys::SigAction includes an longer discussion of this problem, and a DBD::Oracle test script. .PP Be sure to read all the signal handling sections of the perlipc manual. .PP And finally, two more points to keep firmly in mind. Firstly, remember that what we've done here is essentially revert to old style \fIunsafe\fR handling of these signals. So do as little as possible in the handler. Ideally just \fBdie()\fR. Secondly, the handles in use at the time the signal is handled may not be safe to use afterwards. .SS "Subclassing the \s-1DBI\s0" .IX Subsection "Subclassing the DBI" \&\s-1DBI\s0 can be subclassed and extended just like any other object oriented module. Before we talk about how to do that, it's important to be clear about the various \s-1DBI\s0 classes and how they work together. .PP By default \f(CW\*(C`$dbh = DBI\->connect(...)\*(C'\fR returns a \f(CW$dbh\fR blessed into the \f(CW\*(C`DBI::db\*(C'\fR class. And the \f(CW\*(C`$dbh\->prepare\*(C'\fR method returns an \f(CW$sth\fR blessed into the \f(CW\*(C`DBI::st\*(C'\fR class (actually it simply changes the last four characters of the calling handle class to be \f(CW\*(C`::st\*(C'\fR). .PP The leading '\f(CW\*(C`DBI\*(C'\fR' is known as the 'root class' and the extra \&'\f(CW\*(C`::db\*(C'\fR' or '\f(CW\*(C`::st\*(C'\fR' are the 'handle type suffixes'. If you want to subclass the \s-1DBI\s0 you'll need to put your overriding methods into the appropriate classes. For example, if you want to use a root class of \f(CW\*(C`MySubDBI\*(C'\fR and override the \fBdo()\fR, \fBprepare()\fR and \fBexecute()\fR methods, then your \fBdo()\fR and \fBprepare()\fR methods should be in the \f(CW\*(C`MySubDBI::db\*(C'\fR class and the \fBexecute()\fR method should be in the \f(CW\*(C`MySubDBI::st\*(C'\fR class. .PP To setup the inheritance hierarchy the \f(CW@ISA\fR variable in \f(CW\*(C`MySubDBI::db\*(C'\fR should include \f(CW\*(C`DBI::db\*(C'\fR and the \f(CW@ISA\fR variable in \f(CW\*(C`MySubDBI::st\*(C'\fR should include \f(CW\*(C`DBI::st\*(C'\fR. The \f(CW\*(C`MySubDBI\*(C'\fR root class itself isn't currently used for anything visible and so, apart from setting \f(CW@ISA\fR to include \f(CW\*(C`DBI\*(C'\fR, it can be left empty. .PP So, having put your overriding methods into the right classes, and setup the inheritance hierarchy, how do you get the \s-1DBI\s0 to use them? You have two choices, either a static method call using the name of your subclass: .PP .Vb 1 \& $dbh = MySubDBI\->connect(...); .Ve .PP or specifying a \f(CW\*(C`RootClass\*(C'\fR attribute: .PP .Vb 1 \& $dbh = DBI\->connect(..., { RootClass => \*(AqMySubDBI\*(Aq }); .Ve .PP If both forms are used then the attribute takes precedence. .PP The only differences between the two are that using an explicit RootClass attribute will a) make the \s-1DBI\s0 automatically attempt to load a module by that name if the class doesn't exist, and b) won't call your \fBMySubDBI::connect()\fR method, if you have one. .PP When subclassing is being used then, after a successful new connect, the \s-1DBI\-\s0>connect method automatically calls: .PP .Vb 1 \& $dbh\->connected($dsn, $user, $pass, \e%attr); .Ve .PP The default method does nothing. The call is made just to simplify any post-connection setup that your subclass may want to perform. The parameters are the same as passed to \s-1DBI\-\s0>connect. If your subclass supplies a connected method, it should be part of the MySubDBI::db package. .PP One more thing to note: you must let the \s-1DBI\s0 do the handle creation. If you want to override the \fBconnect()\fR method in your *::dr class then it must still call SUPER::connect to get a \f(CW$dbh\fR to work with. Similarly, an overridden \&\fBprepare()\fR method in *::db must still call SUPER::prepare to get a \f(CW$sth\fR. If you try to create your own handles using \fBbless()\fR then you'll find the \s-1DBI\s0 will reject them with an \*(L"is not a \s-1DBI\s0 handle (has no magic)\*(R" error. .PP Here's a brief example of a \s-1DBI\s0 subclass. A more thorough example can be found in \fIt/subclass.t\fR in the \s-1DBI\s0 distribution. .PP .Vb 1 \& package MySubDBI; \& \& use strict; \& \& use DBI; \& use vars qw(@ISA); \& @ISA = qw(DBI); \& \& package MySubDBI::db; \& use vars qw(@ISA); \& @ISA = qw(DBI::db); \& \& sub prepare { \& my ($dbh, @args) = @_; \& my $sth = $dbh\->SUPER::prepare(@args) \& or return; \& $sth\->{private_mysubdbi_info} = { foo => \*(Aqbar\*(Aq }; \& return $sth; \& } \& \& package MySubDBI::st; \& use vars qw(@ISA); \& @ISA = qw(DBI::st); \& \& sub fetch { \& my ($sth, @args) = @_; \& my $row = $sth\->SUPER::fetch(@args) \& or return; \& do_something_magical_with_row_data($row) \& or return $sth\->set_err(1234, "The magic failed", undef, "fetch"); \& return $row; \& } .Ve .PP When calling a SUPER::method that returns a handle, be careful to check the return value before trying to do other things with it in your overridden method. This is especially important if you want to set a hash attribute on the handle, as Perl's autovivification will bite you by (in)conveniently creating an unblessed hashref, which your method will then return with usually baffling results later on like the error \*(L"dbih_getcom handle \s-1HASH\s0(0xa4451a8) is not a \s-1DBI\s0 handle (has no magic\*(R". It's best to check right after the call and return undef immediately on error, just like \s-1DBI\s0 would and just like the example above. .PP If your method needs to record an error it should call the \fBset_err()\fR method with the error code and error string, as shown in the example above. The error code and error string will be recorded in the handle and available via \f(CW\*(C`$h\->err\*(C'\fR and \f(CW$DBI::errstr\fR etc. The \fBset_err()\fR method always returns an undef or empty list as appropriate. Since your method should nearly always return an undef or empty list as soon as an error is detected it's handy to simply return what \fBset_err()\fR returns, as shown in the example above. .PP If the handle has \f(CW\*(C`RaiseError\*(C'\fR, \f(CW\*(C`PrintError\*(C'\fR, or \f(CW\*(C`HandleError\*(C'\fR etc. set then the \fBset_err()\fR method will honour them. This means that if \f(CW\*(C`RaiseError\*(C'\fR is set then \fBset_err()\fR won't return in the normal way but will 'throw an exception' that can be caught with an \f(CW\*(C`eval\*(C'\fR block. .PP You can stash private data into \s-1DBI\s0 handles via \f(CW\*(C`$h\->{private_..._*}\*(C'\fR. See the entry under \*(L"\s-1ATTRIBUTES COMMON TO ALL HANDLES\*(R"\s0 for info and important caveats. .SS "Memory Leaks" .IX Subsection "Memory Leaks" When tracking down memory leaks using tools like Devel::Leak you'll find that some \s-1DBI\s0 internals are reported as 'leaking' memory. This is very unlikely to be a real leak. The \s-1DBI\s0 has various caches to improve performance and the apparrent leaks are simply the normal operation of these caches. .PP The most frequent sources of the apparrent leaks are \*(L"ChildHandles\*(R", \&\*(L"prepare_cached\*(R" and \*(L"connect_cached\*(R". .PP For example http://stackoverflow.com/questions/13338308/perl\-dbi\-memory\-leak .PP Given how widely the \s-1DBI\s0 is used, you can rest assured that if a new release of the \s-1DBI\s0 did have a real leak it would be discovered, reported, and fixed immediately. The leak you're looking for is probably elsewhere. Good luck! .SH "TRACING" .IX Header "TRACING" The \s-1DBI\s0 has a powerful tracing mechanism built in. It enables you to see what's going on 'behind the scenes', both within the \s-1DBI\s0 and the drivers you're using. .SS "Trace Settings" .IX Subsection "Trace Settings" Which details are written to the trace output is controlled by a combination of a \fItrace level\fR, an integer from 0 to 15, and a set of \fItrace flags\fR that are either on or off. Together these are known as the \fItrace settings\fR and are stored together in a single integer. For normal use you only need to set the trace level, and generally only to a value between 1 and 4. .PP Each handle has its own trace settings, and so does the \s-1DBI.\s0 When you call a method the \s-1DBI\s0 merges the handles settings into its own for the duration of the call: the trace flags of the handle are \&\s-1OR\s0'd into the trace flags of the \s-1DBI,\s0 and if the handle has a higher trace level then the \s-1DBI\s0 trace level is raised to match it. The previous \s-1DBI\s0 trace settings are restored when the called method returns. .SS "Trace Levels" .IX Subsection "Trace Levels" Trace \fIlevels\fR are as follows: .PP .Vb 8 \& 0 \- Trace disabled. \& 1 \- Trace top\-level DBI method calls returning with results or errors. \& 2 \- As above, adding tracing of top\-level method entry with parameters. \& 3 \- As above, adding some high\-level information from the driver \& and some internal information from the DBI. \& 4 \- As above, adding more detailed information from the driver. \& This is the first level to trace all the rows being fetched. \& 5 to 15 \- As above but with more and more internal information. .Ve .PP Trace level 1 is best for a simple overview of what's happening. Trace levels 2 thru 4 a good choice for general purpose tracing. Levels 5 and above are best reserved for investigating a specific problem, when you need to see \*(L"inside\*(R" the driver and \s-1DBI.\s0 .PP The trace output is detailed and typically very useful. Much of the trace output is formatted using the \*(L"neat\*(R" function, so strings in the trace output may be edited and truncated by that function. .SS "Trace Flags" .IX Subsection "Trace Flags" Trace \fIflags\fR are used to enable tracing of specific activities within the \s-1DBI\s0 and drivers. The \s-1DBI\s0 defines some trace flags and drivers can define others. \s-1DBI\s0 trace flag names begin with a capital letter and driver specific names begin with a lowercase letter, as usual. .PP Currently the \s-1DBI\s0 defines these trace flags: .PP .Vb 10 \& ALL \- turn on all DBI and driver flags (not recommended) \& SQL \- trace SQL statements executed \& (not yet implemented in DBI but implemented in some DBDs) \& CON \- trace connection process \& ENC \- trace encoding (unicode translations etc) \& (not yet implemented in DBI but implemented in some DBDs) \& DBD \- trace only DBD messages \& (not implemented by all DBDs yet) \& TXN \- trace transactions \& (not implemented in all DBDs yet) .Ve .PP The \*(L"parse_trace_flags\*(R" and \*(L"parse_trace_flag\*(R" methods are used to convert trace flag names into the corresponding integer bit flags. .SS "Enabling Trace" .IX Subsection "Enabling Trace" The \f(CW\*(C`$h\->trace\*(C'\fR method sets the trace settings for a handle and \f(CW\*(C`DBI\->trace\*(C'\fR does the same for the \s-1DBI.\s0 .PP In addition to the \*(L"trace\*(R" method, you can enable the same trace information, and direct the output to a file, by setting the \&\f(CW\*(C`DBI_TRACE\*(C'\fR environment variable before starting Perl. See \*(L"\s-1DBI_TRACE\*(R"\s0 for more information. .PP Finally, you can set, or get, the trace settings for a handle using the \f(CW\*(C`TraceLevel\*(C'\fR attribute. .PP All of those methods use \fBparse_trace_flags()\fR and so allow you set both the trace level and multiple trace flags by using a string containing the trace level and/or flag names separated by vertical bar ("\f(CW\*(C`|\*(C'\fR\*(L") or comma (\*(R"\f(CW\*(C`,\*(C'\fR") characters. For example: .PP .Vb 1 \& local $h\->{TraceLevel} = "3|SQL|foo"; .Ve .SS "Trace Output" .IX Subsection "Trace Output" Initially trace output is written to \f(CW\*(C`STDERR\*(C'\fR. Both the \&\f(CW\*(C`$h\->trace\*(C'\fR and \f(CW\*(C`DBI\->trace\*(C'\fR methods take an optional \&\f(CW$trace_file\fR parameter, which may be either the name of a file to be opened by \s-1DBI\s0 in append mode, or a reference to an existing writable (possibly layered) filehandle. If \f(CW$trace_file\fR is a filename, and can be opened in append mode, or \f(CW$trace_file\fR is a writable filehandle, then \fIall\fR trace output (currently including that from other handles) is redirected to that file. A warning is generated if \f(CW$trace_file\fR can't be opened or is not writable. .PP Further calls to \fBtrace()\fR without \f(CW$trace_file\fR do not alter where the trace output is sent. If \f(CW$trace_file\fR is undefined, then trace output is sent to \f(CW\*(C`STDERR\*(C'\fR and, if the prior trace was opened with \&\f(CW$trace_file\fR as a filename, the previous trace file is closed; if \f(CW$trace_file\fR was a filehandle, the filehandle is \fBnot\fR closed. .PP \&\fB\s-1NOTE\s0\fR: If \f(CW$trace_file\fR is specified as a filehandle, the filehandle should not be closed until all \s-1DBI\s0 operations are completed, or the application has reset the trace file via another call to \&\f(CW\*(C`trace()\*(C'\fR that changes the trace file. .SS "Tracing to Layered Filehandles" .IX Subsection "Tracing to Layered Filehandles" \&\fB\s-1NOTE\s0\fR: .IP "\(bu" 4 Tied filehandles are not currently supported, as tie operations are not available to the PerlIO methods used by the \s-1DBI.\s0 .IP "\(bu" 4 PerlIO layer support requires Perl version 5.8 or higher. .PP As of version 5.8, Perl provides the ability to layer various \&\*(L"disciplines\*(R" on an open filehandle via the PerlIO module. .PP A simple example of using PerlIO layers is to use a scalar as the output: .PP .Vb 3 \& my $scalar = \*(Aq\*(Aq; \& open( my $fh, "+>:scalar", \e$scalar ); \& $dbh\->trace( 2, $fh ); .Ve .PP Now all trace output is simply appended to \f(CW$scalar\fR. .PP A more complex application of tracing to a layered filehandle is the use of a custom layer (\fIRefer to \fRPerlio::via \fIfor details on creating custom PerlIO layers.\fR). Consider an application with the following logger module: .PP .Vb 1 \& package MyFancyLogger; \& \& sub new \& { \& my $self = {}; \& my $fh; \& open $fh, \*(Aq>\*(Aq, \*(Aqfancylog.log\*(Aq; \& $self\->{_fh} = $fh; \& $self\->{_buf} = \*(Aq\*(Aq; \& return bless $self, shift; \& } \& \& sub log \& { \& my $self = shift; \& return unless exists $self\->{_fh}; \& my $fh = $self\->{_fh}; \& $self\->{_buf} .= shift; \& # \& # DBI feeds us pieces at a time, so accumulate a complete line \& # before outputing \& # \& print $fh "At ", scalar localtime(), \*(Aq:\*(Aq, $self\->{_buf}, "\en" and \& $self\->{_buf} = \*(Aq\*(Aq \& if $self\->{_buf}=~tr/\en//; \& } \& \& sub close { \& my $self = shift; \& return unless exists $self\->{_fh}; \& my $fh = $self\->{_fh}; \& print $fh "At ", scalar localtime(), \*(Aq:\*(Aq, $self\->{_buf}, "\en" and \& $self\->{_buf} = \*(Aq\*(Aq \& if $self\->{_buf}; \& close $fh; \& delete $self\->{_fh}; \& } \& \& 1; .Ve .PP To redirect \s-1DBI\s0 traces to this logger requires creating a package for the layer: .PP .Vb 1 \& package PerlIO::via::MyFancyLogLayer; \& \& sub PUSHED \& { \& my ($class,$mode,$fh) = @_; \& my $logger; \& return bless \e$logger,$class; \& } \& \& sub OPEN { \& my ($self, $path, $mode, $fh) = @_; \& # \& # $path is actually our logger object \& # \& $$self = $path; \& return 1; \& } \& \& sub WRITE \& { \& my ($self, $buf, $fh) = @_; \& $$self\->log($buf); \& return length($buf); \& } \& \& sub CLOSE { \& my $self = shift; \& $$self\->close(); \& return 0; \& } \& \& 1; .Ve .PP The application can then cause \s-1DBI\s0 traces to be routed to the logger using .PP .Vb 1 \& use PerlIO::via::MyFancyLogLayer; \& \& open my $fh, \*(Aq>:via(MyFancyLogLayer)\*(Aq, MyFancyLogger\->new(); \& \& $dbh\->trace(\*(AqSQL\*(Aq, $fh); .Ve .PP Now all trace output will be processed by MyFancyLogger's \&\fBlog()\fR method. .SS "Trace Content" .IX Subsection "Trace Content" Many of the values embedded in trace output are formatted using the \fBneat()\fR utility function. This means they may be quoted, sanitized, and possibly truncated if longer than \f(CW$DBI::neat_maxlen\fR. See \*(L"neat\*(R" for more details. .SS "Tracing Tips" .IX Subsection "Tracing Tips" You can add tracing to your own application code using the \*(L"trace_msg\*(R" method. .PP It can sometimes be handy to compare trace files from two different runs of the same script. However using a tool like \f(CW\*(C`diff\*(C'\fR on the original log output doesn't work well because the trace file is full of object addresses that may differ on each run. .PP The \s-1DBI\s0 includes a handy utility called dbilogstrip that can be used to \&'normalize' the log content. It can be used as a filter like this: .PP .Vb 3 \& DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log \& DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log \& diff \-u dbitrace1.log dbitrace2.log .Ve .PP See dbilogstrip for more information. .SH "DBI ENVIRONMENT VARIABLES" .IX Header "DBI ENVIRONMENT VARIABLES" The \s-1DBI\s0 module recognizes a number of environment variables, but most of them should not be used most of the time. It is better to be explicit about what you are doing to avoid the need for environment variables, especially in a web serving system where web servers are stingy about which environment variables are available. .SS "\s-1DBI_DSN\s0" .IX Subsection "DBI_DSN" The \s-1DBI_DSN\s0 environment variable is used by \s-1DBI\-\s0>connect if you do not specify a data source when you issue the connect. It should have a format such as \*(L"dbi:Driver:databasename\*(R". .SS "\s-1DBI_DRIVER\s0" .IX Subsection "DBI_DRIVER" The \s-1DBI_DRIVER\s0 environment variable is used to fill in the database driver name in \s-1DBI\-\s0>connect if the data source string starts \*(L"dbi::\*(R" (thereby omitting the driver). If \s-1DBI_DSN\s0 omits the driver name, \s-1DBI_DRIVER\s0 can fill the gap. .SS "\s-1DBI_AUTOPROXY\s0" .IX Subsection "DBI_AUTOPROXY" The \s-1DBI_AUTOPROXY\s0 environment variable takes a string value that starts \&\*(L"dbi:Proxy:\*(R" and is typically followed by \*(L"hostname=...;port=...\*(R". It is used to alter the behaviour of \s-1DBI\-\s0>connect. For full details, see DBI::Proxy documentation. .SS "\s-1DBI_USER\s0" .IX Subsection "DBI_USER" The \s-1DBI_USER\s0 environment variable takes a string value that is used as the user name if the \s-1DBI\-\s0>connect call is given undef (as distinct from an empty string) as the username argument. Be wary of the security implications of using this. .SS "\s-1DBI_PASS\s0" .IX Subsection "DBI_PASS" The \s-1DBI_PASS\s0 environment variable takes a string value that is used as the password if the \s-1DBI\-\s0>connect call is given undef (as distinct from an empty string) as the password argument. Be extra wary of the security implications of using this. .SS "\s-1DBI_DBNAME\s0 (obsolete)" .IX Subsection "DBI_DBNAME (obsolete)" The \s-1DBI_DBNAME\s0 environment variable takes a string value that is used only when the obsolescent style of \s-1DBI\-\s0>connect (with driver name as fourth parameter) is used, and when no value is provided for the first (database name) argument. .SS "\s-1DBI_TRACE\s0" .IX Subsection "DBI_TRACE" The \s-1DBI_TRACE\s0 environment variable specifies the global default trace settings for the \s-1DBI\s0 at startup. Can also be used to direct trace output to a file. When the \s-1DBI\s0 is loaded it does: .PP .Vb 1 \& DBI\->trace(split /=/, $ENV{DBI_TRACE}, 2) if $ENV{DBI_TRACE}; .Ve .PP So if \f(CW\*(C`DBI_TRACE\*(C'\fR contains an "\f(CW\*(C`=\*(C'\fR" character then what follows it is used as the name of the file to append the trace to. .PP output appended to that file. If the name begins with a number followed by an equal sign (\f(CW\*(C`=\*(C'\fR), then the number and the equal sign are stripped off from the name, and the number is used to set the trace level. For example: .PP .Vb 1 \& DBI_TRACE=1=dbitrace.log perl your_test_script.pl .Ve .PP On Unix-like systems using a Bourne-like shell, you can do this easily on the command line: .PP .Vb 1 \& DBI_TRACE=2 perl your_test_script.pl .Ve .PP See \*(L"\s-1TRACING\*(R"\s0 for more information. .SS "\s-1PERL_DBI_DEBUG\s0 (obsolete)" .IX Subsection "PERL_DBI_DEBUG (obsolete)" An old variable that should no longer be used; equivalent to \s-1DBI_TRACE.\s0 .SS "\s-1DBI_PROFILE\s0" .IX Subsection "DBI_PROFILE" The \s-1DBI_PROFILE\s0 environment variable can be used to enable profiling of \s-1DBI\s0 method calls. See DBI::Profile for more information. .SS "\s-1DBI_PUREPERL\s0" .IX Subsection "DBI_PUREPERL" The \s-1DBI_PUREPERL\s0 environment variable can be used to enable the use of DBI::PurePerl. See DBI::PurePerl for more information. .SH "WARNING AND ERROR MESSAGES" .IX Header "WARNING AND ERROR MESSAGES" .SS "Fatal Errors" .IX Subsection "Fatal Errors" .ie n .IP "Can't call method ""prepare"" without a package or object reference" 4 .el .IP "Can't call method ``prepare'' without a package or object reference" 4 .IX Item "Can't call method prepare without a package or object reference" The \f(CW$dbh\fR handle you're using to call \f(CW\*(C`prepare\*(C'\fR is probably undefined because the preceding \f(CW\*(C`connect\*(C'\fR failed. You should always check the return status of \&\s-1DBI\s0 methods, or use the \*(L"RaiseError\*(R" attribute. .ie n .IP "Can't call method ""execute"" without a package or object reference" 4 .el .IP "Can't call method ``execute'' without a package or object reference" 4 .IX Item "Can't call method execute without a package or object reference" The \f(CW$sth\fR handle you're using to call \f(CW\*(C`execute\*(C'\fR is probably undefined because the preceding \f(CW\*(C`prepare\*(C'\fR failed. You should always check the return status of \&\s-1DBI\s0 methods, or use the \*(L"RaiseError\*(R" attribute. .IP "\s-1DBI/DBD\s0 internal version mismatch" 4 .IX Item "DBI/DBD internal version mismatch" The \s-1DBD\s0 driver module was built with a different version of \s-1DBI\s0 than the one currently being used. You should rebuild the \s-1DBD\s0 module under the current version of \s-1DBI.\s0 .Sp (Some rare platforms require \*(L"static linking\*(R". On those platforms, there may be an old \s-1DBI\s0 or \s-1DBD\s0 driver version actually embedded in the Perl executable being used.) .IP "\s-1DBD\s0 driver has not implemented the AutoCommit attribute" 4 .IX Item "DBD driver has not implemented the AutoCommit attribute" The \s-1DBD\s0 driver implementation is incomplete. Consult the author. .ie n .IP "Can't [sg]et %s\->{%s}: unrecognised attribute" 4 .el .IP "Can't [sg]et \f(CW%s\fR\->{%s}: unrecognised attribute" 4 .IX Item "Can't [sg]et %s->{%s}: unrecognised attribute" You attempted to set or get an unknown attribute of a handle. Make sure you have spelled the attribute name correctly; case is significant (e.g., \*(L"Autocommit\*(R" is not the same as \*(L"AutoCommit\*(R"). .SH "Pure-Perl DBI" .IX Header "Pure-Perl DBI" A pure-perl emulation of the \s-1DBI\s0 is included in the distribution for people using pure-perl drivers who, for whatever reason, can't install the compiled \s-1DBI.\s0 See DBI::PurePerl. .SH "SEE ALSO" .IX Header "SEE ALSO" .SS "Driver and Database Documentation" .IX Subsection "Driver and Database Documentation" Refer to the documentation for the \s-1DBD\s0 driver that you are using. .PP Refer to the \s-1SQL\s0 Language Reference Manual for the database engine that you are using. .SS "\s-1ODBC\s0 and \s-1SQL/CLI\s0 Standards Reference Information" .IX Subsection "ODBC and SQL/CLI Standards Reference Information" More detailed information about the semantics of certain \s-1DBI\s0 methods that are based on \s-1ODBC\s0 and \s-1SQL/CLI\s0 standards is available on-line via microsoft.com, for \s-1ODBC,\s0 and www.jtc1sc32.org for the \s-1SQL/CLI\s0 standard: .PP .Vb 9 \& DBI method ODBC function SQL/CLI Working Draft \& \-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& column_info SQLColumns Page 124 \& foreign_key_info SQLForeignKeys Page 163 \& get_info SQLGetInfo Page 214 \& primary_key_info SQLPrimaryKeys Page 254 \& table_info SQLTables Page 294 \& type_info SQLGetTypeInfo Page 239 \& statistics_info SQLStatistics .Ve .PP To find documentation on the \s-1ODBC\s0 function you can use the \s-1MSDN\s0 search facility at: .PP .Vb 1 \& http://msdn.microsoft.com/Search .Ve .PP and search for something like \f(CW"SQLColumns returns"\fR. .PP And for \s-1SQL/CLI\s0 standard information on SQLColumns you'd read page 124 of the (very large) \s-1SQL/CLI\s0 Working Draft available from: .PP .Vb 1 \& http://jtc1sc32.org/doc/N0701\-0750/32N0744T.pdf .Ve .SS "Standards Reference Information" .IX Subsection "Standards Reference Information" A hyperlinked, browsable version of the \s-1BNF\s0 syntax for \s-1SQL92\s0 (plus Oracle 7 \s-1SQL\s0 and \s-1PL/SQL\s0) is available here: .PP .Vb 1 \& http://cui.unige.ch/db\-research/Enseignement/analyseinfo/SQL92/BNFindex.html .Ve .PP You can find more information about \s-1SQL\s0 standards online by searching for the appropriate standard names and numbers. For example, searching for \&\*(L"\s-1ANSI/ISO/IEC\s0 International Standard (\s-1IS\s0) Database Language \s-1SQL\s0 \- Part 1: SQL/Framework\*(R" you'll find a copy at: .PP .Vb 1 \& ftp://ftp.iks\-jena.de/mitarb/lutz/standards/sql/ansi\-iso\-9075\-1\-1999.pdf .Ve .SS "Books and Articles" .IX Subsection "Books and Articles" Programming the Perl \s-1DBI,\s0 by Alligator Descartes and Tim Bunce. .PP Programming Perl 3rd Ed. by Larry Wall, Tom Christiansen & Jon Orwant. .PP Learning Perl by Randal Schwartz. .PP Details of many other books related to perl can be found at .SS "Perl Modules" .IX Subsection "Perl Modules" Index of \s-1DBI\s0 related modules available from \s-1CPAN:\s0 .PP .Vb 3 \& L \& L \& L .Ve .PP For a good comparison of RDBMS-OO mappers and some OO-RDBMS mappers (including Class::DBI, Alzabo, and DBIx::RecordSet in the former category and Tangram and \s-1SPOPS\s0 in the latter) see the Perl Object-Oriented Persistence project pages at: .PP .Vb 1 \& http://poop.sourceforge.net .Ve .PP A similar page for Java toolkits can be found at: .PP .Vb 1 \& http://c2.com/cgi\-bin/wiki?ObjectRelationalToolComparison .Ve .SS "Mailing List" .IX Subsection "Mailing List" The \fIdbi-users\fR mailing list is the primary means of communication among users of the \s-1DBI\s0 and its related modules. For details send email to: .PP .Vb 1 \& L .Ve .PP There are typically between 700 and 900 messages per month. You have to subscribe in order to be able to post. However you can opt for a \&'post\-only' subscription. .PP Mailing list archives (of variable quality) are held at: .PP .Vb 3 \& http://groups.google.com/groups?group=perl.dbi.users \& http://www.xray.mpe.mpg.de/mailing\-lists/dbi/ \& http://www.mail\-archive.com/dbi\-users%40perl.org/ .Ve .SS "Assorted Related Links" .IX Subsection "Assorted Related Links" The \s-1DBI\s0 \*(L"Home Page\*(R": .PP .Vb 1 \& http://dbi.perl.org/ .Ve .PP Other \s-1DBI\s0 related links: .PP .Vb 2 \& http://www.perlmonks.org/?node=DBI%20recipes \& http://www.perlmonks.org/?node=Speeding%20up%20the%20DBI .Ve .PP Other database related links: .PP .Vb 1 \& http://www.connectionstrings.com/ .Ve .PP Security, especially the \*(L"\s-1SQL\s0 Injection\*(R" attack: .PP .Vb 2 \& http://bobby\-tables.com/ \& http://online.securityfocus.com/infocus/1644 .Ve .SS "\s-1FAQ\s0" .IX Subsection "FAQ" See .SH "AUTHORS" .IX Header "AUTHORS" \&\s-1DBI\s0 by Tim Bunce, .PP This pod text by Tim Bunce, J. Douglas Dunlop, Jonathan Leffler and others. Perl by Larry Wall and the \f(CW\*(C`perl5\-porters\*(C'\fR. .SH "COPYRIGHT" .IX Header "COPYRIGHT" The \s-1DBI\s0 module is Copyright (c) 1994\-2012 Tim Bunce. Ireland. All rights reserved. .PP You may distribute under the terms of either the \s-1GNU\s0 General Public License or the Artistic License, as specified in the Perl 5.10.0 \s-1README\s0 file. .SH "SUPPORT / WARRANTY" .IX Header "SUPPORT / WARRANTY" The \s-1DBI\s0 is free Open Source software. \s-1IT COMES WITHOUT WARRANTY OF ANY KIND.\s0 .SS "Support" .IX Subsection "Support" My consulting company, Data Plan Services, offers annual and multi-annual support contracts for the \s-1DBI.\s0 These provide sustained support for \s-1DBI\s0 development, and sustained value for you in return. Contact me for details. .SS "Sponsor Enhancements" .IX Subsection "Sponsor Enhancements" If your company would benefit from a specific new \s-1DBI\s0 feature, please consider sponsoring its development. Work is performed rapidly, and usually on a fixed-price payment-on-delivery basis. Contact me for details. .PP Using such targeted financing allows you to contribute to \s-1DBI\s0 development, and rapidly get something specific and valuable in return. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" I would like to acknowledge the valuable contributions of the many people I have worked with on the \s-1DBI\s0 project, especially in the early years (1992\-1994). In no particular order: Kevin Stock, Buzz Moschetti, Kurt Andersen, Ted Lemon, William Hails, Garth Kennedy, Michael Peppler, Neil S. Briscoe, Jeff Urlwin, David J. Hughes, Jeff Stander, Forrest D Whitcher, Larry Wall, Jeff Fried, Roy Johnson, Paul Hudson, Georg Rehfeld, Steve Sizemore, Ron Pool, Jon Meek, Tom Christiansen, Steve Baumgarten, Randal Schwartz, and a whole lot more. .PP Then, of course, there are the poor souls who have struggled through untold and undocumented obstacles to actually implement \s-1DBI\s0 drivers. Among their ranks are Jochen Wiedmann, Alligator Descartes, Jonathan Leffler, Jeff Urlwin, Michael Peppler, Henrik Tougaard, Edwin Pratomo, Davide Migliavacca, Jan Pazdziora, Peter Haworth, Edmund Mergl, Steve Williams, Thomas Lowery, and Phlip Plumlee. Without them, the \s-1DBI\s0 would not be the practical reality it is today. I'm also especially grateful to Alligator Descartes for starting work on the first edition of the \&\*(L"Programming the Perl \s-1DBI\*(R"\s0 book and letting me jump on board. .PP The \s-1DBI\s0 and DBD::Oracle were originally developed while I was Technical Director (\s-1CTO\s0) of the Paul Ingram Group in the \s-1UK.\s0 So I'd especially like to thank Paul for his generosity and vision in supporting this work for many years. .PP A couple of specific \s-1DBI\s0 features have been sponsored by enlightened companies: .PP The development of the \fBswap_inner_handle()\fR method was sponsored by BizRate.com () .PP The development of DBD::Gofer and related modules was sponsored by Shopzilla.com (), where I currently work. .SH "CONTRIBUTING" .IX Header "CONTRIBUTING" As you can see above, many people have contributed to the \s-1DBI\s0 and drivers in many ways over many years. .PP If you'd like to help then see . .PP If you'd like the \s-1DBI\s0 to do something new or different then a good way to make that happen is to do it yourself and send me a patch to the source code that shows the changes. (But read \*(L"Speak before you patch\*(R" below.) .SS "Browsing the source code repository" .IX Subsection "Browsing the source code repository" Use https://github.com/perl5\-dbi/dbi .SS "How to create a patch using Git" .IX Subsection "How to create a patch using Git" The \s-1DBI\s0 source code is maintained using Git. To access the source you'll need to install a Git client. Then, to get the source code, do: .PP .Vb 1 \& git clone https://github.com/perl5\-dbi/dbi.git DBI\-git .Ve .PP The source code will now be available in the new subdirectory \f(CW\*(C`DBI\-git\*(C'\fR. .PP When you want to synchronize later, issue the command .PP .Vb 1 \& git pull \-\-all .Ve .PP Make your changes, test them, test them again until everything passes. If there are no tests for the new feature you added or a behaviour change, the change should include a new test. Then commit the changes. Either use .PP .Vb 1 \& git gui .Ve .PP or .PP .Vb 1 \& git commit \-a \-m \*(AqMessage to my changes\*(Aq .Ve .PP If you get any conflicts reported you'll need to fix them first. .PP Then generate the patch file to be mailed: .PP .Vb 1 \& git format\-patch \-1 \-\-attach .Ve .PP which will create a file 0001\-*.patch (where * relates to the commit message). Read the patch file, as a sanity check, and then email it to dbi\-dev@perl.org. .PP If you have a github account, you can also fork the repository, commit your changes to the forked repository and then do a pull request. .SS "How to create a patch without Git" .IX Subsection "How to create a patch without Git" Unpack a fresh copy of the distribution: .PP .Vb 2 \& wget http://cpan.metacpan.org/authors/id/T/TI/TIMB/DBI\-1.627.tar.gz \& tar xfz DBI\-1.627.tar.gz .Ve .PP Rename the newly created top level directory: .PP .Vb 1 \& mv DBI\-1.627 DBI\-1.627.your_foo .Ve .PP Edit the contents of \s-1DBI\-1.627\s0.your_foo/* till it does what you want. .PP Test your changes and then remove all temporary files: .PP .Vb 1 \& make test && make distclean .Ve .PP Go back to the directory you originally unpacked the distribution: .PP .Vb 1 \& cd .. .Ve .PP Unpack \fIanother\fR copy of the original distribution you started with: .PP .Vb 1 \& tar xfz DBI\-1.627.tar.gz .Ve .PP Then create a patch file by performing a recursive \f(CW\*(C`diff\*(C'\fR on the two top level directories: .PP .Vb 1 \& diff \-purd DBI\-1.627 DBI\-1.627.your_foo > DBI\-1.627.your_foo.patch .Ve .SS "Speak before you patch" .IX Subsection "Speak before you patch" For anything non-trivial or possibly controversial it's a good idea to discuss (on dbi\-dev@perl.org) the changes you propose before actually spending time working on them. Otherwise you run the risk of them being rejected because they don't fit into some larger plans you may not be aware of. .PP You can also reach the developers on \s-1IRC\s0 (chat). If they are on-line, the most likely place to talk to them is the #dbi channel on irc.perl.org .SH "TRANSLATIONS" .IX Header "TRANSLATIONS" A German translation of this manual (possibly slightly out of date) is available, thanks to O'Reilly, at: .PP .Vb 1 \& http://www.oreilly.de/catalog/perldbiger/ .Ve .SH "OTHER RELATED WORK AND PERL MODULES" .IX Header "OTHER RELATED WORK AND PERL MODULES" .IP "Apache::DBI" 4 .IX Item "Apache::DBI" To be used with the Apache daemon together with an embedded Perl interpreter like \f(CW\*(C`mod_perl\*(C'\fR. Establishes a database connection which remains open for the lifetime of the \s-1HTTP\s0 daemon. This way the \s-1CGI\s0 connect and disconnect for every database access becomes superfluous. .IP "\s-1SQL\s0 Parser" 4 .IX Item "SQL Parser" See also the SQL::Statement module, \s-1SQL\s0 parser and engine. man/man3/Net::HTTP.3pm000044400000040262152462503210010212 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Net::HTTP 3pm" .TH Net::HTTP 3pm "2021-03-18" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::HTTP \- Low\-level HTTP connection (client) .SH "VERSION" .IX Header "VERSION" version 6.21 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 4 \& use Net::HTTP; \& my $s = Net::HTTP\->new(Host => "www.perl.com") || die $@; \& $s\->write_request(GET => "/", \*(AqUser\-Agent\*(Aq => "Mozilla/5.0"); \& my($code, $mess, %h) = $s\->read_response_headers; \& \& while (1) { \& my $buf; \& my $n = $s\->read_entity_body($buf, 1024); \& die "read failed: $!" unless defined $n; \& last unless $n; \& print $buf; \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`Net::HTTP\*(C'\fR class is a low-level \s-1HTTP\s0 client. An instance of the \&\f(CW\*(C`Net::HTTP\*(C'\fR class represents a connection to an \s-1HTTP\s0 server. The \&\s-1HTTP\s0 protocol is described in \s-1RFC 2616.\s0 The \f(CW\*(C`Net::HTTP\*(C'\fR class supports \f(CW\*(C`HTTP/1.0\*(C'\fR and \f(CW\*(C`HTTP/1.1\*(C'\fR. .PP \&\f(CW\*(C`Net::HTTP\*(C'\fR is a sub-class of one of \f(CW\*(C`IO::Socket::IP\*(C'\fR (IPv6+IPv4), \&\f(CW\*(C`IO::Socket::INET6\*(C'\fR (IPv6+IPv4), or \f(CW\*(C`IO::Socket::INET\*(C'\fR (IPv4 only). You can mix the methods described below with reading and writing from the socket directly. This is not necessary a good idea, unless you know what you are doing. .PP The following methods are provided (in addition to those of \&\f(CW\*(C`IO::Socket::INET\*(C'\fR): .ie n .IP "$s = Net::HTTP\->new( %options )" 4 .el .IP "\f(CW$s\fR = Net::HTTP\->new( \f(CW%options\fR )" 4 .IX Item "$s = Net::HTTP->new( %options )" The \f(CW\*(C`Net::HTTP\*(C'\fR constructor method takes the same options as \&\f(CW\*(C`IO::Socket::INET\*(C'\fR's as well as these: .Sp .Vb 7 \& Host: Initial host attribute value \& KeepAlive: Initial keep_alive attribute value \& SendTE: Initial send_te attribute_value \& HTTPVersion: Initial http_version attribute value \& PeerHTTPVersion: Initial peer_http_version attribute value \& MaxLineLength: Initial max_line_length attribute value \& MaxHeaderLines: Initial max_header_lines attribute value .Ve .Sp The \f(CW\*(C`Host\*(C'\fR option is also the default for \f(CW\*(C`IO::Socket::INET\*(C'\fR's \&\f(CW\*(C`PeerAddr\*(C'\fR. The \f(CW\*(C`PeerPort\*(C'\fR defaults to 80 if not provided. The \f(CW\*(C`PeerPort\*(C'\fR specification can also be embedded in the \f(CW\*(C`PeerAddr\*(C'\fR by preceding it with a \*(L":\*(R", and closing the IPv6 address on brackets \*(L"[]\*(R" if necessary: \*(L"192.0.2.1:80\*(R",\*(L"[2001:db8::1]:80\*(R",\*(L"any.example.com:80\*(R". .Sp The \f(CW\*(C`Listen\*(C'\fR option provided by \f(CW\*(C`IO::Socket::INET\*(C'\fR's constructor method is not allowed. .Sp If unable to connect to the given \s-1HTTP\s0 server then the constructor returns \f(CW\*(C`undef\*(C'\fR and $@ contains the reason. After a successful connect, a \f(CW\*(C`Net:HTTP\*(C'\fR object is returned. .ie n .IP "$s\->host" 4 .el .IP "\f(CW$s\fR\->host" 4 .IX Item "$s->host" Get/set the default value of the \f(CW\*(C`Host\*(C'\fR header to send. The \f(CW$host\fR must not be set to an empty string (or \f(CW\*(C`undef\*(C'\fR) for \s-1HTTP/1.1.\s0 .ie n .IP "$s\->keep_alive" 4 .el .IP "\f(CW$s\fR\->keep_alive" 4 .IX Item "$s->keep_alive" Get/set the \fIkeep-alive\fR value. If this value is \s-1TRUE\s0 then the request will be sent with headers indicating that the server should try to keep the connection open so that multiple requests can be sent. .Sp The actual headers set will depend on the value of the \f(CW\*(C`http_version\*(C'\fR and \f(CW\*(C`peer_http_version\*(C'\fR attributes. .ie n .IP "$s\->send_te" 4 .el .IP "\f(CW$s\fR\->send_te" 4 .IX Item "$s->send_te" Get/set the a value indicating if the request will be sent with a \*(L"\s-1TE\*(R"\s0 header to indicate the transfer encodings that the server can choose to use. The list of encodings announced as accepted by this client depends on availability of the following modules: \f(CW\*(C`Compress::Raw::Zlib\*(C'\fR for \&\fIdeflate\fR, and \f(CW\*(C`IO::Compress::Gunzip\*(C'\fR for \fIgzip\fR. .ie n .IP "$s\->http_version" 4 .el .IP "\f(CW$s\fR\->http_version" 4 .IX Item "$s->http_version" Get/set the \s-1HTTP\s0 version number that this client should announce. This value can only be set to \*(L"1.0\*(R" or \*(L"1.1\*(R". The default is \*(L"1.1\*(R". .ie n .IP "$s\->peer_http_version" 4 .el .IP "\f(CW$s\fR\->peer_http_version" 4 .IX Item "$s->peer_http_version" Get/set the protocol version number of our peer. This value will initially be \*(L"1.0\*(R", but will be updated by a successful \&\fBread_response_headers()\fR method call. .ie n .IP "$s\->max_line_length" 4 .el .IP "\f(CW$s\fR\->max_line_length" 4 .IX Item "$s->max_line_length" Get/set a limit on the length of response line and response header lines. The default is 8192. A value of 0 means no limit. .ie n .IP "$s\->max_header_length" 4 .el .IP "\f(CW$s\fR\->max_header_length" 4 .IX Item "$s->max_header_length" Get/set a limit on the number of header lines that a response can have. The default is 128. A value of 0 means no limit. .ie n .IP "$s\->format_request($method, $uri, %headers, [$content])" 4 .el .IP "\f(CW$s\fR\->format_request($method, \f(CW$uri\fR, \f(CW%headers\fR, [$content])" 4 .IX Item "$s->format_request($method, $uri, %headers, [$content])" Format a request message and return it as a string. If the headers do not include a \f(CW\*(C`Host\*(C'\fR header, then a header is inserted with the value of the \f(CW\*(C`host\*(C'\fR attribute. Headers like \f(CW\*(C`Connection\*(C'\fR and \&\f(CW\*(C`Keep\-Alive\*(C'\fR might also be added depending on the status of the \&\f(CW\*(C`keep_alive\*(C'\fR attribute. .Sp If \f(CW$content\fR is given (and it is non-empty), then a \f(CW\*(C`Content\-Length\*(C'\fR header is automatically added unless it was already present. .ie n .IP "$s\->write_request($method, $uri, %headers, [$content])" 4 .el .IP "\f(CW$s\fR\->write_request($method, \f(CW$uri\fR, \f(CW%headers\fR, [$content])" 4 .IX Item "$s->write_request($method, $uri, %headers, [$content])" Format and send a request message. Arguments are the same as for \&\fBformat_request()\fR. Returns true if successful. .ie n .IP "$s\->format_chunk( $data )" 4 .el .IP "\f(CW$s\fR\->format_chunk( \f(CW$data\fR )" 4 .IX Item "$s->format_chunk( $data )" Returns the string to be written for the given chunk of data. .ie n .IP "$s\->write_chunk($data)" 4 .el .IP "\f(CW$s\fR\->write_chunk($data)" 4 .IX Item "$s->write_chunk($data)" Will write a new chunk of request entity body data. This method should only be used if the \f(CW\*(C`Transfer\-Encoding\*(C'\fR header with a value of \&\f(CW\*(C`chunked\*(C'\fR was sent in the request. Note, writing zero-length data is a no-op. Use the \fBwrite_chunk_eof()\fR method to signal end of entity body data. .Sp Returns true if successful. .ie n .IP "$s\->format_chunk_eof( %trailers )" 4 .el .IP "\f(CW$s\fR\->format_chunk_eof( \f(CW%trailers\fR )" 4 .IX Item "$s->format_chunk_eof( %trailers )" Returns the string to be written for signaling \s-1EOF\s0 when a \&\f(CW\*(C`Transfer\-Encoding\*(C'\fR of \f(CW\*(C`chunked\*(C'\fR is used. .ie n .IP "$s\->write_chunk_eof( %trailers )" 4 .el .IP "\f(CW$s\fR\->write_chunk_eof( \f(CW%trailers\fR )" 4 .IX Item "$s->write_chunk_eof( %trailers )" Will write eof marker for chunked data and optional trailers. Note that trailers should not really be used unless is was signaled with a \f(CW\*(C`Trailer\*(C'\fR header. .Sp Returns true if successful. .ie n .IP "($code, $mess, %headers) = $s\->read_response_headers( %opts )" 4 .el .IP "($code, \f(CW$mess\fR, \f(CW%headers\fR) = \f(CW$s\fR\->read_response_headers( \f(CW%opts\fR )" 4 .IX Item "($code, $mess, %headers) = $s->read_response_headers( %opts )" Read response headers from server and return it. The \f(CW$code\fR is the 3 digit \s-1HTTP\s0 status code (see HTTP::Status) and \f(CW$mess\fR is the textual message that came with it. Headers are then returned as key/value pairs. Since key letter casing is not normalized and the same key can even occur multiple times, assigning these values directly to a hash is not wise. Only the \f(CW$code\fR is returned if this method is called in scalar context. .Sp As a side effect this method updates the 'peer_http_version' attribute. .Sp Options might be passed in as key/value pairs. There are currently only two options supported; \f(CW\*(C`laxed\*(C'\fR and \f(CW\*(C`junk_out\*(C'\fR. .Sp The \f(CW\*(C`laxed\*(C'\fR option will make \fBread_response_headers()\fR more forgiving towards servers that have not learned how to speak \s-1HTTP\s0 properly. The \&\f(CW\*(C`laxed\*(C'\fR option is a boolean flag, and is enabled by passing in a \s-1TRUE\s0 value. The \f(CW\*(C`junk_out\*(C'\fR option can be used to capture bad header lines when \f(CW\*(C`laxed\*(C'\fR is enabled. The value should be an array reference. Bad header lines will be pushed onto the array. .Sp The \f(CW\*(C`laxed\*(C'\fR option must be specified in order to communicate with pre\-HTTP/1.0 servers that don't describe the response outcome or the data they send back with a header block. For these servers peer_http_version is set to \*(L"0.9\*(R" and this method returns (200, \&\*(L"Assumed \s-1OK\*(R"\s0). .Sp The method will raise an exception (die) if the server does not speak proper \s-1HTTP\s0 or if the \f(CW\*(C`max_line_length\*(C'\fR or \f(CW\*(C`max_header_length\*(C'\fR limits are reached. If the \f(CW\*(C`laxed\*(C'\fR option is turned on and \&\f(CW\*(C`max_line_length\*(C'\fR and \f(CW\*(C`max_header_length\*(C'\fR checks are turned off, then no exception will be raised and this method will always return a response code. .ie n .IP "$n = $s\->read_entity_body($buf, $size);" 4 .el .IP "\f(CW$n\fR = \f(CW$s\fR\->read_entity_body($buf, \f(CW$size\fR);" 4 .IX Item "$n = $s->read_entity_body($buf, $size);" Reads chunks of the entity body content. Basically the same interface as for \fBread()\fR and \fBsysread()\fR, but the buffer offset argument is not supported yet. This method should only be called after a successful \&\fBread_response_headers()\fR call. .Sp The return value will be \f(CW\*(C`undef\*(C'\fR on read errors, 0 on \s-1EOF,\s0 \-1 if no data could be returned this time, otherwise the number of bytes assigned to \f(CW$buf\fR. The \f(CW$buf\fR is set to "" when the return value is \-1. .Sp You normally want to retry this call if this function returns either \&\-1 or \f(CW\*(C`undef\*(C'\fR with \f(CW$!\fR as \s-1EINTR\s0 or \s-1EAGAIN\s0 (see Errno). \s-1EINTR\s0 can happen if the application catches signals and \s-1EAGAIN\s0 can happen if you made the socket non-blocking. .Sp This method will raise exceptions (die) if the server does not speak proper \s-1HTTP.\s0 This can only happen when reading chunked data. .ie n .IP "%headers = $s\->get_trailers" 4 .el .IP "\f(CW%headers\fR = \f(CW$s\fR\->get_trailers" 4 .IX Item "%headers = $s->get_trailers" After \fBread_entity_body()\fR has returned 0 to indicate end of the entity body, you might call this method to pick up any trailers. .ie n .IP "$s\->_rbuf" 4 .el .IP "\f(CW$s\fR\->_rbuf" 4 .IX Item "$s->_rbuf" Get/set the read buffer content. The \fBread_response_headers()\fR and \&\fBread_entity_body()\fR methods use an internal buffer which they will look for data before they actually sysread more from the socket itself. If they read too much, the remaining data will be left in this buffer. .ie n .IP "$s\->_rbuf_length" 4 .el .IP "\f(CW$s\fR\->_rbuf_length" 4 .IX Item "$s->_rbuf_length" Returns the number of bytes in the read buffer. This should always be the same as: .Sp .Vb 1 \& length($s\->_rbuf) .Ve .Sp but might be more efficient. .SH "SUBCLASSING" .IX Header "SUBCLASSING" The \fBread_response_headers()\fR and \fBread_entity_body()\fR will invoke the \&\fBsysread()\fR method when they need more data. Subclasses might want to override this method to control how reading takes place. .PP The object itself is a glob. Subclasses should avoid using hash key names prefixed with \f(CW\*(C`http_\*(C'\fR and \f(CW\*(C`io_\*(C'\fR. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1LWP\s0, IO::Socket::INET, Net::HTTP::NB .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2001\-2017 by Gisle Aas. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. man/man3/version.3pm000044400000033155152462503210010270 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "version 3" .TH version 3 "2020-07-31" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" version \- Perl extension for Version Objects .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& # Parsing version strings (decimal or dotted\-decimal) \& \& use version 0.77; # get latest bug\-fixes and API \& $ver = version\->parse($string) \& \& # Declaring a dotted\-decimal $VERSION (keep on one line!) \& \& use version; our $VERSION = version\->declare("v1.2.3"); # formal \& use version; our $VERSION = qv("v1.2.3"); # deprecated \& use version; our $VERSION = qv("v1.2_3"); # deprecated \& \& # Declaring an old\-style decimal $VERSION (use quotes!) \& \& our $VERSION = "1.0203"; # recommended \& use version; our $VERSION = version\->parse("1.0203"); # formal \& use version; our $VERSION = version\->parse("1.02_03"); # alpha \& \& # Comparing mixed version styles (decimals, dotted\-decimals, objects) \& \& if ( version\->parse($v1) == version\->parse($v2) ) { \& # do stuff \& } \& \& # Sorting mixed version styles \& \& @ordered = sort { version\->parse($a) <=> version\->parse($b) } @list; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Version objects were added to Perl in 5.10. This module implements version objects for older version of Perl and provides the version object \s-1API\s0 for all versions of Perl. All previous releases before 0.74 are deprecated and should not be used due to incompatible \s-1API\s0 changes. Version 0.77 introduces the new \&'parse' and 'declare' methods to standardize usage. You are strongly urged to set 0.77 as a minimum in your code, e.g. .PP .Vb 1 \& use version 0.77; # even for Perl v.5.10.0 .Ve .SH "TYPES OF VERSION OBJECTS" .IX Header "TYPES OF VERSION OBJECTS" There are two different types of version objects, corresponding to the two different styles of versions in use: .IP "Decimal Versions" 2 .IX Item "Decimal Versions" The classic floating-point number \f(CW$VERSION\fR. The advantage to this style is that you don't need to do anything special, just type a number into your source file. Quoting is recommended, as it ensures that trailing zeroes (\*(L"1.50\*(R") are preserved in any warnings or other output. .IP "Dotted Decimal Versions" 2 .IX Item "Dotted Decimal Versions" The more modern form of version assignment, with 3 (or potentially more) integers separated by decimal points (e.g. v1.2.3). This is the form that Perl itself has used since 5.6.0 was released. The leading 'v' is now strongly recommended for clarity, and will throw a warning in a future release if omitted. A leading 'v' character is required to pass the \&\*(L"\fBis_strict()\fR\*(R" test. .SH "DECLARING VERSIONS" .IX Header "DECLARING VERSIONS" If you have a module that uses a decimal \f(CW$VERSION\fR (floating point), and you do not intend to ever change that, this module is not for you. There is nothing that version.pm gains you over a simple \f(CW$VERSION\fR assignment: .PP .Vb 1 \& our $VERSION = "1.02"; .Ve .PP Since Perl v5.10.0 includes the version.pm comparison logic anyways, you don't need to do anything at all. .SS "How to convert a module from decimal to dotted-decimal" .IX Subsection "How to convert a module from decimal to dotted-decimal" If you have used a decimal \f(CW$VERSION\fR in the past and wish to switch to a dotted-decimal \f(CW$VERSION\fR, then you need to make a one-time conversion to the new format. .PP \&\fBImportant Note\fR: you must ensure that your new \f(CW$VERSION\fR is numerically greater than your current decimal \f(CW$VERSION\fR; this is not always obvious. First, convert your old decimal version (e.g. 1.02) to a normalized dotted-decimal form: .PP .Vb 2 \& $ perl \-Mversion \-e \*(Aqprint version\->parse("1.02")\->normal\*(Aq \& v1.20.0 .Ve .PP Then increment any of the dotted-decimal components (v1.20.1 or v1.21.0). .ie n .SS "How to ""declare()"" a dotted-decimal version" .el .SS "How to \f(CWdeclare()\fP a dotted-decimal version" .IX Subsection "How to declare() a dotted-decimal version" .Vb 1 \& use version; our $VERSION = version\->declare("v1.2.3"); .Ve .PP The \f(CW\*(C`declare()\*(C'\fR method always creates dotted-decimal version objects. When used in a module, you \fBmust\fR put it on the same line as \*(L"use version\*(R" to ensure that \f(CW$VERSION\fR is read correctly by \s-1PAUSE\s0 and installer tools. You should also add 'version' to the 'configure_requires' section of your module metadata file. See instructions in ExtUtils::MakeMaker or Module::Build for details. .PP \&\fBImportant Note\fR: Even if you pass in what looks like a decimal number (\*(L"1.2\*(R"), a dotted-decimal will be created (\*(L"v1.200.0\*(R"). To avoid confusion or unintentional errors on older Perls, follow these guidelines: .IP "\(bu" 2 Always use a dotted-decimal with (at least) three components .IP "\(bu" 2 Always use a leading-v .IP "\(bu" 2 Always quote the version .PP If you really insist on using version.pm with an ordinary decimal version, use \f(CW\*(C`parse()\*(C'\fR instead of declare. See the \*(L"\s-1PARSING AND COMPARING VERSIONS\*(R"\s0 for details. .PP See also version::Internals for more on version number conversion, quoting, calculated version numbers and declaring developer or \*(L"alpha\*(R" version numbers. .SH "PARSING AND COMPARING VERSIONS" .IX Header "PARSING AND COMPARING VERSIONS" If you need to compare version numbers, but can't be sure whether they are expressed as numbers, strings, v\-strings or version objects, then you should use version.pm to parse them all into objects for comparison. .ie n .SS "How to ""parse()"" a version" .el .SS "How to \f(CWparse()\fP a version" .IX Subsection "How to parse() a version" The \f(CW\*(C`parse()\*(C'\fR method takes in anything that might be a version and returns a corresponding version object, doing any necessary conversion along the way. .IP "\(bu" 2 Dotted-decimal: bare v\-strings (v1.2.3) and strings with more than one decimal point and a leading 'v' (\*(L"v1.2.3\*(R"); \s-1NOTE\s0 you can technically use a v\-string or strings with a leading-v and only one decimal point (v1.2 or \&\*(L"v1.2\*(R"), but you will confuse both yourself and others. .IP "\(bu" 2 Decimal: regular decimal numbers (literal or in a string) .PP Some examples: .PP .Vb 8 \& $variable version\->parse($variable) \& \-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& 1.23 v1.230.0 \& "1.23" v1.230.0 \& v1.23 v1.23.0 \& "v1.23" v1.23.0 \& "1.2.3" v1.2.3 \& "v1.2.3" v1.2.3 .Ve .PP See version::Internals for more on version number conversion. .SS "How to check for a legal version string" .IX Subsection "How to check for a legal version string" If you do not want to actually create a full blown version object, but would still like to verify that a given string meets the criteria to be parsed as a version, there are two helper functions that can be employed directly: .ie n .IP """is_lax()""" 4 .el .IP "\f(CWis_lax()\fR" 4 .IX Item "is_lax()" The lax criteria corresponds to what is currently allowed by the version parser. All of the following formats are acceptable for dotted-decimal formats strings: .Sp .Vb 5 \& v1.2 \& 1.2345.6 \& v1.23_4 \& 1.2345 \& 1.2345_01 .Ve .ie n .IP """is_strict()""" 4 .el .IP "\f(CWis_strict()\fR" 4 .IX Item "is_strict()" If you want to limit yourself to a much more narrow definition of what a version string constitutes, \f(CW\*(C`is_strict()\*(C'\fR is limited to version strings like the following list: .Sp .Vb 2 \& v1.234.5 \& 2.3456 .Ve .PP See version::Internals for details of the regular expressions that define the legal version string forms, as well as how to use those regular expressions in your own code if \f(CW\*(C`is_lax()\*(C'\fR and \&\f(CW\*(C`is_strict()\*(C'\fR are not sufficient for your needs. .SS "How to compare version objects" .IX Subsection "How to compare version objects" Version objects overload the \f(CW\*(C`cmp\*(C'\fR and \f(CW\*(C`<=>\*(C'\fR operators. Perl automatically generates all of the other comparison operators based on those two so all the normal logical comparisons will work. .PP .Vb 3 \& if ( version\->parse($v1) == version\->parse($v2) ) { \& # do stuff \& } .Ve .PP If a version object is compared against a non-version object, the non-object term will be converted to a version object using \f(CW\*(C`parse()\*(C'\fR. This may give surprising results: .PP .Vb 2 \& $v1 = version\->parse("v0.95.0"); \& $bool = $v1 < 0.94; # TRUE since 0.94 is v0.940.0 .Ve .PP Always comparing to a version object will help avoid surprises: .PP .Vb 1 \& $bool = $v1 < version\->parse("v0.94.0"); # FALSE .Ve .PP Note that \*(L"alpha\*(R" version objects (where the version string contains a trailing underscore segment) compare as less than the equivalent version without an underscore: .PP .Vb 1 \& $bool = version\->parse("1.23_45") < version\->parse("1.2345"); # TRUE .Ve .PP See version::Internals for more details on \*(L"alpha\*(R" versions. .SH "OBJECT METHODS" .IX Header "OBJECT METHODS" .SS "\fBis_alpha()\fP" .IX Subsection "is_alpha()" True if and only if the version object was created with a underscore, e.g. .PP .Vb 2 \& version\->parse(\*(Aq1.002_03\*(Aq)\->is_alpha; # TRUE \& version\->declare(\*(Aq1.2.3_4\*(Aq)\->is_alpha; # TRUE .Ve .SS "\fBis_qv()\fP" .IX Subsection "is_qv()" True only if the version object is a dotted-decimal version, e.g. .PP .Vb 4 \& version\->parse(\*(Aqv1.2.0\*(Aq)\->is_qv; # TRUE \& version\->declare(\*(Aqv1.2\*(Aq)\->is_qv; # TRUE \& qv(\*(Aq1.2\*(Aq)\->is_qv; # TRUE \& version\->parse(\*(Aq1.2\*(Aq)\->is_qv; # FALSE .Ve .SS "\fBnormal()\fP" .IX Subsection "normal()" Returns a string with a standard 'normalized' dotted-decimal form with a leading-v and at least 3 components. .PP .Vb 2 \& version\->declare(\*(Aqv1.2\*(Aq)\->normal; # v1.2.0 \& version\->parse(\*(Aq1.2\*(Aq)\->normal; # v1.200.0 .Ve .SS "\fBnumify()\fP" .IX Subsection "numify()" Returns a value representing the object in a pure decimal. .PP .Vb 2 \& version\->declare(\*(Aqv1.2\*(Aq)\->numify; # 1.002000 \& version\->parse(\*(Aq1.2\*(Aq)\->numify; # 1.200 .Ve .SS "\fBstringify()\fP" .IX Subsection "stringify()" Returns a string that is as close to the original representation as possible. If the original representation was a numeric literal, it will be returned the way perl would normally represent it in a string. This method is used whenever a version object is interpolated into a string. .PP .Vb 3 \& version\->declare(\*(Aqv1.2\*(Aq)\->stringify; # v1.2 \& version\->parse(\*(Aq1.200\*(Aq)\->stringify; # 1.2 \& version\->parse(1.02_30)\->stringify; # 1.023 .Ve .SH "EXPORTED FUNCTIONS" .IX Header "EXPORTED FUNCTIONS" .SS "\fBqv()\fP" .IX Subsection "qv()" This function is no longer recommended for use, but is maintained for compatibility with existing code. If you do not want to have it exported to your namespace, use this form: .PP .Vb 1 \& use version 0.77 (); .Ve .SS "\fBis_lax()\fP" .IX Subsection "is_lax()" (Not exported by default) .PP This function takes a scalar argument and returns a boolean value indicating whether the argument meets the \*(L"lax\*(R" rules for a version number. Leading and trailing spaces are not allowed. .SS "\fBis_strict()\fP" .IX Subsection "is_strict()" (Not exported by default) .PP This function takes a scalar argument and returns a boolean value indicating whether the argument meets the \*(L"strict\*(R" rules for a version number. Leading and trailing spaces are not allowed. .SH "AUTHOR" .IX Header "AUTHOR" John Peacock .SH "SEE ALSO" .IX Header "SEE ALSO" version::Internals. .PP perl. man/man3/DBD::Sponge.3pm000044400000010773152462503210010535 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Sponge 3" .TH DBD::Sponge 3 "2015-05-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Sponge \- Create a DBI statement handle from Perl data .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 7 \& my $sponge = DBI\->connect("dbi:Sponge:","","",{ RaiseError => 1 }); \& my $sth = $sponge\->prepare($statement, { \& rows => $data, \& NAME => $names, \& %attr \& } \& ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBD::Sponge is useful for making a Perl data structure accessible through a standard \s-1DBI\s0 statement handle. This may be useful to \s-1DBD\s0 module authors who need to transform data in this way. .SH "METHODS" .IX Header "METHODS" .SS "\fBconnect()\fP" .IX Subsection "connect()" .Vb 1 \& my $sponge = DBI\->connect("dbi:Sponge:","","",{ RaiseError => 1 }); .Ve .PP Here's a sample syntax for creating a database handle for the Sponge driver. No username and password are needed. .SS "\fBprepare()\fP" .IX Subsection "prepare()" .Vb 6 \& my $sth = $sponge\->prepare($statement, { \& rows => $data, \& NAME => $names, \& %attr \& } \& ); .Ve .IP "\(bu" 4 The \f(CW$statement\fR here is an arbitrary statement or name you want to provide as identity of your data. If you're using DBI::Profile it will appear in the profile data. .Sp Generally it's expected that you are preparing a statement handle as if a \f(CW\*(C`select\*(C'\fR statement happened. .IP "\(bu" 4 \&\f(CW$data\fR is a reference to the data you are providing, given as an array of arrays. .IP "\(bu" 4 \&\f(CW$names\fR is a reference an array of column names for the \f(CW$data\fR you are providing. The number and order should match the number and ordering of the \f(CW$data\fR columns. .IP "\(bu" 4 \&\f(CW%attr\fR is a hash of other standard \s-1DBI\s0 attributes that you might pass to a prepare statement. .Sp Currently only \s-1NAME, TYPE,\s0 and \s-1PRECISION\s0 are supported. .SH "BUGS" .IX Header "BUGS" Using this module to prepare INSERT-like statements is not currently documented. .SH "AUTHOR AND COPYRIGHT" .IX Header "AUTHOR AND COPYRIGHT" This module is Copyright (c) 2003 Tim Bunce .PP Documentation initially written by Mark Stosberg .PP The DBD::Sponge module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. In particular permission is granted to Tim Bunce for distributing this as a part of the \s-1DBI.\s0 .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1DBI\s0 man/man3/Types::Serialiser::Error.3pm000044400000005215152462503210013310 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Serialiser::Error 3" .TH Serialiser::Error 3 "2013-10-27" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Types::Serialiser::Error \- dummy module for Types::Serialiser .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& # do not "use" yourself .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module exists only to provide overload resolution for Storable and similar modules that assume that class name equals module name. See Types::Serialiser for more info about this class. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 2 \& Marc Lehmann \& http://home.schmorp.de/ .Ve man/man3/DBD::Gofer::Transport::pipeone.3pm000044400000006531152462503210014206 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Transport::pipeone 3" .TH DBD::Gofer::Transport::pipeone 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Transport::pipeone \- DBD::Gofer client transport for testing .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& $original_dsn = "..."; \& DBI\->connect("dbi:Gofer:transport=pipeone;dsn=$original_dsn",...) .Ve .PP or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: .PP .Vb 1 \& export DBI_AUTOPROXY="dbi:Gofer:transport=pipeone" .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Connect via DBD::Gofer and execute each request by starting executing a subprocess. .PP This is, as you might imagine, spectacularly inefficient! .PP It's only intended for testing. Specifically it demonstrates that the server side is completely stateless. .PP It also provides a base class for the much more useful DBD::Gofer::Transport::stream transport. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. .SH "SEE ALSO" .IX Header "SEE ALSO" DBD::Gofer::Transport::Base .PP DBD::Gofer man/man3/Log::NullLogLite.3pm000044400000012054152462503210011616 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "NullLogLite 3" .TH NullLogLite 3 "2002-09-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Log::NullLogLite \- The "Log::NullLogLite" class implements the Null Object pattern for the "Log::LogLite" class. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Log::NullLogLite; \& \& # create new Log::NullLogLite object \& my $log = new Log::NullLogLite(); \& \& ... \& \& # we had an error (this entry will not be written to the log \& # file because we use Log::NullLogLite object). \& $log\->write("Could not open the file ".$file_name.": $!", 4); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`Log::NullLogLite\*(C'\fR class is derived from the \f(CW\*(C`Log::LogLite\*(C'\fR class and implement the Null Object Pattern to let us to use the \f(CW\*(C`Log::LogLite\*(C'\fR class with \fBnull\fR \f(CW\*(C`Log::LogLite\*(C'\fR objects. We might want to do that if we use a \f(CW\*(C`Log::LogLite\*(C'\fR object in our code, and we do not want always to actually define a \f(CW\*(C`Log::LogLite\*(C'\fR object (i.e. not always we want to write to a log file). In such a case we will create a \&\f(CW\*(C`Log::NullLogLite\*(C'\fR object instead of the \f(CW\*(C`Log::LogLite\*(C'\fR object, and will use that object instead. The object has all the methods that the \f(CW\*(C`Log::LogLite\*(C'\fR object has, but those methods do nothing. Thus our code will continue to run without any change, yet we will not have to define a log file path for the \&\f(CW\*(C`Log::LogLite\*(C'\fR object, and no log will be created. .SH "CONSTRUCTOR" .IX Header "CONSTRUCTOR" .IP "new ( \s-1FILEPATH\s0 [,LEVEL [,DEFAULT_MESSAGE ]] )" 4 .IX Item "new ( FILEPATH [,LEVEL [,DEFAULT_MESSAGE ]] )" The constructor. The parameters will not have any affect. Returns the new Log::NullLogLite object. .SH "METHODS" .IX Header "METHODS" .IP "write( \s-1MESSAGE\s0 [, \s-1LEVEL\s0 ] )" 4 .IX Item "write( MESSAGE [, LEVEL ] )" Does nothing. The parameters will not have any affect. Returns nothing. .IP "level( [ \s-1LEVEL\s0 ] )" 4 .IX Item "level( [ LEVEL ] )" Does nothing. The parameters will not have any affect. Returns \-1. .IP "default_message( [ \s-1MESSAGE\s0 ] )" 4 .IX Item "default_message( [ MESSAGE ] )" Does nothing. The parameters will not have any affect. Returns empty string (""). .SH "AUTHOR" .IX Header "AUTHOR" Rani Pinchuk, rani@cpan.org .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2001\-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBLog::LogLite\fR\|(3), The Null Object Pattern \- Bobby Woolf \- PLoP96 \- published in Pattern Languages of Program Design 3 (http://cseng.aw.com/book/0,,0201310112,00.html) .SH "POD ERRORS" .IX Header "POD ERRORS" Hey! \fBThe above document had some coding errors, which are explained below:\fR .IP "Around line 128:" 4 .IX Item "Around line 128:" You forgot a '=back' before '=head1' man/man3/DBI::ProxyServer.3pm000044400000056013152462503210011614 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::ProxyServer 3" .TH DBI::ProxyServer 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::ProxyServer \- a server for the DBD::Proxy driver .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use DBI::ProxyServer; \& DBI::ProxyServer::main(@ARGV); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBI::Proxy Server is a module for implementing a proxy for the \s-1DBI\s0 proxy driver, DBD::Proxy. It allows access to databases over the network if the \&\s-1DBMS\s0 does not offer networked operations. But the proxy server might be useful for you, even if you have a \s-1DBMS\s0 with integrated network functionality: It can be used as a \s-1DBI\s0 proxy in a firewalled environment. .PP DBI::ProxyServer runs as a daemon on the machine with the \s-1DBMS\s0 or on the firewall. The client connects to the agent using the \s-1DBI\s0 driver DBD::Proxy, thus in the exactly same way than using DBD::mysql, DBD::mSQL or any other \&\s-1DBI\s0 driver. .PP The agent is implemented as a RPC::PlServer application. Thus you have access to all the possibilities of this module, in particular encryption and a similar configuration file. DBI::ProxyServer adds the possibility of query restrictions: You can define a set of queries that a client may execute and restrict access to those. (Requires a \s-1DBI\s0 driver that supports parameter binding.) See \*(L"\s-1CONFIGURATION FILE\*(R"\s0. .PP The provided driver script, dbiproxy, may either be used as it is or used as the basis for a local version modified to meet your needs. .SH "OPTIONS" .IX Header "OPTIONS" When calling the \fBDBI::ProxyServer::main()\fR function, you supply an array of options. These options are parsed by the Getopt::Long module. The ProxyServer inherits all of RPC::PlServer's and hence Net::Daemon's options and option handling, in particular the ability to read options from either the command line or a config file. See RPC::PlServer. See Net::Daemon. Available options include .IP "\fIchroot\fR (\fB\-\-chroot=dir\fR)" 4 .IX Item "chroot (--chroot=dir)" (\s-1UNIX\s0 only) After doing a \fBbind()\fR, change root directory to the given directory by doing a \fBchroot()\fR. This is useful for security, but it restricts the environment a lot. For example, you need to load \s-1DBI\s0 drivers in the config file or you have to create hard links to Unix sockets, if your drivers are using them. For example, with MySQL, a config file might contain the following lines: .Sp .Vb 9 \& my $rootdir = \*(Aq/var/dbiproxy\*(Aq; \& my $unixsockdir = \*(Aq/tmp\*(Aq; \& my $unixsockfile = \*(Aqmysql.sock\*(Aq; \& foreach $dir ($rootdir, "$rootdir$unixsockdir") { \& mkdir 0755, $dir; \& } \& link("$unixsockdir/$unixsockfile", \& "$rootdir$unixsockdir/$unixsockfile"); \& require DBD::mysql; \& \& { \& \*(Aqchroot\*(Aq => $rootdir, \& ... \& } .Ve .Sp If you don't know \fBchroot()\fR, think of an \s-1FTP\s0 server where you can see a certain directory tree only after logging in. See also the \-\-group and \&\-\-user options. .IP "\fIclients\fR" 4 .IX Item "clients" An array ref with a list of clients. Clients are hash refs, the attributes \&\fIaccept\fR (0 for denying access and 1 for permitting) and \fImask\fR, a Perl regular expression for the clients \s-1IP\s0 number or its host name. .IP "\fIconfigfile\fR (\fB\-\-configfile=file\fR)" 4 .IX Item "configfile (--configfile=file)" Config files are assumed to return a single hash ref that overrides the arguments of the new method. However, command line arguments in turn take precedence over the config file. See the \*(L"\s-1CONFIGURATION FILE\*(R"\s0 section below for details on the config file. .IP "\fIdebug\fR (\fB\-\-debug\fR)" 4 .IX Item "debug (--debug)" Turn debugging mode on. Mainly this asserts that logging messages of level \*(L"debug\*(R" are created. .IP "\fIfacility\fR (\fB\-\-facility=mode\fR)" 4 .IX Item "facility (--facility=mode)" (\s-1UNIX\s0 only) Facility to use for Sys::Syslog. The default is \&\fBdaemon\fR. .IP "\fIgroup\fR (\fB\-\-group=gid\fR)" 4 .IX Item "group (--group=gid)" After doing a \fBbind()\fR, change the real and effective \s-1GID\s0 to the given. This is useful, if you want your server to bind to a privileged port (<1024), but don't want the server to execute as root. See also the \-\-user option. .Sp \&\s-1GID\s0's can be passed as group names or numeric values. .IP "\fIlocaladdr\fR (\fB\-\-localaddr=ip\fR)" 4 .IX Item "localaddr (--localaddr=ip)" By default a daemon is listening to any \s-1IP\s0 number that a machine has. This attribute allows one to restrict the server to the given \&\s-1IP\s0 number. .IP "\fIlocalport\fR (\fB\-\-localport=port\fR)" 4 .IX Item "localport (--localport=port)" This attribute sets the port on which the daemon is listening. It must be given somehow, as there's no default. .IP "\fIlogfile\fR (\fB\-\-logfile=file\fR)" 4 .IX Item "logfile (--logfile=file)" Be default logging messages will be written to the syslog (Unix) or to the event log (Windows \s-1NT\s0). On other operating systems you need to specify a log file. The special value \*(L"\s-1STDERR\*(R"\s0 forces logging to stderr. See Net::Daemon::Log for details. .IP "\fImode\fR (\fB\-\-mode=modename\fR)" 4 .IX Item "mode (--mode=modename)" The server can run in three different modes, depending on the environment. .Sp If you are running Perl 5.005 and did compile it for threads, then the server will create a new thread for each connection. The thread will execute the server's \fBRun()\fR method and then terminate. This mode is the default, you can force it with \*(L"\-\-mode=threads\*(R". .Sp If threads are not available, but you have a working \fBfork()\fR, then the server will behave similar by creating a new process for each connection. This mode will be used automatically in the absence of threads or if you use the \*(L"\-\-mode=fork\*(R" option. .Sp Finally there's a single-connection mode: If the server has accepted a connection, he will enter the \fBRun()\fR method. No other connections are accepted until the \fBRun()\fR method returns (if the client disconnects). This operation mode is useful if you have neither threads nor \fBfork()\fR, for example on the Macintosh. For debugging purposes you can force this mode with \*(L"\-\-mode=single\*(R". .IP "\fIpidfile\fR (\fB\-\-pidfile=file\fR)" 4 .IX Item "pidfile (--pidfile=file)" (\s-1UNIX\s0 only) If this option is present, a \s-1PID\s0 file will be created at the given location. Default is to not create a pidfile. .IP "\fIuser\fR (\fB\-\-user=uid\fR)" 4 .IX Item "user (--user=uid)" After doing a \fBbind()\fR, change the real and effective \s-1UID\s0 to the given. This is useful, if you want your server to bind to a privileged port (<1024), but don't want the server to execute as root. See also the \-\-group and the \-\-chroot options. .Sp \&\s-1UID\s0's can be passed as group names or numeric values. .IP "\fIversion\fR (\fB\-\-version\fR)" 4 .IX Item "version (--version)" Suppresses startup of the server; instead the version string will be printed and the program exits immediately. .SH "SHUTDOWN" .IX Header "SHUTDOWN" DBI::ProxyServer is built on RPC::PlServer which is, in turn, built on Net::Daemon. .PP You should refer to Net::Daemon for how to shutdown the server, except that you can't because it's not currently documented there (as of v0.43). The bottom-line is that it seems that there's no support for graceful shutdown. .SH "CONFIGURATION FILE" .IX Header "CONFIGURATION FILE" The configuration file is just that of \fIRPC::PlServer\fR or \fINet::Daemon\fR with some additional attributes in the client list. .PP The config file is a Perl script. At the top of the file you may include arbitrary Perl source, for example load drivers at the start (useful to enhance performance), prepare a chroot environment and so on. .PP The important thing is that you finally return a hash ref of option name/value pairs. The possible options are listed above. .PP All possibilities of Net::Daemon and RPC::PlServer apply, in particular .IP "Host and/or User dependent access control" 4 .IX Item "Host and/or User dependent access control" .PD 0 .IP "Host and/or User dependent encryption" 4 .IX Item "Host and/or User dependent encryption" .IP "Changing \s-1UID\s0 and/or \s-1GID\s0 after binding to the port" 4 .IX Item "Changing UID and/or GID after binding to the port" .IP "Running in a \fBchroot()\fR environment" 4 .IX Item "Running in a chroot() environment" .PD .PP Additionally the server offers you query restrictions. Suggest the following client list: .PP .Vb 10 \& \*(Aqclients\*(Aq => [ \& { \*(Aqmask\*(Aq => \*(Aq^admin\e.company\e.com$\*(Aq, \& \*(Aqaccept\*(Aq => 1, \& \*(Aqusers\*(Aq => [ \*(Aqroot\*(Aq, \*(Aqwwwrun\*(Aq ], \& }, \& { \& \*(Aqmask\*(Aq => \*(Aq^admin\e.company\e.com$\*(Aq, \& \*(Aqaccept\*(Aq => 1, \& \*(Aqusers\*(Aq => [ \*(Aqroot\*(Aq, \*(Aqwwwrun\*(Aq ], \& \*(Aqsql\*(Aq => { \& \*(Aqselect\*(Aq => \*(AqSELECT * FROM foo\*(Aq, \& \*(Aqinsert\*(Aq => \*(AqINSERT INTO foo VALUES (?, ?, ?)\*(Aq \& } \& } .Ve .PP then only the users root and wwwrun may connect from admin.company.com, executing arbitrary queries, but only wwwrun may connect from other hosts and is restricted to .PP .Vb 1 \& $sth\->prepare("select"); .Ve .PP or .PP .Vb 1 \& $sth\->prepare("insert"); .Ve .PP which in fact are \*(L"\s-1SELECT\s0 * \s-1FROM\s0 foo\*(R" or \*(L"\s-1INSERT INTO\s0 foo \s-1VALUES\s0 (?, ?, ?)\*(R". .SH "Proxyserver Configuration file (bigger example)" .IX Header "Proxyserver Configuration file (bigger example)" This section tells you how to restrict a DBI-Proxy: Not every user from every workstation shall be able to execute every query. .PP There is a perl program \*(L"dbiproxy\*(R" which runs on a machine which is able to connect to all the databases we wish to reach. All Perl-DBD-drivers must be installed on this machine. You can also reach databases for which drivers are not available on the machine where you run the program querying the database, e.g. ask MS-Access-database from Linux. .PP Create a configuration file \*(L"proxy_oracle.cfg\*(R" at the dbproxy-server: .PP .Vb 8 \& { \& # This shall run in a shell or a DOS\-window \& # facility => \*(Aqdaemon\*(Aq, \& pidfile => \*(Aqyour_dbiproxy.pid\*(Aq, \& logfile => 1, \& debug => 0, \& mode => \*(Aqsingle\*(Aq, \& localport => \*(Aq12400\*(Aq, \& \& # Access control, the first match in this list wins! \& # So the order is important \& clients => [ \& # hint to organize: \& # the most specialized rules for single machines/users are 1st \& # then the denying rules \& # then the rules about whole networks \& \& # rule: internal_webserver \& # desc: to get statistical information \& { \& # this IP\-address only is meant \& mask => \*(Aq^10\e.95\e.81\e.243$\*(Aq, \& # accept (not defer) connections like this \& accept => 1, \& # only users from this list \& # are allowed to log on \& users => [ \*(Aqinformationdesk\*(Aq ], \& # only this statistical query is allowed \& # to get results for a web\-query \& sql => { \& alive => \*(Aqselect count(*) from dual\*(Aq, \& statistic_area => \*(Aqselect count(*) from e01admin.e01e203 where geb_bezei like ?\*(Aq, \& } \& }, \& \& # rule: internal_bad_guy_1 \& { \& mask => \*(Aq^10\e.95\e.81\e.1$\*(Aq, \& accept => 0, \& }, \& \& # rule: employee_workplace \& # desc: get detailed information \& { \& # any IP\-address is meant here \& mask => \*(Aq^10\e.95\e.81\e.(\ed+)$\*(Aq, \& # accept (not defer) connections like this \& accept => 1, \& # only users from this list \& # are allowed to log on \& users => [ \*(Aqinformationdesk\*(Aq, \*(Aqlippmann\*(Aq ], \& # all these queries are allowed: \& sql => { \& search_city => \*(Aqselect ort_nr, plz, ort from e01admin.e01e200 where plz like ?\*(Aq, \& search_area => \*(Aqselect gebiettyp, geb_bezei from e01admin.e01e203 where geb_bezei like ? or geb_bezei like ?\*(Aq, \& } \& }, \& \& # rule: internal_bad_guy_2 \& # This does NOT work, because rule "employee_workplace" hits \& # with its ip\-address\-mask of the whole network \& { \& # don\*(Aqt accept connection from this ip\-address \& mask => \*(Aq^10\e.95\e.81\e.5$\*(Aq, \& accept => 0, \& } \& ] \& } .Ve .PP Start the proxyserver like this: .PP .Vb 3 \& rem well\-set Oracle_home needed for Oracle \& set ORACLE_HOME=d:\eoracle\eora81 \& dbiproxy \-\-configfile proxy_oracle.cfg .Ve .SS "Testing the connection from a remote machine" .IX Subsection "Testing the connection from a remote machine" Call a program \*(L"dbish\*(R" from your commandline. I take the machine from rule \*(L"internal_webserver\*(R" .PP .Vb 1 \& dbish "dbi:Proxy:hostname=oracle.zdf;port=12400;dsn=dbi:Oracle:e01" informationdesk xxx .Ve .PP There will be a shell-prompt: .PP .Vb 1 \& informationdesk@dbi...> alive \& \& Current statement buffer (enter \*(Aq/\*(Aq...): \& alive \& \& informationdesk@dbi...> / \& COUNT(*) \& \*(Aq1\*(Aq \& [1 rows of 1 fields returned] .Ve .SS "Testing the connection with a perl-script" .IX Subsection "Testing the connection with a perl-script" Create a perl-script like this: .PP .Vb 2 \& # file: oratest.pl \& # call me like this: perl oratest.pl user password \& \& use strict; \& use DBI; \& \& my $user = shift || die "Usage: $0 user password"; \& my $pass = shift || die "Usage: $0 user password"; \& my $config = { \& dsn_at_proxy => "dbi:Oracle:e01", \& proxy => "hostname=oechsle.zdf;port=12400", \& }; \& my $dsn = sprintf "dbi:Proxy:%s;dsn=%s", \& $config\->{proxy}, \& $config\->{dsn_at_proxy}; \& \& my $dbh = DBI\->connect( $dsn, $user, $pass ) \& || die "connect did not work: $DBI::errstr"; \& \& my $sql = "search_city"; \& printf "%s\en%s\en%s\en", "="x40, $sql, "="x40; \& my $cur = $dbh\->prepare($sql); \& $cur\->bind_param(1,\*(Aq905%\*(Aq); \& &show_result ($cur); \& \& my $sql = "search_area"; \& printf "%s\en%s\en%s\en", "="x40, $sql, "="x40; \& my $cur = $dbh\->prepare($sql); \& $cur\->bind_param(1,\*(AqPfarr%\*(Aq); \& $cur\->bind_param(2,\*(AqBronnamberg%\*(Aq); \& &show_result ($cur); \& \& my $sql = "statistic_area"; \& printf "%s\en%s\en%s\en", "="x40, $sql, "="x40; \& my $cur = $dbh\->prepare($sql); \& $cur\->bind_param(1,\*(AqPfarr%\*(Aq); \& &show_result ($cur); \& \& $dbh\->disconnect; \& exit; \& \& \& sub show_result { \& my $cur = shift; \& unless ($cur\->execute()) { \& print "Could not execute\en"; \& return; \& } \& \& my $rownum = 0; \& while (my @row = $cur\->fetchrow_array()) { \& printf "Row is: %s\en", join(", ",@row); \& if ($rownum++ > 5) { \& print "... and so on\en"; \& last; \& } \& } \& $cur\->finish; \& } .Ve .PP The result .PP .Vb 10 \& C:\e>perl oratest.pl informationdesk xxx \& ======================================== \& search_city \& ======================================== \& Row is: 3322, 9050, Chemnitz \& Row is: 3678, 9051, Chemnitz \& Row is: 10447, 9051, Chemnitz \& Row is: 12128, 9051, Chemnitz \& Row is: 10954, 90513, Zirndorf \& Row is: 5808, 90513, Zirndorf \& Row is: 5715, 90513, Zirndorf \& ... and so on \& ======================================== \& search_area \& ======================================== \& Row is: 101, Bronnamberg \& Row is: 400, Pfarramt Zirndorf \& Row is: 400, Pfarramt Rosstal \& Row is: 400, Pfarramt Oberasbach \& Row is: 401, Pfarramt Zirndorf \& Row is: 401, Pfarramt Rosstal \& ======================================== \& statistic_area \& ======================================== \& DBD::Proxy::st execute failed: Server returned error: Failed to execute method CallMethod: Unknown SQL query: statistic_area at E:/Perl/site/lib/DBI/ProxyServer.pm line 258. \& Could not execute .Ve .SS "How the configuration works" .IX Subsection "How the configuration works" The most important section to control access to your dbi-proxy is \*(L"client=>\*(R" in the file \*(L"proxy_oracle.cfg\*(R": .PP Controlling which person at which machine is allowed to access .IP "\(bu" 4 \&\*(L"mask\*(R" is a perl regular expression against the plain ip-address of the machine which wishes to connect _or_ the reverse-lookup from a nameserver. .IP "\(bu" 4 \&\*(L"accept\*(R" tells the dbiproxy-server whether ip-adresse like in \*(L"mask\*(R" are allowed to connect or not (0/1) .IP "\(bu" 4 \&\*(L"users\*(R" is a reference to a list of usernames which must be matched, this is \s-1NOT\s0 a regular expression. .PP Controlling which SQL-statements are allowed .PP You can put every SQL-statement you like in simply omitting \*(L"sql => ...\*(R", but the more important thing is to restrict the connection so that only allowed queries are possible. .PP If you include an sql-section in your config-file like this: .PP .Vb 4 \& sql => { \& alive => \*(Aqselect count(*) from dual\*(Aq, \& statistic_area => \*(Aqselect count(*) from e01admin.e01e203 where geb_bezei like ?\*(Aq, \& } .Ve .PP The user is allowed to put two queries against the dbi-proxy. The queries are _not_ \*(L"select count(*)...\*(R", the queries are \*(L"alive\*(R" and \*(L"statistic_area\*(R"! These keywords are replaced by the real query. So you can run a query for \*(L"alive\*(R": .PP .Vb 3 \& my $sql = "alive"; \& my $cur = $dbh\->prepare($sql); \& ... .Ve .PP The flexibility is that you can put parameters in the where-part of the query so the query are not static. Simply replace a value in the where-part of the query through a question mark and bind it as a parameter to the query. .PP .Vb 5 \& my $sql = "statistic_area"; \& my $cur = $dbh\->prepare($sql); \& $cur\->bind_param(1,\*(Aq905%\*(Aq); \& # A second parameter would be called like this: \& # $cur\->bind_param(2,\*(Aq98%\*(Aq); .Ve .PP The result is this query: .PP .Vb 2 \& select count(*) from e01admin.e01e203 \& where geb_bezei like \*(Aq905%\*(Aq .Ve .PP Don't try to put parameters into the sql-query like this: .PP .Vb 7 \& # Does not work like you think. \& # Only the first word of the query is parsed, \& # so it\*(Aqs changed to "statistic_area", the rest is omitted. \& # You _have_ to work with $cur\->bind_param. \& my $sql = "statistic_area 905%"; \& my $cur = $dbh\->prepare($sql); \& ... .Ve .SS "Problems" .IX Subsection "Problems" .IP "\(bu" 4 I don't know how to restrict users to special databases. .IP "\(bu" 4 I don't know how to pass query-parameters via dbish .SH "SECURITY WARNING" .IX Header "SECURITY WARNING" RPC::PlServer used underneath is not secure due to serializing and deserializing data with Storable module. Use the proxy driver only in trusted environment. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 4 \& Copyright (c) 1997 Jochen Wiedmann \& Am Eisteich 9 \& 72555 Metzingen \& Germany \& \& Email: joe@ispsoft.de \& Phone: +49 7123 14881 .Ve .PP The DBI::ProxyServer module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. In particular permission is granted to Tim Bunce for distributing this as a part of the \s-1DBI.\s0 .SH "SEE ALSO" .IX Header "SEE ALSO" dbiproxy, DBD::Proxy, \s-1DBI\s0, RPC::PlServer, RPC::PlClient, Net::Daemon, Net::Daemon::Log, Sys::Syslog, Win32::EventLog, syslog man/man3/Bundle::DBD::mysql.3pm000044400000004510152462503210011755 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Bundle::DBD::mysql 3" .TH Bundle::DBD::mysql 3 "2019-01-09" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Bundle::DBD::mysql .SH "DESCRIPTION" .IX Header "DESCRIPTION" This package only exists for legacy reasons. Please use the DBD::mysql package instead. man/man3/Path::Class::Dir.3pm000044400000065425152462503210011501 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Path::Class::Dir 3" .TH Path::Class::Dir 3 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Path::Class::Dir \- Objects representing directories .SH "VERSION" .IX Header "VERSION" version 0.37 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Path::Class; # Exports dir() by default \& \& my $dir = dir(\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq); # Path::Class::Dir object \& my $dir = Path::Class::Dir\->new(\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq); # Same thing \& \& # Stringifies to \*(Aqfoo/bar\*(Aq on Unix, \*(Aqfoo\ebar\*(Aq on Windows, etc. \& print "dir: $dir\en"; \& \& if ($dir\->is_absolute) { ... } \& if ($dir\->is_relative) { ... } \& \& my $v = $dir\->volume; # Could be \*(AqC:\*(Aq on Windows, empty string \& # on Unix, \*(AqMacintosh HD:\*(Aq on Mac OS \& \& $dir\->cleanup; # Perform logical cleanup of pathname \& $dir\->resolve; # Perform physical cleanup of pathname \& \& my $file = $dir\->file(\*(Aqfile.txt\*(Aq); # A file in this directory \& my $subdir = $dir\->subdir(\*(Aqgeorge\*(Aq); # A subdirectory \& my $parent = $dir\->parent; # The parent directory, \*(Aqfoo\*(Aq \& \& my $abs = $dir\->absolute; # Transform to absolute path \& my $rel = $abs\->relative; # Transform to relative path \& my $rel = $abs\->relative(\*(Aq/foo\*(Aq); # Relative to /foo \& \& print $dir\->as_foreign(\*(AqMac\*(Aq); # :foo:bar: \& print $dir\->as_foreign(\*(AqWin32\*(Aq); # foo\ebar \& \& # Iterate with IO::Dir methods: \& my $handle = $dir\->open; \& while (my $file = $handle\->read) { \& $file = $dir\->file($file); # Turn into Path::Class::File object \& ... \& } \& \& # Iterate with Path::Class methods: \& while (my $file = $dir\->next) { \& # $file is a Path::Class::File or Path::Class::Dir object \& ... \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`Path::Class::Dir\*(C'\fR class contains functionality for manipulating directory names in a cross-platform way. .SH "METHODS" .IX Header "METHODS" .ie n .IP "$dir = Path::Class::Dir\->new( , , ... )" 4 .el .IP "\f(CW$dir\fR = Path::Class::Dir\->new( , , ... )" 4 .IX Item "$dir = Path::Class::Dir->new( , , ... )" .PD 0 .ie n .IP "$dir = dir( , , ... )" 4 .el .IP "\f(CW$dir\fR = dir( , , ... )" 4 .IX Item "$dir = dir( , , ... )" .PD Creates a new \f(CW\*(C`Path::Class::Dir\*(C'\fR object and returns it. The arguments specify names of directories which will be joined to create a single directory object. A volume may also be specified as the first argument, or as part of the first argument. You can use platform-neutral syntax: .Sp .Vb 1 \& my $dir = dir( \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq ); .Ve .Sp or platform-native syntax: .Sp .Vb 1 \& my $dir = dir( \*(Aqfoo/bar/baz\*(Aq ); .Ve .Sp or a mixture of the two: .Sp .Vb 1 \& my $dir = dir( \*(Aqfoo/bar\*(Aq, \*(Aqbaz\*(Aq ); .Ve .Sp All three of the above examples create relative paths. To create an absolute path, either use the platform native syntax for doing so: .Sp .Vb 1 \& my $dir = dir( \*(Aq/var/tmp\*(Aq ); .Ve .Sp or use an empty string as the first argument: .Sp .Vb 1 \& my $dir = dir( \*(Aq\*(Aq, \*(Aqvar\*(Aq, \*(Aqtmp\*(Aq ); .Ve .Sp If the second form seems awkward, that's somewhat intentional \- paths like \f(CW\*(C`/var/tmp\*(C'\fR or \f(CW\*(C`\eWindows\*(C'\fR aren't cross-platform concepts in the first place (many non-Unix platforms don't have a notion of a \*(L"root directory\*(R"), so they probably shouldn't appear in your code if you're trying to be cross-platform. The first form is perfectly natural, because paths like this may come from config files, user input, or whatever. .Sp As a special case, since it doesn't otherwise mean anything useful and it's convenient to define this way, \f(CW\*(C`Path::Class::Dir\->new()\*(C'\fR (or \&\f(CW\*(C`dir()\*(C'\fR) refers to the current directory (\f(CW\*(C`File::Spec\->curdir\*(C'\fR). To get the current directory as an absolute path, do \f(CW\*(C`dir()\->absolute\*(C'\fR. .Sp Finally, as another special case \f(CW\*(C`dir(undef)\*(C'\fR will return undef, since that's usually an accident on the part of the caller, and returning the root directory would be a nasty surprise just asking for trouble a few lines later. .ie n .IP "$dir\->stringify" 4 .el .IP "\f(CW$dir\fR\->stringify" 4 .IX Item "$dir->stringify" This method is called internally when a \f(CW\*(C`Path::Class::Dir\*(C'\fR object is used in a string context, so the following are equivalent: .Sp .Vb 2 \& $string = $dir\->stringify; \& $string = "$dir"; .Ve .ie n .IP "$dir\->volume" 4 .el .IP "\f(CW$dir\fR\->volume" 4 .IX Item "$dir->volume" Returns the volume (e.g. \f(CW\*(C`C:\*(C'\fR on Windows, \f(CW\*(C`Macintosh HD:\*(C'\fR on Mac \s-1OS,\s0 etc.) of the directory object, if any. Otherwise, returns the empty string. .ie n .IP "$dir\->basename" 4 .el .IP "\f(CW$dir\fR\->basename" 4 .IX Item "$dir->basename" Returns the last directory name of the path as a string. .ie n .IP "$dir\->is_dir" 4 .el .IP "\f(CW$dir\fR\->is_dir" 4 .IX Item "$dir->is_dir" Returns a boolean value indicating whether this object represents a directory. Not surprisingly, Path::Class::File objects always return false, and \f(CW\*(C`Path::Class::Dir\*(C'\fR objects always return true. .ie n .IP "$dir\->is_absolute" 4 .el .IP "\f(CW$dir\fR\->is_absolute" 4 .IX Item "$dir->is_absolute" Returns true or false depending on whether the directory refers to an absolute path specifier (like \f(CW\*(C`/usr/local\*(C'\fR or \f(CW\*(C`\eWindows\*(C'\fR). .ie n .IP "$dir\->is_relative" 4 .el .IP "\f(CW$dir\fR\->is_relative" 4 .IX Item "$dir->is_relative" Returns true or false depending on whether the directory refers to a relative path specifier (like \f(CW\*(C`lib/foo\*(C'\fR or \f(CW\*(C`./dir\*(C'\fR). .ie n .IP "$dir\->cleanup" 4 .el .IP "\f(CW$dir\fR\->cleanup" 4 .IX Item "$dir->cleanup" Performs a logical cleanup of the file path. For instance: .Sp .Vb 2 \& my $dir = dir(\*(Aq/foo//baz/./foo\*(Aq)\->cleanup; \& # $dir now represents \*(Aq/foo/baz/foo\*(Aq; .Ve .ie n .IP "$dir\->resolve" 4 .el .IP "\f(CW$dir\fR\->resolve" 4 .IX Item "$dir->resolve" Performs a physical cleanup of the file path. For instance: .Sp .Vb 2 \& my $dir = dir(\*(Aq/foo//baz/../foo\*(Aq)\->resolve; \& # $dir now represents \*(Aq/foo/foo\*(Aq, assuming no symlinks .Ve .Sp This actually consults the filesystem to verify the validity of the path. .ie n .IP "$file = $dir\->file( , , ..., )" 4 .el .IP "\f(CW$file\fR = \f(CW$dir\fR\->file( , , ..., )" 4 .IX Item "$file = $dir->file( , , ..., )" Returns a Path::Class::File object representing an entry in \f(CW$dir\fR or one of its subdirectories. Internally, this just calls \f(CW\*(C`Path::Class::File\->new( @_ )\*(C'\fR. .ie n .IP "$subdir = $dir\->subdir( , , ... )" 4 .el .IP "\f(CW$subdir\fR = \f(CW$dir\fR\->subdir( , , ... )" 4 .IX Item "$subdir = $dir->subdir( , , ... )" Returns a new \f(CW\*(C`Path::Class::Dir\*(C'\fR object representing a subdirectory of \f(CW$dir\fR. .ie n .IP "$parent = $dir\->parent" 4 .el .IP "\f(CW$parent\fR = \f(CW$dir\fR\->parent" 4 .IX Item "$parent = $dir->parent" Returns the parent directory of \f(CW$dir\fR. Note that this is the \&\fIlogical\fR parent, not necessarily the physical parent. It really means we just chop off entries from the end of the directory list until we cain't chop no more. If the directory is relative, we start using the relative forms of parent directories. .Sp The following code demonstrates the behavior on absolute and relative directories: .Sp .Vb 5 \& $dir = dir(\*(Aq/foo/bar\*(Aq); \& for (1..6) { \& print "Absolute: $dir\en"; \& $dir = $dir\->parent; \& } \& \& $dir = dir(\*(Aqfoo/bar\*(Aq); \& for (1..6) { \& print "Relative: $dir\en"; \& $dir = $dir\->parent; \& } \& \& ########### Output on Unix ################ \& Absolute: /foo/bar \& Absolute: /foo \& Absolute: / \& Absolute: / \& Absolute: / \& Absolute: / \& Relative: foo/bar \& Relative: foo \& Relative: . \& Relative: .. \& Relative: ../.. \& Relative: ../../.. .Ve .ie n .IP "@list = $dir\->children" 4 .el .IP "\f(CW@list\fR = \f(CW$dir\fR\->children" 4 .IX Item "@list = $dir->children" Returns a list of Path::Class::File and/or \f(CW\*(C`Path::Class::Dir\*(C'\fR objects listed in this directory, or in scalar context the number of such objects. Obviously, it is necessary for \f(CW$dir\fR to exist and be readable in order to find its children. .Sp Note that the children are returned as subdirectories of \f(CW$dir\fR, i.e. the children of \fIfoo\fR will be \fIfoo/bar\fR and \fIfoo/baz\fR, not \&\fIbar\fR and \fIbaz\fR. .Sp Ordinarily \f(CW\*(C`children()\*(C'\fR will not include the \fIself\fR and \fIparent\fR entries \f(CW\*(C`.\*(C'\fR and \f(CW\*(C`..\*(C'\fR (or their equivalents on non-Unix systems), because that's like I'm-my-own-grandpa business. If you do want all directory entries including these special ones, pass a true value for the \f(CW\*(C`all\*(C'\fR parameter: .Sp .Vb 2 \& @c = $dir\->children(); # Just the children \& @c = $dir\->children(all => 1); # All entries .Ve .Sp In addition, there's a \f(CW\*(C`no_hidden\*(C'\fR parameter that will exclude all normally \*(L"hidden\*(R" entries \- on Unix this means excluding all entries that begin with a dot (\f(CW\*(C`.\*(C'\fR): .Sp .Vb 1 \& @c = $dir\->children(no_hidden => 1); # Just normally\-visible entries .Ve .ie n .IP "$abs = $dir\->absolute" 4 .el .IP "\f(CW$abs\fR = \f(CW$dir\fR\->absolute" 4 .IX Item "$abs = $dir->absolute" Returns a \f(CW\*(C`Path::Class::Dir\*(C'\fR object representing \f(CW$dir\fR as an absolute path. An optional argument, given as either a string or a \&\f(CW\*(C`Path::Class::Dir\*(C'\fR object, specifies the directory to use as the base of relativity \- otherwise the current working directory will be used. .ie n .IP "$rel = $dir\->relative" 4 .el .IP "\f(CW$rel\fR = \f(CW$dir\fR\->relative" 4 .IX Item "$rel = $dir->relative" Returns a \f(CW\*(C`Path::Class::Dir\*(C'\fR object representing \f(CW$dir\fR as a relative path. An optional argument, given as either a string or a \&\f(CW\*(C`Path::Class::Dir\*(C'\fR object, specifies the directory to use as the base of relativity \- otherwise the current working directory will be used. .ie n .IP "$boolean = $dir\->subsumes($other)" 4 .el .IP "\f(CW$boolean\fR = \f(CW$dir\fR\->subsumes($other)" 4 .IX Item "$boolean = $dir->subsumes($other)" Returns true if this directory spec subsumes the other spec, and false otherwise. Think of \*(L"subsumes\*(R" as \*(L"contains\*(R", but we only look at the \&\fIspecs\fR, not whether \f(CW$dir\fR actually contains \f(CW$other\fR on the filesystem. .Sp The \f(CW$other\fR argument may be a \f(CW\*(C`Path::Class::Dir\*(C'\fR object, a Path::Class::File object, or a string. In the latter case, we assume it's a directory. .Sp .Vb 7 \& # Examples: \& dir(\*(Aqfoo/bar\*(Aq )\->subsumes(dir(\*(Aqfoo/bar/baz\*(Aq)) # True \& dir(\*(Aq/foo/bar\*(Aq)\->subsumes(dir(\*(Aq/foo/bar/baz\*(Aq)) # True \& dir(\*(Aqfoo/..\*(Aq)\->subsumes(dir(\*(Aqfoo/../bar)) # True \& dir(\*(Aqfoo/bar\*(Aq )\->subsumes(dir(\*(Aqbar/baz\*(Aq)) # False \& dir(\*(Aq/foo/bar\*(Aq)\->subsumes(dir(\*(Aqfoo/bar\*(Aq)) # False \& dir(\*(Aqfoo/..\*(Aq)\->subsumes(dir(\*(Aqbar\*(Aq)) # False! Use C to resolve ".." .Ve .ie n .IP "$boolean = $dir\->contains($other)" 4 .el .IP "\f(CW$boolean\fR = \f(CW$dir\fR\->contains($other)" 4 .IX Item "$boolean = $dir->contains($other)" Returns true if this directory actually contains \f(CW$other\fR on the filesystem. \f(CW$other\fR doesn't have to be a direct child of \f(CW$dir\fR, it just has to be subsumed after both paths have been resolved. .ie n .IP "$foreign = $dir\->as_foreign($type)" 4 .el .IP "\f(CW$foreign\fR = \f(CW$dir\fR\->as_foreign($type)" 4 .IX Item "$foreign = $dir->as_foreign($type)" Returns a \f(CW\*(C`Path::Class::Dir\*(C'\fR object representing \f(CW$dir\fR as it would be specified on a system of type \f(CW$type\fR. Known types include \&\f(CW\*(C`Unix\*(C'\fR, \f(CW\*(C`Win32\*(C'\fR, \f(CW\*(C`Mac\*(C'\fR, \f(CW\*(C`VMS\*(C'\fR, and \f(CW\*(C`OS2\*(C'\fR, i.e. anything for which there is a subclass of \f(CW\*(C`File::Spec\*(C'\fR. .Sp Any generated objects (subdirectories, files, parents, etc.) will also retain this type. .ie n .IP "$foreign = Path::Class::Dir\->new_foreign($type, @args)" 4 .el .IP "\f(CW$foreign\fR = Path::Class::Dir\->new_foreign($type, \f(CW@args\fR)" 4 .IX Item "$foreign = Path::Class::Dir->new_foreign($type, @args)" Returns a \f(CW\*(C`Path::Class::Dir\*(C'\fR object representing \f(CW$dir\fR as it would be specified on a system of type \f(CW$type\fR. Known types include \&\f(CW\*(C`Unix\*(C'\fR, \f(CW\*(C`Win32\*(C'\fR, \f(CW\*(C`Mac\*(C'\fR, \f(CW\*(C`VMS\*(C'\fR, and \f(CW\*(C`OS2\*(C'\fR, i.e. anything for which there is a subclass of \f(CW\*(C`File::Spec\*(C'\fR. .Sp The arguments in \f(CW@args\fR are the same as they would be specified in \&\f(CW\*(C`new()\*(C'\fR. .ie n .IP "@list = $dir\->dir_list([\s-1OFFSET,\s0 [\s-1LENGTH\s0]])" 4 .el .IP "\f(CW@list\fR = \f(CW$dir\fR\->dir_list([\s-1OFFSET,\s0 [\s-1LENGTH\s0]])" 4 .IX Item "@list = $dir->dir_list([OFFSET, [LENGTH]])" Returns the list of strings internally representing this directory structure. Each successive member of the list is understood to be an entry in its predecessor's directory list. By contract, \f(CW\*(C`Path::Class\->new( $dir\->dir_list )\*(C'\fR should be equivalent to \f(CW$dir\fR. .Sp The semantics of this method are similar to Perl's \f(CW\*(C`splice\*(C'\fR or \&\f(CW\*(C`substr\*(C'\fR functions; they return \f(CW\*(C`LENGTH\*(C'\fR elements starting at \&\f(CW\*(C`OFFSET\*(C'\fR. If \f(CW\*(C`LENGTH\*(C'\fR is omitted, returns all the elements starting at \f(CW\*(C`OFFSET\*(C'\fR up to the end of the list. If \f(CW\*(C`LENGTH\*(C'\fR is negative, returns the elements from \f(CW\*(C`OFFSET\*(C'\fR onward except for \f(CW\*(C`\-LENGTH\*(C'\fR elements at the end. If \f(CW\*(C`OFFSET\*(C'\fR is negative, it counts backward \&\f(CW\*(C`OFFSET\*(C'\fR elements from the end of the list. If \f(CW\*(C`OFFSET\*(C'\fR and \&\f(CW\*(C`LENGTH\*(C'\fR are both omitted, the entire list is returned. .Sp In a scalar context, \f(CW\*(C`dir_list()\*(C'\fR with no arguments returns the number of entries in the directory list; \f(CW\*(C`dir_list(OFFSET)\*(C'\fR returns the single element at that offset; \f(CW\*(C`dir_list(OFFSET, LENGTH)\*(C'\fR returns the final element that would have been returned in a list context. .ie n .IP "$dir\->components" 4 .el .IP "\f(CW$dir\fR\->components" 4 .IX Item "$dir->components" Identical to \f(CW\*(C`dir_list()\*(C'\fR. It exists because there's an analogous method \f(CW\*(C`dir_list()\*(C'\fR in the \f(CW\*(C`Path::Class::File\*(C'\fR class that also returns the basename string, so this method lets someone call \&\f(CW\*(C`components()\*(C'\fR without caring whether the object is a file or a directory. .ie n .IP "$fh = $dir\->\fBopen()\fR" 4 .el .IP "\f(CW$fh\fR = \f(CW$dir\fR\->\fBopen()\fR" 4 .IX Item "$fh = $dir->open()" Passes \f(CW$dir\fR to \f(CW\*(C`IO::Dir\->open\*(C'\fR and returns the result as an IO::Dir object. If the opening fails, \f(CW\*(C`undef\*(C'\fR is returned and \&\f(CW$!\fR is set. .ie n .IP "$dir\->mkpath($verbose, $mode)" 4 .el .IP "\f(CW$dir\fR\->mkpath($verbose, \f(CW$mode\fR)" 4 .IX Item "$dir->mkpath($verbose, $mode)" Passes all arguments, including \f(CW$dir\fR, to \f(CW\*(C`File::Path::mkpath()\*(C'\fR and returns the result (a list of all directories created). .ie n .IP "$dir\->rmtree($verbose, $cautious)" 4 .el .IP "\f(CW$dir\fR\->rmtree($verbose, \f(CW$cautious\fR)" 4 .IX Item "$dir->rmtree($verbose, $cautious)" Passes all arguments, including \f(CW$dir\fR, to \f(CW\*(C`File::Path::rmtree()\*(C'\fR and returns the result (the number of files successfully deleted). .ie n .IP "$dir\->\fBremove()\fR" 4 .el .IP "\f(CW$dir\fR\->\fBremove()\fR" 4 .IX Item "$dir->remove()" Removes the directory, which must be empty. Returns a boolean value indicating whether or not the directory was successfully removed. This method is mainly provided for consistency with \&\f(CW\*(C`Path::Class::File\*(C'\fR's \f(CW\*(C`remove()\*(C'\fR method. .ie n .IP "$dir\->tempfile(...)" 4 .el .IP "\f(CW$dir\fR\->tempfile(...)" 4 .IX Item "$dir->tempfile(...)" An interface to File::Temp's \f(CW\*(C`tempfile()\*(C'\fR function. Just like that function, if you call this in a scalar context, the return value is the filehandle and the file is \f(CW\*(C`unlink\*(C'\fRed as soon as possible (which is immediately on Unix-like platforms). If called in a list context, the return values are the filehandle and the filename. .Sp The given directory is passed as the \f(CW\*(C`DIR\*(C'\fR parameter. .Sp Here's an example of pretty good usage which doesn't allow race conditions, won't leave yucky tempfiles around on your filesystem, etc.: .Sp .Vb 4 \& my $fh = $dir\->tempfile; \& print $fh "Here\*(Aqs some data...\en"; \& seek($fh, 0, 0); \& while (<$fh>) { do something... } .Ve .Sp Or in combination with a \f(CW\*(C`fork\*(C'\fR: .Sp .Vb 8 \& my $fh = $dir\->tempfile; \& print $fh "Here\*(Aqs some more data...\en"; \& seek($fh, 0, 0); \& if ($pid=fork()) { \& wait; \& } else { \& something($_) while <$fh>; \& } .Ve .ie n .IP "$dir_or_file = $dir\->\fBnext()\fR" 4 .el .IP "\f(CW$dir_or_file\fR = \f(CW$dir\fR\->\fBnext()\fR" 4 .IX Item "$dir_or_file = $dir->next()" A convenient way to iterate through directory contents. The first time \f(CW\*(C`next()\*(C'\fR is called, it will \f(CW\*(C`open()\*(C'\fR the directory and read the first item from it, returning the result as a \f(CW\*(C`Path::Class::Dir\*(C'\fR or Path::Class::File object (depending, of course, on its actual type). Each subsequent call to \f(CW\*(C`next()\*(C'\fR will simply iterate over the directory's contents, until there are no more items in the directory, and then the undefined value is returned. For example, to iterate over all the regular files in a directory: .Sp .Vb 5 \& while (my $file = $dir\->next) { \& next unless \-f $file; \& my $fh = $file\->open(\*(Aqr\*(Aq) or die "Can\*(Aqt read $file: $!"; \& ... \& } .Ve .Sp If an error occurs when opening the directory (for instance, it doesn't exist or isn't readable), \f(CW\*(C`next()\*(C'\fR will throw an exception with the value of \f(CW$!\fR. .ie n .IP "$dir\->traverse( sub { ... }, @args )" 4 .el .IP "\f(CW$dir\fR\->traverse( sub { ... }, \f(CW@args\fR )" 4 .IX Item "$dir->traverse( sub { ... }, @args )" Calls the given callback for the root, passing it a continuation function which, when called, will call this recursively on each of its children. The callback function should be of the form: .Sp .Vb 4 \& sub { \& my ($child, $cont, @args) = @_; \& # ... \& } .Ve .Sp For instance, to calculate the number of files in a directory, you can do this: .Sp .Vb 4 \& my $nfiles = $dir\->traverse(sub { \& my ($child, $cont) = @_; \& return sum($cont\->(), ($child\->is_dir ? 0 : 1)); \& }); .Ve .Sp or to calculate the maximum depth of a directory: .Sp .Vb 4 \& my $depth = $dir\->traverse(sub { \& my ($child, $cont, $depth) = @_; \& return max($cont\->($depth + 1), $depth); \& }, 0); .Ve .Sp You can also choose not to call the callback in certain situations: .Sp .Vb 6 \& $dir\->traverse(sub { \& my ($child, $cont) = @_; \& return if \-l $child; # don\*(Aqt follow symlinks \& # do something with $child \& return $cont\->(); \& }); .Ve .ie n .IP "$dir\->traverse_if( sub { ... }, sub { ... }, @args )" 4 .el .IP "\f(CW$dir\fR\->traverse_if( sub { ... }, sub { ... }, \f(CW@args\fR )" 4 .IX Item "$dir->traverse_if( sub { ... }, sub { ... }, @args )" traverse with additional \*(L"should I visit this child\*(R" callback. Particularly useful in case examined tree contains inaccessible directories. .Sp Canonical example: .Sp .Vb 11 \& $dir\->traverse_if( \& sub { \& my ($child, $cont) = @_; \& # do something with $child \& return $cont\->(); \& }, \& sub { \& my ($child) = @_; \& # Process only readable items \& return \-r $child; \& }); .Ve .Sp Second callback gets single parameter: child. Only children for which it returns true will be processed by the first callback. .Sp Remaining parameters are interpreted as in traverse, in particular \&\f(CW\*(C`traverse_if(callback, sub { 1 }, @args\*(C'\fR is equivalent to \&\f(CW\*(C`traverse(callback, @args)\*(C'\fR. .ie n .IP "$dir\->recurse( callback => sub {...} )" 4 .el .IP "\f(CW$dir\fR\->recurse( callback => sub {...} )" 4 .IX Item "$dir->recurse( callback => sub {...} )" Iterates through this directory and all of its children, and all of its children's children, etc., calling the \f(CW\*(C`callback\*(C'\fR subroutine for each entry. This is a lot like what the File::Find module does, and of course \f(CW\*(C`File::Find\*(C'\fR will work fine on Path::Class objects, but the advantage of the \f(CW\*(C`recurse()\*(C'\fR method is that it will also feed your callback routine \f(CW\*(C`Path::Class\*(C'\fR objects rather than just pathname strings. .Sp The \f(CW\*(C`recurse()\*(C'\fR method requires a \f(CW\*(C`callback\*(C'\fR parameter specifying the subroutine to invoke for each entry. It will be passed the \&\f(CW\*(C`Path::Class\*(C'\fR object as its first argument. .Sp \&\f(CW\*(C`recurse()\*(C'\fR also accepts two boolean parameters, \f(CW\*(C`depthfirst\*(C'\fR and \&\f(CW\*(C`preorder\*(C'\fR that control the order of recursion. The default is a preorder, breadth-first search, i.e. \f(CW\*(C`depthfirst => 0, preorder => 1\*(C'\fR. At the time of this writing, all combinations of these two parameters are supported \fIexcept\fR \f(CW\*(C`depthfirst => 0, preorder => 0\*(C'\fR. .Sp \&\f(CW\*(C`callback\*(C'\fR is normally not required to return any value. If it returns special constant \f(CW\*(C`Path::Class::Entity::PRUNE()\*(C'\fR (more easily available as \f(CW\*(C`$item\->PRUNE\*(C'\fR), no children of analyzed item will be analyzed (mostly as if you set \f(CW\*(C`$File::Find::prune=1\*(C'\fR). Of course pruning is available only in \f(CW\*(C`preorder\*(C'\fR, in postorder return value has no effect. .ie n .IP "$st = $file\->\fBstat()\fR" 4 .el .IP "\f(CW$st\fR = \f(CW$file\fR\->\fBstat()\fR" 4 .IX Item "$st = $file->stat()" Invokes \f(CW\*(C`File::stat::stat()\*(C'\fR on this directory and returns a \&\f(CW\*(C`File::stat\*(C'\fR object representing the result. .ie n .IP "$st = $file\->\fBlstat()\fR" 4 .el .IP "\f(CW$st\fR = \f(CW$file\fR\->\fBlstat()\fR" 4 .IX Item "$st = $file->lstat()" Same as \f(CW\*(C`stat()\*(C'\fR, but if \f(CW$file\fR is a symbolic link, \f(CW\*(C`lstat()\*(C'\fR stats the link instead of the directory the link points to. .ie n .IP "$class = $file\->\fBfile_class()\fR" 4 .el .IP "\f(CW$class\fR = \f(CW$file\fR\->\fBfile_class()\fR" 4 .IX Item "$class = $file->file_class()" Returns the class which should be used to create file objects. .Sp Generally overridden whenever this class is subclassed. .SH "AUTHOR" .IX Header "AUTHOR" Ken Williams, kwilliams@cpan.org .SH "SEE ALSO" .IX Header "SEE ALSO" Path::Class, Path::Class::File, File::Spec man/man3/LWP::Debug.3pm000044400000007550152462503210010400 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::Debug 3" .TH LWP::Debug 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::Debug \- deprecated .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module has been deprecated. Please see LWP::ConsoleLogger for your debugging needs. .PP LWP::Debug is used to provide tracing facilities, but these are not used by \s-1LWP\s0 any more. The code in this module is kept around (undocumented) so that 3rd party code that happens to use the old interfaces continue to run. .PP One useful feature that LWP::Debug provided (in an imprecise and troublesome way) was network traffic monitoring. The following section provides some hints about recommended replacements. .SS "Network traffic monitoring" .IX Subsection "Network traffic monitoring" The best way to monitor the network traffic that \s-1LWP\s0 generates is to use an external \s-1TCP\s0 monitoring program. The WireShark program is highly recommended for this. .PP Another approach it to use a debugging \s-1HTTP\s0 proxy server and make \&\s-1LWP\s0 direct all its traffic via this one. Call \f(CW\*(C`$ua\->proxy\*(C'\fR to set it up and then just use \s-1LWP\s0 as before. .PP For less precise monitoring needs just setting up a few simple handlers might do. The following example sets up handlers to dump the request and response objects that pass through \s-1LWP:\s0 .PP .Vb 3 \& use LWP::UserAgent; \& $ua = LWP::UserAgent\->new; \& $ua\->default_header(\*(AqAccept\-Encoding\*(Aq => scalar HTTP::Message::decodable()); \& \& $ua\->add_handler("request_send", sub { shift\->dump; return }); \& $ua\->add_handler("response_done", sub { shift\->dump; return }); \& \& $ua\->get("http://www.example.com"); .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" LWP::ConsoleLogger, LWP::ConsoleLogger::Everywhere, LWP::UserAgent man/man3/DBI::Util::CacheMemory.3pm000044400000006557152462503210012532 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Util::CacheMemory 3" .TH DBI::Util::CacheMemory 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Util::CacheMemory \- a very fast but very minimal subset of Cache::Memory .SH "DESCRIPTION" .IX Header "DESCRIPTION" Like Cache::Memory (part of the Cache distribution) but doesn't support any fancy features. .PP This module aims to be a very fast compatible strict sub-set for simple cases, such as basic client-side caching for DBD::Gofer. .PP Like Cache::Memory, and other caches in the Cache and Cache::Cache distributions, the data will remain in the cache until cleared, it expires, or the process dies. The cache object simply going out of scope will \fInot\fR destroy the data. .SH "METHODS WITH CHANGES" .IX Header "METHODS WITH CHANGES" .SS "new" .IX Subsection "new" All options except \f(CW\*(C`namespace\*(C'\fR are ignored. .SS "set" .IX Subsection "set" Doesn't support expiry. .SS "purge" .IX Subsection "purge" Same as \fBclear()\fR \- deletes everything in the namespace. .SH "METHODS WITHOUT CHANGES" .IX Header "METHODS WITHOUT CHANGES" .IP "clear" 4 .IX Item "clear" .PD 0 .IP "count" 4 .IX Item "count" .IP "exists" 4 .IX Item "exists" .IP "remove" 4 .IX Item "remove" .PD .SH "UNSUPPORTED METHODS" .IX Header "UNSUPPORTED METHODS" If it's not listed above, it's not supported. man/man3/DBI::Const::GetInfoReturn.3pm000044400000004724152462503210013234 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Const::GetInfoReturn 3" .TH DBI::Const::GetInfoReturn 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Const::GetInfoReturn \- Data and functions for describing GetInfo results .SH "SYNOPSIS" .IX Header "SYNOPSIS" The interface to this module is undocumented and liable to change. .SH "DESCRIPTION" .IX Header "DESCRIPTION" Data and functions for describing GetInfo results man/man3/libwww::lwptut.3pm000044400000072552152462503210011566 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "lwptut 3" .TH lwptut 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" lwptut \-\- An LWP Tutorial .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1LWP\s0 (short for \*(L"Library for \s-1WWW\s0 in Perl\*(R") is a very popular group of Perl modules for accessing data on the Web. Like most Perl module-distributions, each of \s-1LWP\s0's component modules comes with documentation that is a complete reference to its interface. However, there are so many modules in \s-1LWP\s0 that it's hard to know where to start looking for information on how to do even the simplest most common things. .PP Really introducing you to using \s-1LWP\s0 would require a whole book \*(-- a book that just happens to exist, called \fIPerl & \s-1LWP\s0\fR. But this article should give you a taste of how you can go about some common tasks with \&\s-1LWP.\s0 .SS "Getting documents with LWP::Simple" .IX Subsection "Getting documents with LWP::Simple" If you just want to get what's at a particular \s-1URL,\s0 the simplest way to do it is LWP::Simple's functions. .PP In a Perl program, you can call its \f(CW\*(C`get($url)\*(C'\fR function. It will try getting that \s-1URL\s0's content. If it works, then it'll return the content; but if there's some error, it'll return undef. .PP .Vb 2 \& my $url = \*(Aqhttp://www.npr.org/programs/fa/?todayDate=current\*(Aq; \& # Just an example: the URL for the most recent /Fresh Air/ show \& \& use LWP::Simple; \& my $content = get $url; \& die "Couldn\*(Aqt get $url" unless defined $content; \& \& # Then go do things with $content, like this: \& \& if($content =~ m/jazz/i) { \& print "They\*(Aqre talking about jazz today on Fresh Air!\en"; \& } \& else { \& print "Fresh Air is apparently jazzless today.\en"; \& } .Ve .PP The handiest variant on \f(CW\*(C`get\*(C'\fR is \f(CW\*(C`getprint\*(C'\fR, which is useful in Perl one-liners. If it can get the page whose \s-1URL\s0 you provide, it sends it to \s-1STDOUT\s0; otherwise it complains to \s-1STDERR.\s0 .PP .Vb 1 \& % perl \-MLWP::Simple \-e "getprint \*(Aqhttp://www.cpan.org/RECENT\*(Aq" .Ve .PP That is the \s-1URL\s0 of a plain text file that lists new files in \s-1CPAN\s0 in the past two weeks. You can easily make it part of a tidy little shell command, like this one that mails you the list of new \&\f(CW\*(C`Acme::\*(C'\fR modules: .PP .Vb 2 \& % perl \-MLWP::Simple \-e "getprint \*(Aqhttp://www.cpan.org/RECENT\*(Aq" \e \& | grep "/by\-module/Acme" | mail \-s "New Acme modules! Joy!" $USER .Ve .PP There are other useful functions in LWP::Simple, including one function for running a \s-1HEAD\s0 request on a \s-1URL\s0 (useful for checking links, or getting the last-revised time of a \s-1URL\s0), and two functions for saving/mirroring a \s-1URL\s0 to a local file. See the LWP::Simple documentation for the full details, or chapter 2 of \fIPerl & \s-1LWP\s0\fR for more examples. .SS "The Basics of the \s-1LWP\s0 Class Model" .IX Subsection "The Basics of the LWP Class Model" LWP::Simple's functions are handy for simple cases, but its functions don't support cookies or authorization, don't support setting header lines in the \s-1HTTP\s0 request, generally don't support reading header lines in the \s-1HTTP\s0 response (notably the full \s-1HTTP\s0 error message, in case of an error). To get at all those features, you'll have to use the full \s-1LWP\s0 class model. .PP While \s-1LWP\s0 consists of dozens of classes, the main two that you have to understand are LWP::UserAgent and HTTP::Response. LWP::UserAgent is a class for \*(L"virtual browsers\*(R" which you use for performing requests, and HTTP::Response is a class for the responses (or error messages) that you get back from those requests. .PP The basic idiom is \f(CW\*(C`$response = $browser\->get($url)\*(C'\fR, or more fully illustrated: .PP .Vb 1 \& # Early in your program: \& \& use LWP 5.64; # Loads all important LWP classes, and makes \& # sure your version is reasonably recent. \& \& my $browser = LWP::UserAgent\->new; \& \& ... \& \& # Then later, whenever you need to make a get request: \& my $url = \*(Aqhttp://www.npr.org/programs/fa/?todayDate=current\*(Aq; \& \& my $response = $browser\->get( $url ); \& die "Can\*(Aqt get $url \-\- ", $response\->status_line \& unless $response\->is_success; \& \& die "Hey, I was expecting HTML, not ", $response\->content_type \& unless $response\->content_type eq \*(Aqtext/html\*(Aq; \& # or whatever content\-type you\*(Aqre equipped to deal with \& \& # Otherwise, process the content somehow: \& \& if($response\->decoded_content =~ m/jazz/i) { \& print "They\*(Aqre talking about jazz today on Fresh Air!\en"; \& } \& else { \& print "Fresh Air is apparently jazzless today.\en"; \& } .Ve .PP There are two objects involved: \f(CW$browser\fR, which holds an object of class LWP::UserAgent, and then the \f(CW$response\fR object, which is of class HTTP::Response. You really need only one browser object per program; but every time you make a request, you get back a new HTTP::Response object, which will have some interesting attributes: .IP "\(bu" 4 A status code indicating success or failure (which you can test with \f(CW\*(C`$response\->is_success\*(C'\fR). .IP "\(bu" 4 An \s-1HTTP\s0 status line that is hopefully informative if there's failure (which you can see with \f(CW\*(C`$response\->status_line\*(C'\fR, returning something like \*(L"404 Not Found\*(R"). .IP "\(bu" 4 A \s-1MIME\s0 content-type like \*(L"text/html\*(R", \*(L"image/gif\*(R", \&\*(L"application/xml\*(R", etc., which you can see with \&\f(CW\*(C`$response\->content_type\*(C'\fR .IP "\(bu" 4 The actual content of the response, in \f(CW\*(C`$response\->decoded_content\*(C'\fR. If the response is \s-1HTML,\s0 that's where the \s-1HTML\s0 source will be; if it's a \s-1GIF,\s0 then \f(CW\*(C`$response\->decoded_content\*(C'\fR will be the binary \&\s-1GIF\s0 data. .IP "\(bu" 4 And dozens of other convenient and more specific methods that are documented in the docs for HTTP::Response, and its superclasses HTTP::Message and HTTP::Headers. .SS "Adding Other \s-1HTTP\s0 Request Headers" .IX Subsection "Adding Other HTTP Request Headers" The most commonly used syntax for requests is \f(CW\*(C`$response = $browser\->get($url)\*(C'\fR, but in truth, you can add extra \s-1HTTP\s0 header lines to the request by adding a list of key-value pairs after the \s-1URL,\s0 like so: .PP .Vb 1 \& $response = $browser\->get( $url, $key1, $value1, $key2, $value2, ... ); .Ve .PP For example, here's how to send some commonly used headers, in case you're dealing with a site that would otherwise reject your request: .PP .Vb 6 \& my @ns_headers = ( \& \*(AqUser\-Agent\*(Aq => \*(AqMozilla/4.76 [en] (Win98; U)\*(Aq, \& \*(AqAccept\*(Aq => \*(Aqimage/gif, image/x\-xbitmap, image/jpeg, image/pjpeg, image/png, */*\*(Aq, \& \*(AqAccept\-Charset\*(Aq => \*(Aqiso\-8859\-1,*,utf\-8\*(Aq, \& \*(AqAccept\-Language\*(Aq => \*(Aqen\-US\*(Aq, \& ); \& \& ... \& \& $response = $browser\->get($url, @ns_headers); .Ve .PP If you weren't reusing that array, you could just go ahead and do this: .PP .Vb 6 \& $response = $browser\->get($url, \& \*(AqUser\-Agent\*(Aq => \*(AqMozilla/4.76 [en] (Win98; U)\*(Aq, \& \*(AqAccept\*(Aq => \*(Aqimage/gif, image/x\-xbitmap, image/jpeg, image/pjpeg, image/png, */*\*(Aq, \& \*(AqAccept\-Charset\*(Aq => \*(Aqiso\-8859\-1,*,utf\-8\*(Aq, \& \*(AqAccept\-Language\*(Aq => \*(Aqen\-US\*(Aq, \& ); .Ve .PP If you were only ever changing the 'User\-Agent' line, you could just change the \f(CW$browser\fR object's default line from \*(L"libwww\-perl/5.65\*(R" (or the like) to whatever you like, using the LWP::UserAgent \f(CW\*(C`agent\*(C'\fR method: .PP .Vb 1 \& $browser\->agent(\*(AqMozilla/4.76 [en] (Win98; U)\*(Aq); .Ve .SS "Enabling Cookies" .IX Subsection "Enabling Cookies" A default LWP::UserAgent object acts like a browser with its cookies support turned off. There are various ways of turning it on, by setting its \f(CW\*(C`cookie_jar\*(C'\fR attribute. A \*(L"cookie jar\*(R" is an object representing a little database of all the \s-1HTTP\s0 cookies that a browser knows about. It can correspond to a file on disk or an in-memory object that starts out empty, and whose collection of cookies will disappear once the program is finished running. .PP To give a browser an in-memory empty cookie jar, you set its \f(CW\*(C`cookie_jar\*(C'\fR attribute like so: .PP .Vb 2 \& use HTTP::CookieJar::LWP; \& $browser\->cookie_jar( HTTP::CookieJar::LWP\->new ); .Ve .PP To save a cookie jar to disk, see \*(L"dump_cookies\*(R" in HTTP::CookieJar. To load cookies from disk into a jar, see \*(L"load_cookies\*(R" in HTTP::CookieJar. .SS "Posting Form Data" .IX Subsection "Posting Form Data" Many \s-1HTML\s0 forms send data to their server using an \s-1HTTP POST\s0 request, which you can send with this syntax: .PP .Vb 7 \& $response = $browser\->post( $url, \& [ \& formkey1 => value1, \& formkey2 => value2, \& ... \& ], \& ); .Ve .PP Or if you need to send \s-1HTTP\s0 headers: .PP .Vb 9 \& $response = $browser\->post( $url, \& [ \& formkey1 => value1, \& formkey2 => value2, \& ... \& ], \& headerkey1 => value1, \& headerkey2 => value2, \& ); .Ve .PP For example, the following program makes a search request to AltaVista (by sending some form data via an \s-1HTTP POST\s0 request), and extracts from the \s-1HTML\s0 the report of the number of matches: .PP .Vb 4 \& use strict; \& use warnings; \& use LWP 5.64; \& my $browser = LWP::UserAgent\->new; \& \& my $word = \*(Aqtarragon\*(Aq; \& \& my $url = \*(Aqhttp://search.yahoo.com/yhs/search\*(Aq; \& my $response = $browser\->post( $url, \& [ \*(Aqq\*(Aq => $word, # the Altavista query string \& \*(Aqfr\*(Aq => \*(Aqaltavista\*(Aq, \*(Aqpg\*(Aq => \*(Aqq\*(Aq, \*(Aqavkw\*(Aq => \*(Aqtgz\*(Aq, \*(Aqkl\*(Aq => \*(AqXX\*(Aq, \& ] \& ); \& die "$url error: ", $response\->status_line \& unless $response\->is_success; \& die "Weird content type at $url \-\- ", $response\->content_type \& unless $response\->content_is_html; \& \& if( $response\->decoded_content =~ m{([0\-9,]+)(?:<.*?>)? results for} ) { \& # The substring will be like "996,000 results for" \& print "$word: $1\en"; \& } \& else { \& print "Couldn\*(Aqt find the match\-string in the response\en"; \& } .Ve .SS "Sending \s-1GET\s0 Form Data" .IX Subsection "Sending GET Form Data" Some \s-1HTML\s0 forms convey their form data not by sending the data in an \s-1HTTP POST\s0 request, but by making a normal \s-1GET\s0 request with the data stuck on the end of the \s-1URL.\s0 For example, if you went to \&\f(CW\*(C`www.imdb.com\*(C'\fR and ran a search on \*(L"Blade Runner\*(R", the \s-1URL\s0 you'd see in your browser window would be: .PP .Vb 1 \& http://www.imdb.com/find?s=all&q=Blade+Runner .Ve .PP To run the same search with \s-1LWP,\s0 you'd use this idiom, which involves the \s-1URI\s0 class: .PP .Vb 3 \& use URI; \& my $url = URI\->new( \*(Aqhttp://www.imdb.com/find\*(Aq ); \& # makes an object representing the URL \& \& $url\->query_form( # And here the form data pairs: \& \*(Aqq\*(Aq => \*(AqBlade Runner\*(Aq, \& \*(Aqs\*(Aq => \*(Aqall\*(Aq, \& ); \& \& my $response = $browser\->get($url); .Ve .PP See chapter 5 of \fIPerl & \s-1LWP\s0\fR for a longer discussion of \s-1HTML\s0 forms and of form data, and chapters 6 through 9 for a longer discussion of extracting data from \s-1HTML.\s0 .SS "Absolutizing URLs" .IX Subsection "Absolutizing URLs" The \s-1URI\s0 class that we just mentioned above provides all sorts of methods for accessing and modifying parts of URLs (such as asking sort of \s-1URL\s0 it is with \f(CW\*(C`$url\->scheme\*(C'\fR, and asking what host it refers to with \f(CW\*(C`$url\->host\*(C'\fR, and so on, as described in the docs for the \s-1URI\s0 class. However, the methods of most immediate interest are the \f(CW\*(C`query_form\*(C'\fR method seen above, and now the \f(CW\*(C`new_abs\*(C'\fR method for taking a probably-relative \s-1URL\s0 string (like \*(L"../foo.html\*(R") and getting back an absolute \s-1URL\s0 (like \*(L"http://www.perl.com/stuff/foo.html\*(R"), as shown here: .PP .Vb 2 \& use URI; \& $abs = URI\->new_abs($maybe_relative, $base); .Ve .PP For example, consider this program that matches URLs in the \s-1HTML\s0 list of new modules in \s-1CPAN:\s0 .PP .Vb 4 \& use strict; \& use warnings; \& use LWP; \& my $browser = LWP::UserAgent\->new; \& \& my $url = \*(Aqhttp://www.cpan.org/RECENT.html\*(Aq; \& my $response = $browser\->get($url); \& die "Can\*(Aqt get $url \-\- ", $response\->status_line \& unless $response\->is_success; \& \& my $html = $response\->decoded_content; \& while( $html =~ m/new_abs( $1, $response\->base ) ,"\en"; \& } .Ve .PP (The \f(CW\*(C`$response\->base\*(C'\fR method from HTTP::Message is for returning what \s-1URL\s0 should be used for resolving relative URLs \*(-- it's usually just the same as the \s-1URL\s0 that you requested.) .PP That program then emits nicely absolute URLs: .PP .Vb 7 \& http://www.cpan.org/MIRRORING.FROM \& http://www.cpan.org/RECENT \& http://www.cpan.org/RECENT.html \& http://www.cpan.org/authors/00whois.html \& http://www.cpan.org/authors/01mailrc.txt.gz \& http://www.cpan.org/authors/id/A/AA/AASSAD/CHECKSUMS \& ... .Ve .PP See chapter 4 of \fIPerl & \s-1LWP\s0\fR for a longer discussion of \s-1URI\s0 objects. .PP Of course, using a regexp to match hrefs is a bit simplistic, and for more robust programs, you'll probably want to use an HTML-parsing module like HTML::LinkExtor or HTML::TokeParser or even maybe HTML::TreeBuilder. .SS "Other Browser Attributes" .IX Subsection "Other Browser Attributes" LWP::UserAgent objects have many attributes for controlling how they work. Here are a few notable ones: .IP "\(bu" 4 \&\f(CW\*(C`$browser\->timeout(15);\*(C'\fR .Sp This sets this browser object to give up on requests that don't answer within 15 seconds. .IP "\(bu" 4 \&\f(CW\*(C`$browser\->protocols_allowed( [ \*(Aqhttp\*(Aq, \*(Aqgopher\*(Aq] );\*(C'\fR .Sp This sets this browser object to not speak any protocols other than \s-1HTTP\s0 and gopher. If it tries accessing any other kind of \s-1URL\s0 (like an \*(L"ftp:\*(R" or \*(L"mailto:\*(R" or \*(L"news:\*(R" \s-1URL\s0), then it won't actually try connecting, but instead will immediately return an error code 500, with a message like \&\*(L"Access to 'ftp' URIs has been disabled\*(R". .IP "\(bu" 4 \&\f(CW\*(C`use LWP::ConnCache; $browser\->conn_cache(LWP::ConnCache\->new());\*(C'\fR .Sp This tells the browser object to try using the \s-1HTTP/1.1\s0 \*(L"Keep-Alive\*(R" feature, which speeds up requests by reusing the same socket connection for multiple requests to the same server. .IP "\(bu" 4 \&\f(CW\*(C`$browser\->agent( \*(AqSomeName/1.23 (more info here maybe)\*(Aq )\*(C'\fR .Sp This changes how the browser object will identify itself in the default \*(L"User-Agent\*(R" line is its \s-1HTTP\s0 requests. By default, it'll send "libwww\-perl/\fIversionnumber\fR\*(L", like \&\*(R"libwww\-perl/5.65". You can change that to something more descriptive like this: .Sp .Vb 1 \& $browser\->agent( \*(AqSomeName/3.14 (contact@robotplexus.int)\*(Aq ); .Ve .Sp Or if need be, you can go in disguise, like this: .Sp .Vb 1 \& $browser\->agent( \*(AqMozilla/4.0 (compatible; MSIE 5.12; Mac_PowerPC)\*(Aq ); .Ve .IP "\(bu" 4 \&\f(CW\*(C`push @{ $ua\->requests_redirectable }, \*(AqPOST\*(Aq;\*(C'\fR .Sp This tells this browser to obey redirection responses to \s-1POST\s0 requests (like most modern interactive browsers), even though the \s-1HTTP RFC\s0 says that should not normally be done. .PP For more options and information, see the full documentation for LWP::UserAgent. .SS "Writing Polite Robots" .IX Subsection "Writing Polite Robots" If you want to make sure that your LWP-based program respects \fIrobots.txt\fR files and doesn't make too many requests too fast, you can use the LWP::RobotUA class instead of the LWP::UserAgent class. .PP LWP::RobotUA class is just like LWP::UserAgent, and you can use it like so: .PP .Vb 3 \& use LWP::RobotUA; \& my $browser = LWP::RobotUA\->new(\*(AqYourSuperBot/1.34\*(Aq, \*(Aqyou@yoursite.com\*(Aq); \& # Your bot\*(Aqs name and your email address \& \& my $response = $browser\->get($url); .Ve .PP But HTTP::RobotUA adds these features: .IP "\(bu" 4 If the \fIrobots.txt\fR on \f(CW$url\fR's server forbids you from accessing \&\f(CW$url\fR, then the \f(CW$browser\fR object (assuming it's of class LWP::RobotUA) won't actually request it, but instead will give you back (in \f(CW$response\fR) a 403 error with a message \*(L"Forbidden by robots.txt\*(R". That is, if you have this line: .Sp .Vb 2 \& die "$url \-\- ", $response\->status_line, "\enAborted" \& unless $response\->is_success; .Ve .Sp then the program would die with an error message like this: .Sp .Vb 2 \& http://whatever.site.int/pith/x.html \-\- 403 Forbidden by robots.txt \& Aborted at whateverprogram.pl line 1234 .Ve .IP "\(bu" 4 If this \f(CW$browser\fR object sees that the last time it talked to \&\f(CW$url\fR's server was too recently, then it will pause (via \f(CW\*(C`sleep\*(C'\fR) to avoid making too many requests too often. How long it will pause for, is by default one minute \*(-- but you can control it with the \f(CW\*(C`$browser\->delay( \f(CIminutes\f(CW )\*(C'\fR attribute. .Sp For example, this code: .Sp .Vb 1 \& $browser\->delay( 7/60 ); .Ve .Sp \&...means that this browser will pause when it needs to avoid talking to any given server more than once every 7 seconds. .PP For more options and information, see the full documentation for LWP::RobotUA. .SS "Using Proxies" .IX Subsection "Using Proxies" In some cases, you will want to (or will have to) use proxies for accessing certain sites and/or using certain protocols. This is most commonly the case when your \s-1LWP\s0 program is running (or could be running) on a machine that is behind a firewall. .PP To make a browser object use proxies that are defined in the usual environment variables (\f(CW\*(C`HTTP_PROXY\*(C'\fR, etc.), just call the \f(CW\*(C`env_proxy\*(C'\fR on a user-agent object before you go making any requests on it. Specifically: .PP .Vb 2 \& use LWP::UserAgent; \& my $browser = LWP::UserAgent\->new; \& \& # And before you go making any requests: \& $browser\->env_proxy; .Ve .PP For more information on proxy parameters, see the LWP::UserAgent documentation, specifically the \f(CW\*(C`proxy\*(C'\fR, \f(CW\*(C`env_proxy\*(C'\fR, and \f(CW\*(C`no_proxy\*(C'\fR methods. .SS "\s-1HTTP\s0 Authentication" .IX Subsection "HTTP Authentication" Many web sites restrict access to documents by using \*(L"\s-1HTTP\s0 Authentication\*(R". This isn't just any form of \*(L"enter your password\*(R" restriction, but is a specific mechanism where the \s-1HTTP\s0 server sends the browser an \s-1HTTP\s0 code that says \*(L"That document is part of a protected \&'realm', and you can access it only if you re-request it and add some special authorization headers to your request\*(R". .PP For example, the Unicode.org admins stop email-harvesting bots from harvesting the contents of their mailing list archives, by protecting them with \s-1HTTP\s0 Authentication, and then publicly stating the username and password (at \f(CW\*(C`http://www.unicode.org/mail\-arch/\*(C'\fR) \*(-- namely username \*(L"unicode-ml\*(R" and password \*(L"unicode\*(R". .PP For example, consider this \s-1URL,\s0 which is part of the protected area of the web site: .PP .Vb 1 \& http://www.unicode.org/mail\-arch/unicode\-ml/y2002\-m08/0067.html .Ve .PP If you access that with a browser, you'll get a prompt like \&\*(L"Enter username and password for 'Unicode\-MailList\-Archives' at server \&'www.unicode.org'\*(R". .PP In \s-1LWP,\s0 if you just request that \s-1URL,\s0 like this: .PP .Vb 2 \& use LWP; \& my $browser = LWP::UserAgent\->new; \& \& my $url = \& \*(Aqhttp://www.unicode.org/mail\-arch/unicode\-ml/y2002\-m08/0067.html\*(Aq; \& my $response = $browser\->get($url); \& \& die "Error: ", $response\->header(\*(AqWWW\-Authenticate\*(Aq) || \*(AqError accessing\*(Aq, \& # (\*(AqWWW\-Authenticate\*(Aq is the realm\-name) \& "\en ", $response\->status_line, "\en at $url\en Aborting" \& unless $response\->is_success; .Ve .PP Then you'll get this error: .PP .Vb 4 \& Error: Basic realm="Unicode\-MailList\-Archives" \& 401 Authorization Required \& at http://www.unicode.org/mail\-arch/unicode\-ml/y2002\-m08/0067.html \& Aborting at auth1.pl line 9. [or wherever] .Ve .PP \&...because the \f(CW$browser\fR doesn't know any the username and password for that realm (\*(L"Unicode-MailList-Archives\*(R") at that host (\*(L"www.unicode.org\*(R"). The simplest way to let the browser know about this is to use the \f(CW\*(C`credentials\*(C'\fR method to let it know about a username and password that it can try using for that realm at that host. The syntax is: .PP .Vb 5 \& $browser\->credentials( \& \*(Aqservername:portnumber\*(Aq, \& \*(Aqrealm\-name\*(Aq, \& \*(Aqusername\*(Aq => \*(Aqpassword\*(Aq \& ); .Ve .PP In most cases, the port number is 80, the default \s-1TCP/IP\s0 port for \s-1HTTP\s0; and you usually call the \f(CW\*(C`credentials\*(C'\fR method before you make any requests. For example: .PP .Vb 5 \& $browser\->credentials( \& \*(Aqreports.mybazouki.com:80\*(Aq, \& \*(Aqweb_server_usage_reports\*(Aq, \& \*(Aqplinky\*(Aq => \*(Aqbanjo123\*(Aq \& ); .Ve .PP So if we add the following to the program above, right after the \f(CW\*(C`$browser = LWP::UserAgent\->new;\*(C'\fR line... .PP .Vb 5 \& $browser\->credentials( # add this to our $browser \*(Aqs "key ring" \& \*(Aqwww.unicode.org:80\*(Aq, \& \*(AqUnicode\-MailList\-Archives\*(Aq, \& \*(Aqunicode\-ml\*(Aq => \*(Aqunicode\*(Aq \& ); .Ve .PP \&...then when we run it, the request succeeds, instead of causing the \&\f(CW\*(C`die\*(C'\fR to be called. .SS "Accessing \s-1HTTPS\s0 URLs" .IX Subsection "Accessing HTTPS URLs" When you access an \s-1HTTPS URL,\s0 it'll work for you just like an \s-1HTTP URL\s0 would \*(-- if your \s-1LWP\s0 installation has \s-1HTTPS\s0 support (via an appropriate Secure Sockets Layer library). For example: .PP .Vb 8 \& use LWP; \& my $url = \*(Aqhttps://www.paypal.com/\*(Aq; # Yes, HTTPS! \& my $browser = LWP::UserAgent\->new; \& my $response = $browser\->get($url); \& die "Error at $url\en ", $response\->status_line, "\en Aborting" \& unless $response\->is_success; \& print "Whee, it worked! I got that ", \& $response\->content_type, " document!\en"; .Ve .PP If your \s-1LWP\s0 installation doesn't have \s-1HTTPS\s0 support set up, then the response will be unsuccessful, and you'll get this error message: .PP .Vb 3 \& Error at https://www.paypal.com/ \& 501 Protocol scheme \*(Aqhttps\*(Aq is not supported \& Aborting at paypal.pl line 7. [or whatever program and line] .Ve .PP If your \s-1LWP\s0 installation \fIdoes\fR have \s-1HTTPS\s0 support installed, then the response should be successful, and you should be able to consult \&\f(CW$response\fR just like with any normal \s-1HTTP\s0 response. .PP For information about installing \s-1HTTPS\s0 support for your \s-1LWP\s0 installation, see the helpful \fI\s-1README.SSL\s0\fR file that comes in the libwww-perl distribution. .SS "Getting Large Documents" .IX Subsection "Getting Large Documents" When you're requesting a large (or at least potentially large) document, a problem with the normal way of using the request methods (like \f(CW\*(C`$response = $browser\->get($url)\*(C'\fR) is that the response object in memory will have to hold the whole document \*(-- \fIin memory\fR. If the response is a thirty megabyte file, this is likely to be quite an imposition on this process's memory usage. .PP A notable alternative is to have \s-1LWP\s0 save the content to a file on disk, instead of saving it up in memory. This is the syntax to use: .PP .Vb 3 \& $response = $ua\->get($url, \& \*(Aq:content_file\*(Aq => $filespec, \& ); .Ve .PP For example, .PP .Vb 3 \& $response = $ua\->get(\*(Aqhttp://search.cpan.org/\*(Aq, \& \*(Aq:content_file\*(Aq => \*(Aq/tmp/sco.html\*(Aq \& ); .Ve .PP When you use this \f(CW\*(C`:content_file\*(C'\fR option, the \f(CW$response\fR will have all the normal header lines, but \f(CW\*(C`$response\->content\*(C'\fR will be empty. Errors writing to the content file (for example due to permission denied or the filesystem being full) will be reported via the \f(CW\*(C`Client\-Aborted\*(C'\fR or \f(CW\*(C`X\-Died\*(C'\fR response headers, and not the \&\f(CW\*(C`is_success\*(C'\fR method: .PP .Vb 2 \& if ($response\->header(\*(AqClient\-Aborted\*(Aq) eq \*(Aqdie\*(Aq) { \& # handle error ... .Ve .PP Note that this \*(L":content_file\*(R" option isn't supported under older versions of \s-1LWP,\s0 so you should consider adding \f(CW\*(C`use LWP 5.66;\*(C'\fR to check the \s-1LWP\s0 version, if you think your program might run on systems with older versions. .PP If you need to be compatible with older \s-1LWP\s0 versions, then use this syntax, which does the same thing: .PP .Vb 2 \& use HTTP::Request::Common; \& $response = $ua\->request( GET($url), $filespec ); .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" Remember, this article is just the most rudimentary introduction to \&\s-1LWP\s0 \*(-- to learn more about \s-1LWP\s0 and LWP-related tasks, you really must read from the following: .IP "\(bu" 4 LWP::Simple \*(-- simple functions for getting/heading/mirroring URLs .IP "\(bu" 4 \&\s-1LWP\s0 \*(-- overview of the libwww-perl modules .IP "\(bu" 4 LWP::UserAgent \*(-- the class for objects that represent \*(L"virtual browsers\*(R" .IP "\(bu" 4 HTTP::Response \*(-- the class for objects that represent the response to a \s-1LWP\s0 response, as in \f(CW\*(C`$response = $browser\->get(...)\*(C'\fR .IP "\(bu" 4 HTTP::Message and HTTP::Headers \*(-- classes that provide more methods to HTTP::Response. .IP "\(bu" 4 \&\s-1URI\s0 \*(-- class for objects that represent absolute or relative URLs .IP "\(bu" 4 URI::Escape \*(-- functions for URL-escaping and URL-unescaping strings (like turning \*(L"this & that\*(R" to and from \*(L"this%20%26%20that\*(R"). .IP "\(bu" 4 HTML::Entities \*(-- functions for HTML-escaping and HTML-unescaping strings (like turning \*(L"C. & E. Brontë\*(R" to and from \*(L"C. & E. Brontë\*(R") .IP "\(bu" 4 HTML::TokeParser and HTML::TreeBuilder \*(-- classes for parsing \s-1HTML\s0 .IP "\(bu" 4 HTML::LinkExtor \*(-- class for finding links in \s-1HTML\s0 documents .IP "\(bu" 4 The book \fIPerl & \s-1LWP\s0\fR by Sean M. Burke. O'Reilly & Associates, 2002. \s-1ISBN: 0\-596\-00178\-9,\s0 . The whole book is also available free online: . .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2002, Sean M. Burke. You can redistribute this document and/or modify it, but only under the same terms as Perl itself. .SH "AUTHOR" .IX Header "AUTHOR" Sean M. Burke \f(CW\*(C`sburke@cpan.org\*(C'\fR man/man3/LWP::UserAgent.3pm000044400000134015152462503210011244 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::UserAgent 3" .TH LWP::UserAgent 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::UserAgent \- Web user agent class .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use strict; \& use warnings; \& \& use LWP::UserAgent (); \& \& my $ua = LWP::UserAgent\->new(timeout => 10); \& $ua\->env_proxy; \& \& my $response = $ua\->get(\*(Aqhttp://example.com\*(Aq); \& \& if ($response\->is_success) { \& print $response\->decoded_content; \& } \& else { \& die $response\->status_line; \& } .Ve .PP Extra layers of security (note the \f(CW\*(C`cookie_jar\*(C'\fR and \f(CW\*(C`protocols_allowed\*(C'\fR): .PP .Vb 2 \& use strict; \& use warnings; \& \& use HTTP::CookieJar::LWP (); \& use LWP::UserAgent (); \& \& my $jar = HTTP::CookieJar::LWP\->new; \& my $ua = LWP::UserAgent\->new( \& cookie_jar => $jar, \& protocols_allowed => [\*(Aqhttp\*(Aq, \*(Aqhttps\*(Aq], \& timeout => 10, \& ); \& \& $ua\->env_proxy; \& \& my $response = $ua\->get(\*(Aqhttp://example.com\*(Aq); \& \& if ($response\->is_success) { \& print $response\->decoded_content; \& } \& else { \& die $response\->status_line; \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The LWP::UserAgent is a class implementing a web user agent. LWP::UserAgent objects can be used to dispatch web requests. .PP In normal use the application creates an LWP::UserAgent object, and then configures it with values for timeouts, proxies, name, etc. It then creates an instance of HTTP::Request for the request that needs to be performed. This request is then passed to one of the request method the UserAgent, which dispatches it using the relevant protocol, and returns a HTTP::Response object. There are convenience methods for sending the most common request types: \&\*(L"get\*(R" in LWP::UserAgent, \*(L"head\*(R" in LWP::UserAgent, \*(L"post\*(R" in LWP::UserAgent, \&\*(L"put\*(R" in LWP::UserAgent and \*(L"delete\*(R" in LWP::UserAgent. When using these methods, the creation of the request object is hidden as shown in the synopsis above. .PP The basic approach of the library is to use HTTP-style communication for all protocol schemes. This means that you will construct HTTP::Request objects and receive HTTP::Response objects even for non-HTTP resources like \fIgopher\fR and \fIftp\fR. In order to achieve even more similarity to HTTP-style communications, \fIgopher\fR menus and file directories are converted to \s-1HTML\s0 documents. .SH "CONSTRUCTOR METHODS" .IX Header "CONSTRUCTOR METHODS" The following constructor methods are available: .SS "clone" .IX Subsection "clone" .Vb 1 \& my $ua2 = $ua\->clone; .Ve .PP Returns a copy of the LWP::UserAgent object. .PP \&\fB\s-1CAVEAT\s0\fR: Please be aware that the clone method does not copy or clone your \&\f(CW\*(C`cookie_jar\*(C'\fR attribute. Due to the limited restrictions on what can be used for your cookie jar, there is no way to clone the attribute. The \f(CW\*(C`cookie_jar\*(C'\fR attribute will be \f(CW\*(C`undef\*(C'\fR in the new object instance. .SS "new" .IX Subsection "new" .Vb 1 \& my $ua = LWP::UserAgent\->new( %options ) .Ve .PP This method constructs a new LWP::UserAgent object and returns it. Key/value pair arguments may be provided to set up the initial state. The following options correspond to attribute methods described below: .PP .Vb 10 \& KEY DEFAULT \& \-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& agent "libwww\-perl/#.###" \& conn_cache undef \& cookie_jar undef \& default_headers HTTP::Headers\->new \& from undef \& local_address undef \& max_redirect 7 \& max_size undef \& no_proxy [] \& parse_head 1 \& protocols_allowed undef \& protocols_forbidden undef \& proxy undef \& requests_redirectable [\*(AqGET\*(Aq, \*(AqHEAD\*(Aq] \& ssl_opts { verify_hostname => 1 } \& timeout 180 .Ve .PP The following additional options are also accepted: If the \f(CW\*(C`env_proxy\*(C'\fR option is passed in with a true value, then proxy settings are read from environment variables (see \*(L"env_proxy\*(R" in LWP::UserAgent). If \f(CW\*(C`env_proxy\*(C'\fR isn't provided, the \&\f(CW\*(C`PERL_LWP_ENV_PROXY\*(C'\fR environment variable controls if \&\*(L"env_proxy\*(R" in LWP::UserAgent is called during initialization. If the \&\f(CW\*(C`keep_alive\*(C'\fR option value is defined and non-zero, then an \f(CW\*(C`LWP::ConnCache\*(C'\fR is set up (see \&\*(L"conn_cache\*(R" in LWP::UserAgent). The \f(CW\*(C`keep_alive\*(C'\fR value is passed on as the \&\f(CW\*(C`total_capacity\*(C'\fR for the connection cache. .PP \&\f(CW\*(C`proxy\*(C'\fR must be set as an arrayref of key/value pairs. \f(CW\*(C`no_proxy\*(C'\fR takes an arrayref of domains. .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" The settings of the configuration attributes modify the behaviour of the LWP::UserAgent when it dispatches requests. Most of these can also be initialized by options passed to the constructor method. .PP The following attribute methods are provided. The attribute value is left unchanged if no argument is given. The return value from each method is the old attribute value. .SS "agent" .IX Subsection "agent" .Vb 4 \& my $agent = $ua\->agent; \& $ua\->agent(\*(AqCheckbot/0.4 \*(Aq); # append the default to the end \& $ua\->agent(\*(AqMozilla/5.0\*(Aq); \& $ua\->agent(""); # don\*(Aqt identify .Ve .PP Get/set the product token that is used to identify the user agent on the network. The agent value is sent as the \f(CW\*(C`User\-Agent\*(C'\fR header in the requests. .PP The default is a string of the form \f(CW\*(C`libwww\-perl/#.###\*(C'\fR, where \f(CW\*(C`#.###\*(C'\fR is substituted with the version number of this library. .PP If the provided string ends with space, the default \f(CW\*(C`libwww\-perl/#.###\*(C'\fR string is appended to it. .PP The user agent string should be one or more simple product identifiers with an optional version number separated by the \f(CW\*(C`/\*(C'\fR character. .SS "conn_cache" .IX Subsection "conn_cache" .Vb 2 \& my $cache_obj = $ua\->conn_cache; \& $ua\->conn_cache( $cache_obj ); .Ve .PP Get/set the LWP::ConnCache object to use. See LWP::ConnCache for details. .SS "cookie_jar" .IX Subsection "cookie_jar" .Vb 2 \& my $jar = $ua\->cookie_jar; \& $ua\->cookie_jar( $cookie_jar_obj ); .Ve .PP Get/set the cookie jar object to use. The only requirement is that the cookie jar object must implement the \f(CW\*(C`extract_cookies($response)\*(C'\fR and \&\f(CW\*(C`add_cookie_header($request)\*(C'\fR methods. These methods will then be invoked by the user agent as requests are sent and responses are received. Normally this will be a HTTP::Cookies object or some subclass. You are, however, encouraged to use HTTP::CookieJar::LWP instead. See \*(L"\s-1BEST PRACTICES\*(R"\s0 for more information. .PP .Vb 1 \& use HTTP::CookieJar::LWP (); \& \& my $jar = HTTP::CookieJar::LWP\->new; \& my $ua = LWP::UserAgent\->new( cookie_jar => $jar ); \& \& # or after object creation \& $ua\->cookie_jar( $cookie_jar ); .Ve .PP The default is to have no cookie jar, i.e. never automatically add \&\f(CW\*(C`Cookie\*(C'\fR headers to the requests. .PP Shortcut: If a reference to a plain hash is passed in, it is replaced with an instance of HTTP::Cookies that is initialized based on the hash. This form also automatically loads the HTTP::Cookies module. It means that: .PP .Vb 1 \& $ua\->cookie_jar({ file => "$ENV{HOME}/.cookies.txt" }); .Ve .PP is really just a shortcut for: .PP .Vb 2 \& require HTTP::Cookies; \& $ua\->cookie_jar(HTTP::Cookies\->new(file => "$ENV{HOME}/.cookies.txt")); .Ve .SS "credentials" .IX Subsection "credentials" .Vb 4 \& my $creds = $ua\->credentials(); \& $ua\->credentials( $netloc, $realm ); \& $ua\->credentials( $netloc, $realm, $uname, $pass ); \& $ua\->credentials("www.example.com:80", "Some Realm", "foo", "secret"); .Ve .PP Get/set the user name and password to be used for a realm. .PP The \f(CW$netloc\fR is a string of the form \f(CW\*(C`:\*(C'\fR. The username and password will only be passed to this server. .SS "default_header" .IX Subsection "default_header" .Vb 4 \& $ua\->default_header( $field ); \& $ua\->default_header( $field => $value ); \& $ua\->default_header(\*(AqAccept\-Encoding\*(Aq => scalar HTTP::Message::decodable()); \& $ua\->default_header(\*(AqAccept\-Language\*(Aq => "no, en"); .Ve .PP This is just a shortcut for \&\f(CW\*(C`$ua\->default_headers\->header( $field => $value )\*(C'\fR. .SS "default_headers" .IX Subsection "default_headers" .Vb 2 \& my $headers = $ua\->default_headers; \& $ua\->default_headers( $headers_obj ); .Ve .PP Get/set the headers object that will provide default header values for any requests sent. By default this will be an empty HTTP::Headers object. .SS "from" .IX Subsection "from" .Vb 2 \& my $from = $ua\->from; \& $ua\->from(\*(Aqfoo@bar.com\*(Aq); .Ve .PP Get/set the email address for the human user who controls the requesting user agent. The address should be machine-usable, as defined in \s-1RFC2822\s0 . The \f(CW\*(C`from\*(C'\fR value is sent as the \f(CW\*(C`From\*(C'\fR header in the requests. .PP The default is to not send a \f(CW\*(C`From\*(C'\fR header. See \&\*(L"default_headers\*(R" in LWP::UserAgent for the more general interface that allow any header to be defaulted. .SS "local_address" .IX Subsection "local_address" .Vb 2 \& my $address = $ua\->local_address; \& $ua\->local_address( $address ); .Ve .PP Get/set the local interface to bind to for network connections. The interface can be specified as a hostname or an \s-1IP\s0 address. This value is passed as the \&\f(CW\*(C`LocalAddr\*(C'\fR argument to IO::Socket::INET. .SS "max_redirect" .IX Subsection "max_redirect" .Vb 2 \& my $max = $ua\->max_redirect; \& $ua\->max_redirect( $n ); .Ve .PP This reads or sets the object's limit of how many times it will obey redirection responses in a given request cycle. .PP By default, the value is \f(CW7\fR. This means that if you call \*(L"request\*(R" in LWP::UserAgent and the response is a redirect elsewhere which is in turn a redirect, and so on seven times, then \s-1LWP\s0 gives up after that seventh request. .SS "max_size" .IX Subsection "max_size" .Vb 2 \& my $size = $ua\->max_size; \& $ua\->max_size( $bytes ); .Ve .PP Get/set the size limit for response content. The default is \f(CW\*(C`undef\*(C'\fR, which means that there is no limit. If the returned response content is only partial, because the size limit was exceeded, then a \&\f(CW\*(C`Client\-Aborted\*(C'\fR header will be added to the response. The content might end up longer than \f(CW\*(C`max_size\*(C'\fR as we abort once appending a chunk of data makes the length exceed the limit. The \f(CW\*(C`Content\-Length\*(C'\fR header, if present, will indicate the length of the full content and will normally not be the same as \f(CW\*(C`length($res\->content)\*(C'\fR. .SS "parse_head" .IX Subsection "parse_head" .Vb 2 \& my $bool = $ua\->parse_head; \& $ua\->parse_head( $boolean ); .Ve .PP Get/set a value indicating whether we should initialize response headers from the section of \s-1HTML\s0 documents. The default is true. \fIDo not turn this off\fR unless you know what you are doing. .SS "protocols_allowed" .IX Subsection "protocols_allowed" .Vb 4 \& my $aref = $ua\->protocols_allowed; # get allowed protocols \& $ua\->protocols_allowed( \e@protocols ); # allow ONLY these \& $ua\->protocols_allowed(undef); # delete the list \& $ua\->protocols_allowed([\*(Aqhttp\*(Aq,]); # ONLY allow http .Ve .PP By default, an object has neither a \f(CW\*(C`protocols_allowed\*(C'\fR list, nor a \&\*(L"protocols_forbidden\*(R" in LWP::UserAgent list. .PP This reads (or sets) this user agent's list of protocols that the request methods will exclusively allow. The protocol names are case insensitive. .PP For example: \f(CW\*(C`$ua\->protocols_allowed( [ \*(Aqhttp\*(Aq, \*(Aqhttps\*(Aq] );\*(C'\fR means that this user agent will \fIallow only\fR those protocols, and attempts to use this user agent to access URLs with any other schemes (like \f(CW\*(C`ftp://...\*(C'\fR) will result in a 500 error. .PP Note that having a \f(CW\*(C`protocols_allowed\*(C'\fR list causes any \&\*(L"protocols_forbidden\*(R" in LWP::UserAgent list to be ignored. .SS "protocols_forbidden" .IX Subsection "protocols_forbidden" .Vb 4 \& my $aref = $ua\->protocols_forbidden; # get the forbidden list \& $ua\->protocols_forbidden(\e@protocols); # do not allow these \& $ua\->protocols_forbidden([\*(Aqhttp\*(Aq,]); # All http reqs get a 500 \& $ua\->protocols_forbidden(undef); # delete the list .Ve .PP This reads (or sets) this user agent's list of protocols that the request method will \fInot\fR allow. The protocol names are case insensitive. .PP For example: \f(CW\*(C`$ua\->protocols_forbidden( [ \*(Aqfile\*(Aq, \*(Aqmailto\*(Aq] );\*(C'\fR means that this user agent will \fInot\fR allow those protocols, and attempts to use this user agent to access URLs with those schemes will result in a 500 error. .SS "requests_redirectable" .IX Subsection "requests_redirectable" .Vb 3 \& my $aref = $ua\->requests_redirectable; \& $ua\->requests_redirectable( \e@requests ); \& $ua\->requests_redirectable([\*(AqGET\*(Aq, \*(AqHEAD\*(Aq,]); # the default .Ve .PP This reads or sets the object's list of request names that \&\*(L"redirect_ok\*(R" in LWP::UserAgent will allow redirection for. By default, this is \f(CW\*(C`[\*(AqGET\*(Aq, \*(AqHEAD\*(Aq]\*(C'\fR, as per \s-1RFC 2616\s0 . To change to include \f(CW\*(C`POST\*(C'\fR, consider: .PP .Vb 1 \& push @{ $ua\->requests_redirectable }, \*(AqPOST\*(Aq; .Ve .SS "send_te" .IX Subsection "send_te" .Vb 2 \& my $bool = $ua\->send_te; \& $ua\->send_te( $boolean ); .Ve .PP If true, will send a \f(CW\*(C`TE\*(C'\fR header along with the request. The default is true. Set it to false to disable the \f(CW\*(C`TE\*(C'\fR header for systems who can't handle it. .SS "show_progress" .IX Subsection "show_progress" .Vb 2 \& my $bool = $ua\->show_progress; \& $ua\->show_progress( $boolean ); .Ve .PP Get/set a value indicating whether a progress bar should be displayed on the terminal as requests are processed. The default is false. .SS "ssl_opts" .IX Subsection "ssl_opts" .Vb 3 \& my @keys = $ua\->ssl_opts; \& my $val = $ua\->ssl_opts( $key ); \& $ua\->ssl_opts( $key => $value ); .Ve .PP Get/set the options for \s-1SSL\s0 connections. Without argument return the list of options keys currently set. With a single argument return the current value for the given option. With 2 arguments set the option value and return the old. Setting an option to the value \f(CW\*(C`undef\*(C'\fR removes this option. .PP The options that \s-1LWP\s0 relates to are: .ie n .IP """verify_hostname"" => $bool" 4 .el .IP "\f(CWverify_hostname\fR => \f(CW$bool\fR" 4 .IX Item "verify_hostname => $bool" When \s-1TRUE LWP\s0 will for secure protocol schemes ensure it connects to servers that have a valid certificate matching the expected hostname. If \s-1FALSE\s0 no checks are made and you can't be sure that you communicate with the expected peer. The no checks behaviour was the default for libwww\-perl\-5.837 and earlier releases. .Sp This option is initialized from the \f(CW\*(C`PERL_LWP_SSL_VERIFY_HOSTNAME\*(C'\fR environment variable. If this environment variable isn't set; then \f(CW\*(C`verify_hostname\*(C'\fR defaults to 1. .ie n .IP """SSL_ca_file"" => $path" 4 .el .IP "\f(CWSSL_ca_file\fR => \f(CW$path\fR" 4 .IX Item "SSL_ca_file => $path" The path to a file containing Certificate Authority certificates. A default setting for this option is provided by checking the environment variables \f(CW\*(C`PERL_LWP_SSL_CA_FILE\*(C'\fR and \f(CW\*(C`HTTPS_CA_FILE\*(C'\fR in order. .ie n .IP """SSL_ca_path"" => $path" 4 .el .IP "\f(CWSSL_ca_path\fR => \f(CW$path\fR" 4 .IX Item "SSL_ca_path => $path" The path to a directory containing files containing Certificate Authority certificates. A default setting for this option is provided by checking the environment variables \f(CW\*(C`PERL_LWP_SSL_CA_PATH\*(C'\fR and \f(CW\*(C`HTTPS_CA_DIR\*(C'\fR in order. .PP Other options can be set and are processed directly by the \s-1SSL\s0 Socket implementation in use. See IO::Socket::SSL or Net::SSL for details. .PP The libwww-perl core no longer bundles protocol plugins for \s-1SSL.\s0 You will need to install LWP::Protocol::https separately to enable support for processing https-URLs. .SS "timeout" .IX Subsection "timeout" .Vb 2 \& my $secs = $ua\->timeout; \& $ua\->timeout( $secs ); .Ve .PP Get/set the timeout value in seconds. The default value is 180 seconds, i.e. 3 minutes. .PP The request is aborted if no activity on the connection to the server is observed for \f(CW\*(C`timeout\*(C'\fR seconds. This means that the time it takes for the complete transaction and the \*(L"request\*(R" in LWP::UserAgent method to actually return might be longer. .PP When a request times out, a response object is still returned. The response will have a standard \s-1HTTP\s0 Status Code (500). This response will have the \&\*(L"Client-Warning\*(R" header set to the value of \*(L"Internal response\*(R". See the \&\*(L"get\*(R" in LWP::UserAgent method description below for further details. .SH "PROXY ATTRIBUTES" .IX Header "PROXY ATTRIBUTES" The following methods set up when requests should be passed via a proxy server. .SS "env_proxy" .IX Subsection "env_proxy" .Vb 1 \& $ua\->env_proxy; .Ve .PP Load proxy settings from \f(CW*_proxy\fR environment variables. You might specify proxies like this (sh-syntax): .PP .Vb 4 \& gopher_proxy=http://proxy.my.place/ \& wais_proxy=http://proxy.my.place/ \& no_proxy="localhost,example.com" \& export gopher_proxy wais_proxy no_proxy .Ve .PP csh or tcsh users should use the \f(CW\*(C`setenv\*(C'\fR command to define these environment variables. .PP On systems with case insensitive environment variables there exists a name clash between the \s-1CGI\s0 environment variables and the \f(CW\*(C`HTTP_PROXY\*(C'\fR environment variable normally picked up by \f(CW\*(C`env_proxy\*(C'\fR. Because of this \f(CW\*(C`HTTP_PROXY\*(C'\fR is not honored for \s-1CGI\s0 scripts. The \&\f(CW\*(C`CGI_HTTP_PROXY\*(C'\fR environment variable can be used instead. .SS "no_proxy" .IX Subsection "no_proxy" .Vb 3 \& $ua\->no_proxy( @domains ); \& $ua\->no_proxy(\*(Aqlocalhost\*(Aq, \*(Aqexample.com\*(Aq); \& $ua\->no_proxy(); # clear the list .Ve .PP Do not proxy requests to the given domains. Calling \f(CW\*(C`no_proxy\*(C'\fR without any domains clears the list of domains. .SS "proxy" .IX Subsection "proxy" .Vb 2 \& $ua\->proxy(\e@schemes, $proxy_url) \& $ua\->proxy([\*(Aqhttp\*(Aq, \*(Aqftp\*(Aq], \*(Aqhttp://proxy.sn.no:8001/\*(Aq); \& \& # For a single scheme: \& $ua\->proxy($scheme, $proxy_url) \& $ua\->proxy(\*(Aqgopher\*(Aq, \*(Aqhttp://proxy.sn.no:8001/\*(Aq); \& \& # To set multiple proxies at once: \& $ua\->proxy([ \& ftp => \*(Aqhttp://ftp.example.com:8001/\*(Aq, \& [ \*(Aqhttp\*(Aq, \*(Aqhttps\*(Aq ] => \*(Aqhttp://http.example.com:8001/\*(Aq, \& ]); .Ve .PP Set/retrieve proxy \s-1URL\s0 for a scheme. .PP The first form specifies that the \s-1URL\s0 is to be used as a proxy for access methods listed in the list in the first method argument, i.e. \f(CW\*(C`http\*(C'\fR and \f(CW\*(C`ftp\*(C'\fR. .PP The second form shows a shorthand form for specifying proxy \s-1URL\s0 for a single access scheme. .PP The third form demonstrates setting multiple proxies at once. This is also the only form accepted by the constructor. .SH "HANDLERS" .IX Header "HANDLERS" Handlers are code that injected at various phases during the processing of requests. The following methods are provided to manage the active handlers: .SS "add_handler" .IX Subsection "add_handler" .Vb 1 \& $ua\->add_handler( $phase => \e&cb, %matchspec ) .Ve .PP Add handler to be invoked in the given processing phase. For how to specify \f(CW%matchspec\fR see \*(L"Matching\*(R" in HTTP::Config. .PP The possible values \f(CW$phase\fR and the corresponding callback signatures are as follows. Note that the handlers are documented in the order in which they will be run, which is: .PP .Vb 7 \& request_preprepare \& request_prepare \& request_send \& response_header \& response_data \& response_done \& response_redirect .Ve .ie n .IP "request_preprepare => sub { my($request, $ua, $handler) = @_; ... }" 4 .el .IP "request_preprepare => sub { my($request, \f(CW$ua\fR, \f(CW$handler\fR) = \f(CW@_\fR; ... }" 4 .IX Item "request_preprepare => sub { my($request, $ua, $handler) = @_; ... }" The handler is called before the \f(CW\*(C`request_prepare\*(C'\fR and other standard initialization of the request. This can be used to set up headers and attributes that the \f(CW\*(C`request_prepare\*(C'\fR handler depends on. Proxy initialization should take place here; but in general don't register handlers for this phase. .ie n .IP "request_prepare => sub { my($request, $ua, $handler) = @_; ... }" 4 .el .IP "request_prepare => sub { my($request, \f(CW$ua\fR, \f(CW$handler\fR) = \f(CW@_\fR; ... }" 4 .IX Item "request_prepare => sub { my($request, $ua, $handler) = @_; ... }" The handler is called before the request is sent and can modify the request any way it see fit. This can for instance be used to add certain headers to specific requests. .Sp The method can assign a new request object to \f(CW$_[0]\fR to replace the request that is sent fully. .Sp The return value from the callback is ignored. If an exception is raised it will abort the request and make the request method return a \&\*(L"400 Bad request\*(R" response. .ie n .IP "request_send => sub { my($request, $ua, $handler) = @_; ... }" 4 .el .IP "request_send => sub { my($request, \f(CW$ua\fR, \f(CW$handler\fR) = \f(CW@_\fR; ... }" 4 .IX Item "request_send => sub { my($request, $ua, $handler) = @_; ... }" This handler gets a chance of handling requests before they're sent to the protocol handlers. It should return an HTTP::Response object if it wishes to terminate the processing; otherwise it should return nothing. .Sp The \f(CW\*(C`response_header\*(C'\fR and \f(CW\*(C`response_data\*(C'\fR handlers will not be invoked for this response, but the \f(CW\*(C`response_done\*(C'\fR will be. .ie n .IP "response_header => sub { my($response, $ua, $handler) = @_; ... }" 4 .el .IP "response_header => sub { my($response, \f(CW$ua\fR, \f(CW$handler\fR) = \f(CW@_\fR; ... }" 4 .IX Item "response_header => sub { my($response, $ua, $handler) = @_; ... }" This handler is called right after the response headers have been received, but before any content data. The handler might set up handlers for data and might croak to abort the request. .Sp The handler might set the \f(CW\*(C`$response\->{default_add_content}\*(C'\fR value to control if any received data should be added to the response object directly. This will initially be false if the \f(CW\*(C`$ua\->request()\*(C'\fR method was called with a \f(CW$content_file\fR or \f(CW\*(C`$content_cb argument\*(C'\fR; otherwise true. .ie n .IP "response_data => sub { my($response, $ua, $handler, $data) = @_; ... }" 4 .el .IP "response_data => sub { my($response, \f(CW$ua\fR, \f(CW$handler\fR, \f(CW$data\fR) = \f(CW@_\fR; ... }" 4 .IX Item "response_data => sub { my($response, $ua, $handler, $data) = @_; ... }" This handler is called for each chunk of data received for the response. The handler might croak to abort the request. .Sp This handler needs to return a \s-1TRUE\s0 value to be called again for subsequent chunks for the same request. .ie n .IP "response_done => sub { my($response, $ua, $handler) = @_; ... }" 4 .el .IP "response_done => sub { my($response, \f(CW$ua\fR, \f(CW$handler\fR) = \f(CW@_\fR; ... }" 4 .IX Item "response_done => sub { my($response, $ua, $handler) = @_; ... }" The handler is called after the response has been fully received, but before any redirect handling is attempted. The handler can be used to extract information or modify the response. .ie n .IP "response_redirect => sub { my($response, $ua, $handler) = @_; ... }" 4 .el .IP "response_redirect => sub { my($response, \f(CW$ua\fR, \f(CW$handler\fR) = \f(CW@_\fR; ... }" 4 .IX Item "response_redirect => sub { my($response, $ua, $handler) = @_; ... }" The handler is called in \f(CW\*(C`$ua\->request\*(C'\fR after \f(CW\*(C`response_done\*(C'\fR. If the handler returns an HTTP::Request object we'll start over with processing this request instead. .PP For all of these, \f(CW$handler\fR is a code reference to the handler that is currently being run. .SS "get_my_handler" .IX Subsection "get_my_handler" .Vb 2 \& $ua\->get_my_handler( $phase, %matchspec ); \& $ua\->get_my_handler( $phase, %matchspec, $init ); .Ve .PP Will retrieve the matching handler as hash ref. .PP If \f(CW$init\fR is passed as a true value, create and add the handler if it's not found. If \f(CW$init\fR is a subroutine reference, then it's called with the created handler hash as argument. This sub might populate the hash with extra fields; especially the callback. If \&\f(CW$init\fR is a hash reference, merge the hashes. .SS "handlers" .IX Subsection "handlers" .Vb 2 \& $ua\->handlers( $phase, $request ) \& $ua\->handlers( $phase, $response ) .Ve .PP Returns the handlers that apply to the given request or response at the given processing phase. .SS "remove_handler" .IX Subsection "remove_handler" .Vb 3 \& $ua\->remove_handler( undef, %matchspec ); \& $ua\->remove_handler( $phase, %matchspec ); \& $ua\->remove_handler(); # REMOVE ALL HANDLERS IN ALL PHASES .Ve .PP Remove handlers that match the given \f(CW%matchspec\fR. If \f(CW$phase\fR is not provided, remove handlers from all phases. .PP Be careful as calling this function with \f(CW%matchspec\fR that is not specific enough can remove handlers not owned by you. It's probably better to use the \*(L"set_my_handler\*(R" in LWP::UserAgent method instead. .PP The removed handlers are returned. .SS "set_my_handler" .IX Subsection "set_my_handler" .Vb 2 \& $ua\->set_my_handler( $phase, $cb, %matchspec ); \& $ua\->set_my_handler($phase, undef); # remove handler for phase .Ve .PP Set handlers private to the executing subroutine. Works by defaulting an \f(CW\*(C`owner\*(C'\fR field to the \f(CW%matchspec\fR that holds the name of the called subroutine. You might pass an explicit \f(CW\*(C`owner\*(C'\fR to override this. .PP If \f(CW$cb\fR is passed as \f(CW\*(C`undef\*(C'\fR, remove the handler. .SH "REQUEST METHODS" .IX Header "REQUEST METHODS" The methods described in this section are used to dispatch requests via the user agent. The following request methods are provided: .SS "delete" .IX Subsection "delete" .Vb 2 \& my $res = $ua\->delete( $url ); \& my $res = $ua\->delete( $url, $field_name => $value, ... ); .Ve .PP This method will dispatch a \f(CW\*(C`DELETE\*(C'\fR request on the given \s-1URL.\s0 Additional headers and content options are the same as for the \*(L"get\*(R" in LWP::UserAgent method. .PP This method will use the \f(CW\*(C`DELETE()\*(C'\fR function from HTTP::Request::Common to build the request. See HTTP::Request::Common for a details on how to pass form content and other advanced features. .SS "get" .IX Subsection "get" .Vb 2 \& my $res = $ua\->get( $url ); \& my $res = $ua\->get( $url , $field_name => $value, ... ); .Ve .PP This method will dispatch a \f(CW\*(C`GET\*(C'\fR request on the given \s-1URL.\s0 Further arguments can be given to initialize the headers of the request. These are given as separate name/value pairs. The return value is a response object. See HTTP::Response for a description of the interface it provides. .PP There will still be a response object returned when \s-1LWP\s0 can't connect to the server specified in the \s-1URL\s0 or when other failures in protocol handlers occur. These internal responses use the standard \s-1HTTP\s0 status codes, so the responses can't be differentiated by testing the response status code alone. Error responses that \s-1LWP\s0 generates internally will have the \*(L"Client-Warning\*(R" header set to the value \*(L"Internal response\*(R". If you need to differentiate these internal responses from responses that a remote server actually generates, you need to test this header value. .PP Fields names that start with \*(L":\*(R" are special. These will not initialize headers of the request but will determine how the response content is treated. The following special field names are recognized: .PP .Vb 3 \& \*(Aq:content_file\*(Aq => $filename \& \*(Aq:content_cb\*(Aq => \e&callback \& \*(Aq:read_size_hint\*(Aq => $bytes .Ve .PP If a \f(CW$filename\fR is provided with the \f(CW\*(C`:content_file\*(C'\fR option, then the response content will be saved here instead of in the response object. If a callback is provided with the \f(CW\*(C`:content_cb\*(C'\fR option then this function will be called for each chunk of the response content as it is received from the server. If neither of these options are given, then the response content will accumulate in the response object itself. This might not be suitable for very large response bodies. Only one of \f(CW\*(C`:content_file\*(C'\fR or \f(CW\*(C`:content_cb\*(C'\fR can be specified. The content of unsuccessful responses will always accumulate in the response object itself, regardless of the \&\f(CW\*(C`:content_file\*(C'\fR or \f(CW\*(C`:content_cb\*(C'\fR options passed in. Note that errors writing to the content file (for example due to permission denied or the filesystem being full) will be reported via the \f(CW\*(C`Client\-Aborted\*(C'\fR or \f(CW\*(C`X\-Died\*(C'\fR response headers, and not the \f(CW\*(C`is_success\*(C'\fR method. .PP The \f(CW\*(C`:read_size_hint\*(C'\fR option is passed to the protocol module which will try to read data from the server in chunks of this size. A smaller value for the \f(CW\*(C`:read_size_hint\*(C'\fR will result in a higher number of callback invocations. .PP The callback function is called with 3 arguments: a chunk of data, a reference to the response object, and a reference to the protocol object. The callback can abort the request by invoking \f(CW\*(C`die()\*(C'\fR. The exception message will show up as the \*(L"X\-Died\*(R" header field in the response returned by the \f(CW\*(C`$ua\->get()\*(C'\fR method. .SS "head" .IX Subsection "head" .Vb 2 \& my $res = $ua\->head( $url ); \& my $res = $ua\->head( $url , $field_name => $value, ... ); .Ve .PP This method will dispatch a \f(CW\*(C`HEAD\*(C'\fR request on the given \s-1URL.\s0 Otherwise it works like the \*(L"get\*(R" in LWP::UserAgent method described above. .SS "is_protocol_supported" .IX Subsection "is_protocol_supported" .Vb 1 \& my $bool = $ua\->is_protocol_supported( $scheme ); .Ve .PP You can use this method to test whether this user agent object supports the specified \f(CW\*(C`scheme\*(C'\fR. (The \f(CW\*(C`scheme\*(C'\fR might be a string (like \f(CW\*(C`http\*(C'\fR or \&\f(CW\*(C`ftp\*(C'\fR) or it might be an \s-1URI\s0 object reference.) .PP Whether a scheme is supported is determined by the user agent's \&\f(CW\*(C`protocols_allowed\*(C'\fR or \f(CW\*(C`protocols_forbidden\*(C'\fR lists (if any), and by the capabilities of \s-1LWP.\s0 I.e., this will return true only if \s-1LWP\s0 supports this protocol \fIand\fR it's permitted for this particular object. .SS "is_online" .IX Subsection "is_online" .Vb 1 \& my $bool = $ua\->is_online; .Ve .PP Tries to determine if you have access to the Internet. Returns \f(CW1\fR (true) if the built-in heuristics determine that the user agent is able to access the Internet (over \s-1HTTP\s0) or \f(CW0\fR (false). .PP See also LWP::Online. .SS "mirror" .IX Subsection "mirror" .Vb 1 \& my $res = $ua\->mirror( $url, $filename ); .Ve .PP This method will get the document identified by \s-1URL\s0 and store it in file called \f(CW$filename\fR. If the file already exists, then the request will contain an \f(CW\*(C`If\-Modified\-Since\*(C'\fR header matching the modification time of the file. If the document on the server has not changed since this time, then nothing happens. If the document has been updated, it will be downloaded again. The modification time of the file will be forced to match that of the server. .PP The return value is an HTTP::Response object. .SS "patch" .IX Subsection "patch" .Vb 2 \& # Any version of HTTP::Message works with this form: \& my $res = $ua\->patch( $url, $field_name => $value, Content => $content ); \& \& # Using hash or array references requires HTTP::Message >= 6.12 \& use HTTP::Request 6.12; \& my $res = $ua\->patch( $url, \e%form ); \& my $res = $ua\->patch( $url, \e@form ); \& my $res = $ua\->patch( $url, \e%form, $field_name => $value, ... ); \& my $res = $ua\->patch( $url, $field_name => $value, Content => \e%form ); \& my $res = $ua\->patch( $url, $field_name => $value, Content => \e@form ); .Ve .PP This method will dispatch a \f(CW\*(C`PATCH\*(C'\fR request on the given \s-1URL,\s0 with \&\f(CW%form\fR or \f(CW@form\fR providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the \*(L"get\*(R" in LWP::UserAgent method. .PP \&\s-1CAVEAT:\s0 .PP This method can only accept content that is in key-value pairs when using HTTP::Request::Common prior to version \f(CW6.12\fR. Any use of hash or array references will result in an error prior to version \f(CW6.12\fR. .PP This method will use the \f(CW\*(C`PATCH\*(C'\fR function from HTTP::Request::Common to build the request. See HTTP::Request::Common for a details on how to pass form content and other advanced features. .SS "post" .IX Subsection "post" .Vb 6 \& my $res = $ua\->post( $url, \e%form ); \& my $res = $ua\->post( $url, \e@form ); \& my $res = $ua\->post( $url, \e%form, $field_name => $value, ... ); \& my $res = $ua\->post( $url, $field_name => $value, Content => \e%form ); \& my $res = $ua\->post( $url, $field_name => $value, Content => \e@form ); \& my $res = $ua\->post( $url, $field_name => $value, Content => $content ); .Ve .PP This method will dispatch a \f(CW\*(C`POST\*(C'\fR request on the given \s-1URL,\s0 with \&\f(CW%form\fR or \f(CW@form\fR providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the \*(L"get\*(R" in LWP::UserAgent method. .PP This method will use the \f(CW\*(C`POST\*(C'\fR function from HTTP::Request::Common to build the request. See HTTP::Request::Common for a details on how to pass form content and other advanced features. .SS "put" .IX Subsection "put" .Vb 2 \& # Any version of HTTP::Message works with this form: \& my $res = $ua\->put( $url, $field_name => $value, Content => $content ); \& \& # Using hash or array references requires HTTP::Message >= 6.07 \& use HTTP::Request 6.07; \& my $res = $ua\->put( $url, \e%form ); \& my $res = $ua\->put( $url, \e@form ); \& my $res = $ua\->put( $url, \e%form, $field_name => $value, ... ); \& my $res = $ua\->put( $url, $field_name => $value, Content => \e%form ); \& my $res = $ua\->put( $url, $field_name => $value, Content => \e@form ); .Ve .PP This method will dispatch a \f(CW\*(C`PUT\*(C'\fR request on the given \s-1URL,\s0 with \&\f(CW%form\fR or \f(CW@form\fR providing the key/value pairs for the fill-in form content. Additional headers and content options are the same as for the \*(L"get\*(R" in LWP::UserAgent method. .PP \&\s-1CAVEAT:\s0 .PP This method can only accept content that is in key-value pairs when using HTTP::Request::Common prior to version \f(CW6.07\fR. Any use of hash or array references will result in an error prior to version \f(CW6.07\fR. .PP This method will use the \f(CW\*(C`PUT\*(C'\fR function from HTTP::Request::Common to build the request. See HTTP::Request::Common for a details on how to pass form content and other advanced features. .SS "request" .IX Subsection "request" .Vb 4 \& my $res = $ua\->request( $request ); \& my $res = $ua\->request( $request, $content_file ); \& my $res = $ua\->request( $request, $content_cb ); \& my $res = $ua\->request( $request, $content_cb, $read_size_hint ); .Ve .PP This method will dispatch the given \f(CW$request\fR object. Normally this will be an instance of the HTTP::Request class, but any object with a similar interface will do. The return value is an HTTP::Response object. .PP The \f(CW\*(C`request\*(C'\fR method will process redirects and authentication responses transparently. This means that it may actually send several simple requests via the \*(L"simple_request\*(R" in LWP::UserAgent method described below. .PP The request methods described above; \*(L"get\*(R" in LWP::UserAgent, \*(L"head\*(R" in LWP::UserAgent, \&\*(L"post\*(R" in LWP::UserAgent and \*(L"mirror\*(R" in LWP::UserAgent will all dispatch the request they build via this method. They are convenience methods that simply hide the creation of the request object for you. .PP The \f(CW$content_file\fR, \f(CW$content_cb\fR and \f(CW$read_size_hint\fR all correspond to options described with the \*(L"get\*(R" in LWP::UserAgent method above. Note that errors writing to the content file (for example due to permission denied or the filesystem being full) will be reported via the \f(CW\*(C`Client\-Aborted\*(C'\fR or \f(CW\*(C`X\-Died\*(C'\fR response headers, and not the \f(CW\*(C`is_success\*(C'\fR method. .PP You are allowed to use a \s-1CODE\s0 reference as \f(CW\*(C`content\*(C'\fR in the request object passed in. The \f(CW\*(C`content\*(C'\fR function should return the content when called. The content can be returned in chunks. The content function will be invoked repeatedly until it return an empty string to signal that there is no more content. .SS "simple_request" .IX Subsection "simple_request" .Vb 5 \& my $request = HTTP::Request\->new( ... ); \& my $res = $ua\->simple_request( $request ); \& my $res = $ua\->simple_request( $request, $content_file ); \& my $res = $ua\->simple_request( $request, $content_cb ); \& my $res = $ua\->simple_request( $request, $content_cb, $read_size_hint ); .Ve .PP This method dispatches a single request and returns the response received. Arguments are the same as for the \*(L"request\*(R" in LWP::UserAgent described above. .PP The difference from \*(L"request\*(R" in LWP::UserAgent is that \f(CW\*(C`simple_request\*(C'\fR will not try to handle redirects or authentication responses. The \*(L"request\*(R" in LWP::UserAgent method will, in fact, invoke this method for each simple request it sends. .SH "CALLBACK METHODS" .IX Header "CALLBACK METHODS" The following methods will be invoked as requests are processed. These methods are documented here because subclasses of LWP::UserAgent might want to override their behaviour. .SS "get_basic_credentials" .IX Subsection "get_basic_credentials" .Vb 4 \& # This checks wantarray and can either return an array: \& my ($user, $pass) = $ua\->get_basic_credentials( $realm, $uri, $isproxy ); \& # or a string that looks like "user:pass" \& my $creds = $ua\->get_basic_credentials($realm, $uri, $isproxy); .Ve .PP This is called by \*(L"request\*(R" in LWP::UserAgent to retrieve credentials for documents protected by Basic or Digest Authentication. The arguments passed in is the \f(CW$realm\fR provided by the server, the \f(CW$uri\fR requested and a \&\f(CW\*(C`boolean flag\*(C'\fR to indicate if this is authentication against a proxy server. .PP The method should return a username and password. It should return an empty list to abort the authentication resolution attempt. Subclasses can override this method to prompt the user for the information. An example of this can be found in \f(CW\*(C`lwp\-request\*(C'\fR program distributed with this library. .PP The base implementation simply checks a set of pre-stored member variables, set up with the \*(L"credentials\*(R" in LWP::UserAgent method. .SS "prepare_request" .IX Subsection "prepare_request" .Vb 1 \& $request = $ua\->prepare_request( $request ); .Ve .PP This method is invoked by \*(L"simple_request\*(R" in LWP::UserAgent. Its task is to modify the given \f(CW$request\fR object by setting up various headers based on the attributes of the user agent. The return value should normally be the \&\f(CW$request\fR object passed in. If a different request object is returned it will be the one actually processed. .PP The headers affected by the base implementation are; \f(CW\*(C`User\-Agent\*(C'\fR, \&\f(CW\*(C`From\*(C'\fR, \f(CW\*(C`Range\*(C'\fR and \f(CW\*(C`Cookie\*(C'\fR. .SS "progress" .IX Subsection "progress" .Vb 1 \& my $prog = $ua\->progress( $status, $request_or_response ); .Ve .PP This is called frequently as the response is received regardless of how the content is processed. The method is called with \f(CW$status\fR \&\*(L"begin\*(R" at the start of processing the request and with \f(CW$state\fR \*(L"end\*(R" before the request method returns. In between these \f(CW$status\fR will be the fraction of the response currently received or the string \*(L"tick\*(R" if the fraction can't be calculated. .PP When \f(CW$status\fR is \*(L"begin\*(R" the second argument is the HTTP::Request object, otherwise it is the HTTP::Response object. .SS "redirect_ok" .IX Subsection "redirect_ok" .Vb 1 \& my $bool = $ua\->redirect_ok( $prospective_request, $response ); .Ve .PP This method is called by \*(L"request\*(R" in LWP::UserAgent before it tries to follow a redirection to the request in \f(CW$response\fR. This should return a true value if this redirection is permissible. The \f(CW$prospective_request\fR will be the request to be sent if this method returns true. .PP The base implementation will return false unless the method is in the object's \f(CW\*(C`requests_redirectable\*(C'\fR list, false if the proposed redirection is to a \f(CW\*(C`file://...\*(C'\fR \&\s-1URL,\s0 and true otherwise. .SH "BEST PRACTICES" .IX Header "BEST PRACTICES" The default settings can get you up and running quickly, but there are settings you can change in order to make your life easier. .SS "Handling Cookies" .IX Subsection "Handling Cookies" You are encouraged to install Mozilla::PublicSuffix and use HTTP::CookieJar::LWP as your cookie jar. HTTP::CookieJar::LWP provides a better security model matching that of current Web browsers when Mozilla::PublicSuffix is installed. .PP .Vb 1 \& use HTTP::CookieJar::LWP (); \& \& my $jar = HTTP::CookieJar::LWP\->new; \& my $ua = LWP::UserAgent\->new( cookie_jar => $jar ); .Ve .PP See \*(L"cookie_jar\*(R" for more information. .SS "Managing Protocols" .IX Subsection "Managing Protocols" \&\f(CW\*(C`protocols_allowed\*(C'\fR gives you the ability to allow arbitrary protocols. .PP .Vb 3 \& my $ua = LWP::UserAgent\->new( \& protocols_allowed => [ \*(Aqhttp\*(Aq, \*(Aqhttps\*(Aq ] \& ); .Ve .PP This will prevent you from inadvertently following URLs like \&\f(CW\*(C`file:///etc/passwd\*(C'\fR. See \*(L"protocols_allowed\*(R". .PP \&\f(CW\*(C`protocols_forbidden\*(C'\fR gives you the ability to deny arbitrary protocols. .PP .Vb 3 \& my $ua = LWP::UserAgent\->new( \& protocols_forbidden => [ \*(Aqfile\*(Aq, \*(Aqmailto\*(Aq, \*(Aqssh\*(Aq, ] \& ); .Ve .PP This can also prevent you from inadvertently following URLs like \&\f(CW\*(C`file:///etc/passwd\*(C'\fR. See \*(L"protocols_forbidden\*(R". .SH "SEE ALSO" .IX Header "SEE ALSO" See \s-1LWP\s0 for a complete overview of libwww\-perl5. See lwpcook and the scripts \fIlwp-request\fR and \fIlwp-download\fR for examples of usage. .PP See HTTP::Request and HTTP::Response for a description of the message objects dispatched and received. See HTTP::Request::Common and HTML::Form for other ways to build request objects. .PP See WWW::Mechanize and WWW::Search for examples of more specialized user agents based on LWP::UserAgent. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 1995\-2009 Gisle Aas. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::DBD::SqlEngine::Developers.3pm000044400000105052152462503210014102 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::DBD::SqlEngine::Developers 3" .TH DBI::DBD::SqlEngine::Developers 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::DBD::SqlEngine::Developers \- Developers documentation for DBI::DBD::SqlEngine .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& package DBD::myDriver; \& \& use base qw(DBI::DBD::SqlEngine); \& \& sub driver \& { \& ... \& my $drh = $proto\->SUPER::driver($attr); \& ... \& return $drh\->{class}; \& } \& \& sub CLONE { ... } \& \& package DBD::myDriver::dr; \& \& @ISA = qw(DBI::DBD::SqlEngine::dr); \& \& sub data_sources { ... } \& ... \& \& package DBD::myDriver::db; \& \& @ISA = qw(DBI::DBD::SqlEngine::db); \& \& sub init_valid_attributes { ... } \& sub init_default_attributes { ... } \& sub set_versions { ... } \& sub validate_STORE_attr { my ($dbh, $attrib, $value) = @_; ... } \& sub validate_FETCH_attr { my ($dbh, $attrib) = @_; ... } \& sub get_myd_versions { ... } \& sub get_avail_tables { ... } \& \& package DBD::myDriver::st; \& \& @ISA = qw(DBI::DBD::SqlEngine::st); \& \& sub FETCH { ... } \& sub STORE { ... } \& \& package DBD::myDriver::Statement; \& \& @ISA = qw(DBI::DBD::SqlEngine::Statement); \& \& sub open_table { ... } \& \& package DBD::myDriver::Table; \& \& @ISA = qw(DBI::DBD::SqlEngine::Table); \& \& my %reset_on_modify = ( \& myd_abc => "myd_foo", \& myd_mno => "myd_bar", \& ); \& _\|_PACKAGE_\|_\->register_reset_on_modify( \e%reset_on_modify ); \& my %compat_map = ( \& abc => \*(Aqfoo_abc\*(Aq, \& xyz => \*(Aqfoo_xyz\*(Aq, \& ); \& _\|_PACKAGE_\|_\->register_compat_map( \e%compat_map ); \& \& sub bootstrap_table_meta { ... } \& sub init_table_meta { ... } \& sub table_meta_attr_changed { ... } \& sub open_data { ... } \& \& sub new { ... } \& \& sub fetch_row { ... } \& sub push_row { ... } \& sub push_names { ... } \& sub seek { ... } \& sub truncate { ... } \& sub drop { ... } \& \& # optimize the SQL engine by add one or more of \& sub update_current_row { ... } \& # or \& sub update_specific_row { ... } \& # or \& sub update_one_row { ... } \& # or \& sub insert_new_row { ... } \& # or \& sub delete_current_row { ... } \& # or \& sub delete_one_row { ... } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document describes the interface of DBI::DBD::SqlEngine for \s-1DBD\s0 developers who write DBI::DBD::SqlEngine based \s-1DBI\s0 drivers. It supplements \&\s-1DBI::DBD\s0 and DBI::DBD::SqlEngine::HowTo, which you should read first. .SH "CLASSES" .IX Header "CLASSES" Each \s-1DBI\s0 driver must provide a package global \f(CW\*(C`driver\*(C'\fR method and three \s-1DBI\s0 related classes: .IP "DBI::DBD::SqlEngine::dr" 4 .IX Item "DBI::DBD::SqlEngine::dr" Driver package, contains the methods \s-1DBI\s0 calls indirectly via \s-1DBI\s0 interface: .Sp .Vb 1 \& DBI\->connect (\*(AqDBI:DBM:\*(Aq, undef, undef, {}) \& \& # invokes \& package DBD::DBM::dr; \& @DBD::DBM::dr::ISA = qw(DBI::DBD::SqlEngine::dr); \& \& sub connect ($$;$$$) \& { \& ... \& } .Ve .Sp Similar for \f(CW\*(C`data_sources ()\*(C'\fR and \f(CW\*(C`disconnect_all()\*(C'\fR. .Sp Pure Perl \s-1DBI\s0 drivers derived from DBI::DBD::SqlEngine usually don't need to override any of the methods provided through the DBD::XXX::dr package. However if you need additional initialization not fitting in \&\f(CW\*(C`init_valid_attributes()\*(C'\fR and \f(CW\*(C`init_default_attributes()\*(C'\fR of you're ::db class, the connect method might be the final place to be modified. .IP "DBI::DBD::SqlEngine::db" 4 .IX Item "DBI::DBD::SqlEngine::db" Contains the methods which are called through \s-1DBI\s0 database handles (\f(CW$dbh\fR). e.g., .Sp .Vb 3 \& $sth = $dbh\->prepare ("select * from foo"); \& # returns the f_encoding setting for table foo \& $dbh\->csv_get_meta ("foo", "f_encoding"); .Ve .Sp DBI::DBD::SqlEngine provides the typical methods required here. Developers who write \s-1DBI\s0 drivers based on DBI::DBD::SqlEngine need to override the methods \&\f(CW\*(C`set_versions\*(C'\fR and \f(CW\*(C`init_valid_attributes\*(C'\fR. .IP "DBI::DBD::SqlEngine::TieMeta;" 4 .IX Item "DBI::DBD::SqlEngine::TieMeta;" Provides the tie-magic for \f(CW\*(C`$dbh\->{$drv_pfx . "_meta"}\*(C'\fR. Routes \&\f(CW\*(C`STORE\*(C'\fR through \f(CW\*(C`$drv\->set_sql_engine_meta()\*(C'\fR and \f(CW\*(C`FETCH\*(C'\fR through \&\f(CW\*(C`$drv\->get_sql_engine_meta()\*(C'\fR. \f(CW\*(C`DELETE\*(C'\fR is not supported, you have to execute a \f(CW\*(C`DROP TABLE\*(C'\fR statement, where applicable. .IP "DBI::DBD::SqlEngine::TieTables;" 4 .IX Item "DBI::DBD::SqlEngine::TieTables;" Provides the tie-magic for tables in \f(CW\*(C`$dbh\->{$drv_pfx . "_meta"}\*(C'\fR. Routes \f(CW\*(C`STORE\*(C'\fR though \f(CW\*(C`$tblClass\->set_table_meta_attr()\*(C'\fR and \f(CW\*(C`FETCH\*(C'\fR though \f(CW\*(C`$tblClass\->get_table_meta_attr()\*(C'\fR. \f(CW\*(C`DELETE\*(C'\fR removes an attribute from the \fImeta object\fR retrieved by \&\f(CW\*(C`$tblClass\->get_table_meta()\*(C'\fR. .IP "DBI::DBD::SqlEngine::st" 4 .IX Item "DBI::DBD::SqlEngine::st" Contains the methods to deal with prepared statement handles. e.g., .Sp .Vb 1 \& $sth\->execute () or die $sth\->errstr; .Ve .IP "DBI::DBD::SqlEngine::TableSource;" 4 .IX Item "DBI::DBD::SqlEngine::TableSource;" Base class for 3rd party table sources: .Sp .Vb 1 \& $dbh\->{sql_table_source} = "DBD::Foo::TableSource"; .Ve .IP "DBI::DBD::SqlEngine::DataSource;" 4 .IX Item "DBI::DBD::SqlEngine::DataSource;" Base class for 3rd party data sources: .Sp .Vb 1 \& $dbh\->{sql_data_source} = "DBD::Foo::DataSource"; .Ve .IP "DBI::DBD::SqlEngine::Statement;" 4 .IX Item "DBI::DBD::SqlEngine::Statement;" Base class for derived drivers statement engine. Implements \f(CW\*(C`open_table\*(C'\fR. .IP "DBI::DBD::SqlEngine::Table;" 4 .IX Item "DBI::DBD::SqlEngine::Table;" Contains tailoring between \s-1SQL\s0 engine's requirements and \&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR magic for finding the right tables and storage. Builds bridges between \f(CW\*(C`sql_meta\*(C'\fR handling of \f(CW\*(C`DBI::DBD::SqlEngine::db\*(C'\fR, table initialization for \s-1SQL\s0 engines and \fImeta object\fR's attribute management for derived drivers. .SS "DBI::DBD::SqlEngine" .IX Subsection "DBI::DBD::SqlEngine" This is the main package containing the routines to initialize DBI::DBD::SqlEngine based \s-1DBI\s0 drivers. Primarily the \&\f(CW\*(C`DBI::DBD::SqlEngine::driver\*(C'\fR method is invoked, either directly from \s-1DBI\s0 when the driver is initialized or from the derived class. .PP .Vb 1 \& package DBD::DBM; \& \& use base qw( DBI::DBD::SqlEngine ); \& \& sub driver \& { \& my ( $class, $attr ) = @_; \& ... \& my $drh = $class\->SUPER::driver( $attr ); \& ... \& return $drh; \& } .Ve .PP It is not necessary to implement your own driver method as long as additional initialization (e.g. installing more private driver methods) is not required. You do not need to call \f(CW\*(C`setup_driver\*(C'\fR as DBI::DBD::SqlEngine takes care of it. .SS "DBI::DBD::SqlEngine::dr" .IX Subsection "DBI::DBD::SqlEngine::dr" The driver package contains the methods \s-1DBI\s0 calls indirectly via the \s-1DBI\s0 interface (see \*(L"\s-1DBI\s0 Class Methods\*(R" in \s-1DBI\s0). .PP DBI::DBD::SqlEngine based \s-1DBI\s0 drivers usually do not need to implement anything here, it is enough to do the basic initialization: .PP .Vb 1 \& package DBD:XXX::dr; \& \& @DBD::XXX::dr::ISA = qw (DBI::DBD::SqlEngine::dr); \& $DBD::XXX::dr::imp_data_size = 0; \& $DBD::XXX::dr::data_sources_attr = undef; \& $DBD::XXX::ATTRIBUTION = "DBD::XXX $DBD::XXX::VERSION by Hans Mustermann"; .Ve .PP \fIMethods provided by \f(CI\*(C`DBI::DBD::SqlEngine::dr\*(C'\fI:\fR .IX Subsection "Methods provided by DBI::DBD::SqlEngine::dr:" .IP "connect" 4 .IX Item "connect" Supervises the driver bootstrap when calling .Sp .Vb 1 \& DBI\->connect( "dbi:Foo", , , { ... } ); .Ve .Sp First it instantiates a new driver using \f(CW\*(C`DBI::_new_dbh\*(C'\fR. After that, initial bootstrap of the newly instantiated driver is done by .Sp .Vb 1 \& $dbh\->func( 0, "init_default_attributes" ); .Ve .Sp The first argument (\f(CW0\fR) signals that this is the very first call to \&\f(CW\*(C`init_default_attributes\*(C'\fR. Modern drivers understand that and do early stage setup here after calling .Sp .Vb 2 \& package DBD::Foo::db; \& our @DBD::Foo::db::ISA = qw(DBI::DBD::SqlEngine::db); \& \& sub init_default_attributes \& { \& my ($dbh, $phase) = @_; \& $dbh\->SUPER::init_default_attributes($phase); \& ...; # own setup code, maybe separated by phases \& } .Ve .Sp When the \f(CW$phase\fR argument is passed down until \&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_default_attributes\*(C'\fR, \f(CW\*(C`connect()\*(C'\fR recognizes a \fImodern\fR driver and initializes the attributes from \fI\s-1DSN\s0\fR and \fI\f(CI$attr\fI\fR arguments passed via \f(CW\*(C`DBI\->connect( $dsn, $user, $pass, \e%attr )\*(C'\fR. .Sp At the end of the attribute initialization after \fIphase 0\fR, \f(CW\*(C`connect()\*(C'\fR invoked \f(CW\*(C`init_default_attributes\*(C'\fR again for \fIphase 1\fR: .Sp .Vb 1 \& $dbh\->func( 1, "init_default_attributes" ); .Ve .IP "data_sources" 4 .IX Item "data_sources" Returns a list of \fI\s-1DSN\s0\fR's using the \f(CW\*(C`data_sources\*(C'\fR method of the class specified in \f(CW\*(C`$dbh\->{sql_table_source}\*(C'\fR or via \f(CW\*(C`\e%attr\*(C'\fR: .Sp .Vb 2 \& @ary = DBI\->data_sources($driver); \& @ary = DBI\->data_sources($driver, \e%attr); .Ve .IP "disconnect_all" 4 .IX Item "disconnect_all" \&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR doesn't have an overall driver cache, so nothing happens here at all. .SS "DBI::DBD::SqlEngine::db" .IX Subsection "DBI::DBD::SqlEngine::db" This package defines the database methods, which are called via the \s-1DBI\s0 database handle \f(CW$dbh\fR. .PP \fIMethods provided by \f(CI\*(C`DBI::DBD::SqlEngine::db\*(C'\fI:\fR .IX Subsection "Methods provided by DBI::DBD::SqlEngine::db:" .IP "ping" 4 .IX Item "ping" Simply returns the content of the \f(CW\*(C`Active\*(C'\fR attribute. Override when your driver needs more complicated actions here. .IP "prepare" 4 .IX Item "prepare" Prepares a new \s-1SQL\s0 statement to execute. Returns a statement handle, \&\f(CW$sth\fR \- instance of the DBD:XXX::st. It is neither required nor recommended to override this method. .IP "validate_FETCH_attr" 4 .IX Item "validate_FETCH_attr" Called by \f(CW\*(C`FETCH\*(C'\fR to allow inherited drivers do their own attribute name validation. Calling convention is similar to \f(CW\*(C`FETCH\*(C'\fR and the return value is the approved attribute name. .Sp .Vb 1 \& return $validated_attribute_name; .Ve .Sp In case of validation fails (e.g. accessing private attribute or similar), \&\f(CW\*(C`validate_FETCH_attr\*(C'\fR is permitted to throw an exception. .IP "\s-1FETCH\s0" 4 .IX Item "FETCH" Fetches an attribute of a \s-1DBI\s0 database object. Private handle attributes must have a prefix (this is mandatory). If a requested attribute is detected as a private attribute without a valid prefix, the driver prefix (written as \f(CW$drv_prefix\fR) is added. .Sp The driver prefix is extracted from the attribute name and verified against \&\f(CW\*(C`$dbh\->{ $drv_prefix . "valid_attrs" }\*(C'\fR (when it exists). If the requested attribute value is not listed as a valid attribute, this method croaks. If the attribute is valid and readonly (listed in \f(CW\*(C`$dbh\->{ $drv_prefix . "readonly_attrs" }\*(C'\fR when it exists), a real copy of the attribute value is returned. So it's not possible to modify \&\f(CW\*(C`f_valid_attrs\*(C'\fR from outside of DBI::DBD::SqlEngine::db or a derived class. .IP "validate_STORE_attr" 4 .IX Item "validate_STORE_attr" Called by \f(CW\*(C`STORE\*(C'\fR to allow inherited drivers do their own attribute name validation. Calling convention is similar to \f(CW\*(C`STORE\*(C'\fR and the return value is the approved attribute name followed by the approved new value. .Sp .Vb 1 \& return ($validated_attribute_name, $validated_attribute_value); .Ve .Sp In case of validation fails (e.g. accessing private attribute or similar), \&\f(CW\*(C`validate_STORE_attr\*(C'\fR is permitted to throw an exception (\f(CW\*(C`DBI::DBD::SqlEngine::db::validate_STORE_attr\*(C'\fR throws an exception when someone tries to assign value other than \f(CW\*(C`SQL_IC_UPPER .. SQL_IC_MIXED\*(C'\fR to \f(CW\*(C`$dbh\->{sql_identifier_case}\*(C'\fR or \&\f(CW\*(C`$dbh\->{sql_quoted_identifier_case}\*(C'\fR). .IP "\s-1STORE\s0" 4 .IX Item "STORE" Stores a database private attribute. Private handle attributes must have a prefix (this is mandatory). If a requested attribute is detected as a private attribute without a valid prefix, the driver prefix (written as \&\f(CW$drv_prefix\fR) is added. If the database handle has an attribute \&\f(CW\*(C`${drv_prefix}_valid_attrs\*(C'\fR \- for attribute names which are not listed in that hash, this method croaks. If the database handle has an attribute \&\f(CW\*(C`${drv_prefix}_readonly_attrs\*(C'\fR, only attributes which are not listed there can be stored (once they are initialized). Trying to overwrite such an immutable attribute forces this method to croak. .Sp An example of a valid attributes list can be found in \&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_valid_attributes\*(C'\fR. .IP "set_versions" 4 .IX Item "set_versions" This method sets the attributes \f(CW\*(C`f_version\*(C'\fR, \f(CW\*(C`sql_nano_version\*(C'\fR, \&\f(CW\*(C`sql_statement_version\*(C'\fR and (if not prohibited by a restrictive \&\f(CW\*(C`${prefix}_valid_attrs\*(C'\fR) \f(CW\*(C`${prefix}_version\*(C'\fR. .Sp This method is called at the end of the \f(CW\*(C`connect ()\*(C'\fR phase. .Sp When overriding this method, do not forget to invoke the superior one. .IP "init_valid_attributes" 4 .IX Item "init_valid_attributes" This method is called after the database handle is instantiated as the first attribute initialization. .Sp \&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_valid_attributes\*(C'\fR initializes the attributes \f(CW\*(C`sql_valid_attrs\*(C'\fR and \f(CW\*(C`sql_readonly_attrs\*(C'\fR. .Sp When overriding this method, do not forget to invoke the superior one, preferably before doing anything else. .IP "init_default_attributes" 4 .IX Item "init_default_attributes" This method is called after the database handle is instantiated to initialize the default attributes. It expects one argument: \f(CW$phase\fR. If \f(CW$phase\fR is not given, \f(CW\*(C`connect\*(C'\fR of \f(CW\*(C`DBI::DBD::SqlEngine::dr\*(C'\fR expects this is an old-fashioned driver which isn't capable of multi-phased initialization. .Sp \&\f(CW\*(C`DBI::DBD::SqlEngine::db::init_default_attributes\*(C'\fR initializes the attributes \f(CW\*(C`sql_identifier_case\*(C'\fR, \f(CW\*(C`sql_quoted_identifier_case\*(C'\fR, \&\f(CW\*(C`sql_handler\*(C'\fR, \f(CW\*(C`sql_init_order\*(C'\fR, \f(CW\*(C`sql_meta\*(C'\fR, \f(CW\*(C`sql_engine_version\*(C'\fR, \&\f(CW\*(C`sql_nano_version\*(C'\fR and \f(CW\*(C`sql_statement_version\*(C'\fR when SQL::Statement is available. .Sp It sets \f(CW\*(C`sql_init_order\*(C'\fR to the given \f(CW$phase\fR. .Sp When the derived implementor class provides the attribute to validate attributes (e.g. \f(CW\*(C`$dbh\->{dbm_valid_attrs} = {...};\*(C'\fR) or the attribute containing the immutable attributes (e.g. \f(CW\*(C`$dbh\->{dbm_readonly_attrs} = {...};\*(C'\fR), the attributes \f(CW\*(C`drv_valid_attrs\*(C'\fR, \f(CW\*(C`drv_readonly_attrs\*(C'\fR and \&\f(CW\*(C`drv_version\*(C'\fR are added (when available) to the list of valid and immutable attributes (where \f(CW\*(C`drv_\*(C'\fR is interpreted as the driver prefix). .IP "get_versions" 4 .IX Item "get_versions" This method is called by the code injected into the instantiated driver to provide the user callable driver method \f(CW\*(C`${prefix}versions\*(C'\fR (e.g. \&\f(CW\*(C`dbm_versions\*(C'\fR, \f(CW\*(C`csv_versions\*(C'\fR, ...). .Sp The DBI::DBD::SqlEngine implementation returns all version information known by DBI::DBD::SqlEngine (e.g. \s-1DBI\s0 version, Perl version, DBI::DBD::SqlEngine version and the \s-1SQL\s0 handler version). .Sp \&\f(CW\*(C`get_versions\*(C'\fR takes the \f(CW$dbh\fR as the first argument and optionally a second argument containing a table name. The second argument is not evaluated in \f(CW\*(C`DBI::DBD::SqlEngine::db::get_versions\*(C'\fR itself \- but might be in the future. .Sp If the derived implementor class provides a method named \&\f(CW\*(C`get_${drv_prefix}versions\*(C'\fR, this is invoked and the return value of it is associated to the derived driver name: .Sp .Vb 4 \& if (my $dgv = $dbh\->{ImplementorClass}\->can ("get_" . $drv_prefix . "versions") { \& (my $derived_driver = $dbh\->{ImplementorClass}) =~ s/::db$//; \& $versions{$derived_driver} = &$dgv ($dbh, $table); \& } .Ve .Sp Override it to add more version information about your module, (e.g. some kind of parser version in case of \s-1DBD::CSV, ...\s0), if one line is not enough room to provide all relevant information. .IP "sql_parser_object" 4 .IX Item "sql_parser_object" Returns a SQL::Parser instance, when \f(CW\*(C`sql_handler\*(C'\fR is set to \&\*(L"SQL::Statement\*(R". The parser instance is stored in \f(CW\*(C`sql_parser_object\*(C'\fR. .Sp It is not recommended to override this method. .IP "disconnect" 4 .IX Item "disconnect" Disconnects from a database. All local table information is discarded and the \f(CW\*(C`Active\*(C'\fR attribute is set to 0. .IP "type_info_all" 4 .IX Item "type_info_all" Returns information about all the types supported by DBI::DBD::SqlEngine. .IP "table_info" 4 .IX Item "table_info" Returns a statement handle which is prepared to deliver information about all known tables. .IP "list_tables" 4 .IX Item "list_tables" Returns a list of all known table names. .IP "quote" 4 .IX Item "quote" Quotes a string for use in \s-1SQL\s0 statements. .IP "commit" 4 .IX Item "commit" Warns about a useless call (if warnings enabled) and returns. DBI::DBD::SqlEngine is typically a driver which commits every action instantly when executed. .IP "rollback" 4 .IX Item "rollback" Warns about a useless call (if warnings enabled) and returns. DBI::DBD::SqlEngine is typically a driver which commits every action instantly when executed. .PP \fIAttributes used by \f(CI\*(C`DBI::DBD::SqlEngine::db\*(C'\fI:\fR .IX Subsection "Attributes used by DBI::DBD::SqlEngine::db:" .PP This section describes attributes which are important to developers of \s-1DBI\s0 Database Drivers derived from \f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR. .IP "sql_init_order" 4 .IX Item "sql_init_order" This attribute contains a hash with priorities as key and an array containing the \f(CW$dbh\fR attributes to be initialized during before/after other attributes. .Sp \&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR initializes following attributes: .Sp .Vb 4 \& $dbh\->{sql_init_order} = { \& 0 => [qw( Profile RaiseError PrintError AutoCommit )], \& 90 => [ "sql_meta", $dbh\->{$drv_pfx_meta} ? $dbh\->{$drv_pfx_meta} : () ] \& } .Ve .Sp The default priority of not listed attribute keys is \f(CW50\fR. It is well known that a lot of attributes needed to be set before some table settings are initialized. For example, for \s-1DBD::DBM\s0, when using .Sp .Vb 11 \& my $dbh = DBI\->connect( "dbi:DBM:", undef, undef, { \& f_dir => "/path/to/dbm/databases", \& dbm_type => "BerkeleyDB", \& dbm_mldbm => "JSON", # use MLDBM::Serializer::JSON \& dbm_tables => { \& quick => { \& dbm_type => "GDBM_File", \& dbm_MLDBM => "FreezeThaw" \& } \& } \& }); .Ve .Sp This defines a known table \f(CW\*(C`quick\*(C'\fR which uses the GDBM_File backend and FreezeThaw as serializer instead of the overall default BerkeleyDB and \&\s-1JSON\s0. \fBBut\fR all files containing the table data have to be searched in \&\f(CW\*(C`$dbh\->{f_dir}\*(C'\fR, which requires \f(CW\*(C`$dbh\->{f_dir}\*(C'\fR must be initialized before \f(CW\*(C`$dbh\->{sql_meta}\->{quick}\*(C'\fR is initialized by \&\f(CW\*(C`bootstrap_table_meta\*(C'\fR method of \*(L"DBI::DBD::SqlEngine::Table\*(R" to get \&\f(CW\*(C`$dbh\->{sql_meta}\->{quick}\->{f_dir}\*(C'\fR being initialized properly. .IP "sql_init_phase" 4 .IX Item "sql_init_phase" This attribute is only set during the initialization steps of the \s-1DBI\s0 Database Driver. It contains the value of the currently run initialization phase. Currently supported phases are \fIphase 0\fR and \fIphase 1\fR. This attribute is set in \f(CW\*(C`init_default_attributes\*(C'\fR and removed in \f(CW\*(C`init_done\*(C'\fR. .IP "sql_engine_in_gofer" 4 .IX Item "sql_engine_in_gofer" This value has a true value in case of this driver is operated via DBD::Gofer. The impact of being operated via Gofer is a read-only driver (not read-only databases!), so you cannot modify any attributes later \- neither any table settings. \fBBut\fR you won't get an error in cases you modify table attributes, so please carefully watch \&\f(CW\*(C`sql_engine_in_gofer\*(C'\fR. .IP "sql_table_source" 4 .IX Item "sql_table_source" Names a class which is responsible for delivering \fIdata sources\fR and \&\fIavailable tables\fR (Database Driver related). \fIdata sources\fR here refers to \*(L"data_sources\*(R" in \s-1DBI\s0, not \f(CW\*(C`sql_data_source\*(C'\fR. .Sp See \*(L"DBI::DBD::SqlEngine::TableSource\*(R" for details. .IP "sql_data_source" 4 .IX Item "sql_data_source" Name a class which is responsible for handling table resources open and completing table names requested via \s-1SQL\s0 statements. .Sp See \*(L"DBI::DBD::SqlEngine::DataSource\*(R" for details. .IP "sql_dialect" 4 .IX Item "sql_dialect" Controls the dialect understood by SQL::Parser. Possible values (delivery state of SQL::Statement): .Sp .Vb 3 \& * ANSI \& * CSV \& * AnyData .Ve .Sp Defaults to \*(L"\s-1CSV\*(R".\s0 Because an SQL::Parser is instantiated only once and SQL::Parser doesn't allow one to modify the dialect once instantiated, it's strongly recommended to set this flag before any statement is executed (best place is connect attribute hash). .SS "DBI::DBD::SqlEngine::st" .IX Subsection "DBI::DBD::SqlEngine::st" Contains the methods to deal with prepared statement handles: .IP "bind_param" 4 .IX Item "bind_param" Common routine to bind placeholders to a statement for execution. It is dangerous to override this method without detailed knowledge about the DBI::DBD::SqlEngine internal storage structure. .IP "execute" 4 .IX Item "execute" Executes a previously prepared statement (with placeholders, if any). .IP "finish" 4 .IX Item "finish" Finishes a statement handle, discards all buffered results. The prepared statement is not discarded so the statement can be executed again. .IP "fetch" 4 .IX Item "fetch" Fetches the next row from the result-set. This method may be rewritten in a later version and if it's overridden in a derived class, the derived implementation should not rely on the storage details. .IP "fetchrow_arrayref" 4 .IX Item "fetchrow_arrayref" Alias for \f(CW\*(C`fetch\*(C'\fR. .IP "\s-1FETCH\s0" 4 .IX Item "FETCH" Fetches statement handle attributes. Supported attributes (for full overview see \*(L"Statement Handle Attributes\*(R" in \s-1DBI\s0) are \f(CW\*(C`NAME\*(C'\fR, \f(CW\*(C`TYPE\*(C'\fR, \f(CW\*(C`PRECISION\*(C'\fR and \f(CW\*(C`NULLABLE\*(C'\fR. Each column is returned as \f(CW\*(C`NULLABLE\*(C'\fR which might be wrong depending on the derived backend storage. If the statement handle has private attributes, they can be fetched using this method, too. \fBNote\fR that statement attributes are not associated with any table used in this statement. .Sp This method usually requires extending in a derived implementation. See \s-1DBD::CSV\s0 or \s-1DBD::DBM\s0 for some example. .IP "\s-1STORE\s0" 4 .IX Item "STORE" Allows storing of statement private attributes. No special handling is currently implemented here. .IP "rows" 4 .IX Item "rows" Returns the number of rows affected by the last execute. This method might return \f(CW\*(C`undef\*(C'\fR. .SS "DBI::DBD::SqlEngine::TableSource" .IX Subsection "DBI::DBD::SqlEngine::TableSource" Provides data sources and table information on database driver and database handle level. .PP .Vb 1 \& package DBI::DBD::SqlEngine::TableSource; \& \& sub data_sources ($;$) \& { \& my ( $class, $drh, $attrs ) = @_; \& ... \& } \& \& sub avail_tables \& { \& my ( $class, $drh ) = @_; \& ... \& } .Ve .PP The \f(CW\*(C`data_sources\*(C'\fR method is called when the user invokes any of the following: .PP .Vb 2 \& @ary = DBI\->data_sources($driver); \& @ary = DBI\->data_sources($driver, \e%attr); \& \& @ary = $dbh\->data_sources(); \& @ary = $dbh\->data_sources(\e%attr); .Ve .PP The \f(CW\*(C`avail_tables\*(C'\fR method is called when the user invokes any of the following: .PP .Vb 1 \& @names = $dbh\->tables( $catalog, $schema, $table, $type ); \& \& $sth = $dbh\->table_info( $catalog, $schema, $table, $type ); \& $sth = $dbh\->table_info( $catalog, $schema, $table, $type, \e%attr ); \& \& $dbh\->func( "list_tables" ); .Ve .PP Every time where an \f(CW\*(C`\e%attr\*(C'\fR argument can be specified, this \f(CW\*(C`\e%attr\*(C'\fR object's \f(CW\*(C`sql_table_source\*(C'\fR attribute is preferred over the \f(CW$dbh\fR attribute or the driver default. .SS "DBI::DBD::SqlEngine::DataSource" .IX Subsection "DBI::DBD::SqlEngine::DataSource" Provides base functionality for dealing with tables. It is primarily designed for allowing transparent access to files on disk or already opened (file\-)streams (e.g. for \s-1DBD::CSV\s0). .PP Derived classes shall be restricted to similar functionality, too (e.g. opening streams from an archive, transparently compress/uncompress log files before parsing them, .PP .Vb 1 \& package DBI::DBD::SqlEngine::DataSource; \& \& sub complete_table_name ($$;$) \& { \& my ( $self, $meta, $table, $respect_case ) = @_; \& ... \& } .Ve .PP The method \f(CW\*(C`complete_table_name\*(C'\fR is called when first setting up the \&\fImeta information\fR for a table: .PP .Vb 1 \& "SELECT user.id, user.name, user.shell FROM user WHERE ..." .Ve .PP results in opening the table \f(CW\*(C`user\*(C'\fR. First step of the table open process is completing the name. Let's imagine you're having a \s-1DBD::CSV\s0 handle with following settings: .PP .Vb 3 \& $dbh\->{sql_identifier_case} = SQL_IC_LOWER; \& $dbh\->{f_ext} = \*(Aq.lst\*(Aq; \& $dbh\->{f_dir} = \*(Aq/data/web/adrmgr\*(Aq; .Ve .PP Those settings will result in looking for files matching \&\f(CW\*(C`[Uu][Ss][Ee][Rr](\e.lst)?$\*(C'\fR in \f(CW\*(C`/data/web/adrmgr/\*(C'\fR. The scanning of the directory \f(CW\*(C`/data/web/adrmgr/\*(C'\fR and the pattern match check will be done in \f(CW\*(C`DBD::File::DataSource::File\*(C'\fR by the \f(CW\*(C`complete_table_name\*(C'\fR method. .PP If you intend to provide other sources of data streams than files, in addition to provide an appropriate \f(CW\*(C`complete_table_name\*(C'\fR method, a method to open the resource is required: .PP .Vb 1 \& package DBI::DBD::SqlEngine::DataSource; \& \& sub open_data ($) \& { \& my ( $self, $meta, $attrs, $flags ) = @_; \& ... \& } .Ve .PP After the method \f(CW\*(C`open_data\*(C'\fR has been run successfully, the table's meta information are in a state which allows the table's data accessor methods will be able to fetch/store row information. Implementation details heavily depends on the table implementation, whereby the most famous is surely DBD::File::Table. .SS "DBI::DBD::SqlEngine::Statement" .IX Subsection "DBI::DBD::SqlEngine::Statement" Derives from DBI::SQL::Nano::Statement for unified naming when deriving new drivers. No additional feature is provided from here. .SS "DBI::DBD::SqlEngine::Table" .IX Subsection "DBI::DBD::SqlEngine::Table" Derives from DBI::SQL::Nano::Table for unified naming when deriving new drivers. .PP You should consult the documentation of \f(CW\*(C`SQL::Eval::Table\*(C'\fR (see SQL::Eval) to get more information about the abstract methods of the table's base class you have to override and a description of the table meta information expected by the \s-1SQL\s0 engines. .IP "bootstrap_table_meta" 4 .IX Item "bootstrap_table_meta" Initializes a table meta structure. Can be safely overridden in a derived class, as long as the \f(CW\*(C`SUPER\*(C'\fR method is called at the end of the overridden method. .Sp It copies the following attributes from the database into the table meta data \&\f(CW\*(C`$dbh\->{ReadOnly}\*(C'\fR into \f(CW\*(C`$meta\->{readonly}\*(C'\fR, \f(CW\*(C`sql_identifier_case\*(C'\fR and \f(CW\*(C`sql_data_source\*(C'\fR and makes them sticky to the table. .Sp This method should be called before you attempt to map between file name and table name to ensure the correct directory, extension etc. are used. .IP "init_table_meta" 4 .IX Item "init_table_meta" Initializes more attributes of the table meta data \- usually more expensive ones (e.g. those which require class instantiations) \- when the file name and the table name could mapped. .IP "get_table_meta" 4 .IX Item "get_table_meta" Returns the table meta data. If there are none for the required table, a new one is initialized. When after bootstrapping a new \fItable_meta\fR and completing the table name a mapping can be established between an existing \fItable_meta\fR and the new bootstrapped one, the already existing is used and a mapping shortcut between the recent used table name and the already known table name is hold in \f(CW\*(C`$dbh\->{sql_meta_map}\*(C'\fR. When it fails, nothing is returned. On success, the name of the table and the meta data structure is returned. .IP "get_table_meta_attr" 4 .IX Item "get_table_meta_attr" Returns a single attribute from the table meta data. If the attribute name appears in \f(CW%compat_map\fR, the attribute name is updated from there. .IP "set_table_meta_attr" 4 .IX Item "set_table_meta_attr" Sets a single attribute in the table meta data. If the attribute name appears in \f(CW%compat_map\fR, the attribute name is updated from there. .IP "table_meta_attr_changed" 4 .IX Item "table_meta_attr_changed" Called when an attribute of the meta data is modified. .Sp If the modified attribute requires to reset a calculated attribute, the calculated attribute is reset (deleted from meta data structure) and the \fIinitialized\fR flag is removed, too. The decision is made based on \&\f(CW%register_reset_on_modify\fR. .IP "register_reset_on_modify" 4 .IX Item "register_reset_on_modify" Allows \f(CW\*(C`set_table_meta_attr\*(C'\fR to reset meta attributes when special attributes are modified. For DBD::File, modifying one of \f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \&\f(CW\*(C`f_ext\*(C'\fR or \f(CW\*(C`f_lockfile\*(C'\fR will reset \f(CW\*(C`f_fqfn\*(C'\fR. \s-1DBD::DBM\s0 extends the list for \f(CW\*(C`dbm_type\*(C'\fR and \f(CW\*(C`dbm_mldbm\*(C'\fR to reset the value of \f(CW\*(C`dbm_tietype\*(C'\fR. .Sp If your \s-1DBD\s0 has calculated values in the meta data area, then call \&\f(CW\*(C`register_reset_on_modify\*(C'\fR: .Sp .Vb 2 \& my %reset_on_modify = ( "xxx_foo" => "xxx_bar" ); \& _\|_PACKAGE_\|_\->register_reset_on_modify( \e%reset_on_modify ); .Ve .IP "register_compat_map" 4 .IX Item "register_compat_map" Allows \f(CW\*(C`get_table_meta_attr\*(C'\fR and \f(CW\*(C`set_table_meta_attr\*(C'\fR to update the attribute name to the current favored one: .Sp .Vb 3 \& # from DBD::DBM \& my %compat_map = ( "dbm_ext" => "f_ext" ); \& _\|_PACKAGE_\|_\->register_compat_map( \e%compat_map ); .Ve .IP "open_data" 4 .IX Item "open_data" Called to open the table's data storage. This is silently forwarded to \f(CW\*(C`$meta\->{sql_data_source}\->open_data()\*(C'\fR. .Sp After this is done, a derived class might add more steps in an overridden \&\f(CW\*(C`open_file\*(C'\fR method. .IP "new" 4 .IX Item "new" Instantiates the table. This is done in 3 steps: .Sp .Vb 3 \& 1. get the table meta data \& 2. open the data file \& 3. bless the table data structure using inherited constructor new .Ve .Sp It is not recommended to override the constructor of the table class. Find a reasonable place to add you extensions in one of the above four methods. .SH "AUTHOR" .IX Header "AUTHOR" The module DBI::DBD::SqlEngine is currently maintained by .PP H.Merijn Brand < h.m.brand at xs4all.nl > and Jens Rehsack < rehsack at googlemail.com > .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack .PP All rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. man/man3/Mozilla::CA.3pm000044400000006757152462503210010612 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Mozilla::CA 3" .TH Mozilla::CA 3 "2021-10-01" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mozilla::CA \- Mozilla's CA cert bundle in PEM format .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use IO::Socket::SSL; \& use Mozilla::CA; \& \& my $host = "www.paypal.com"; \& my $client = IO::Socket::SSL\->new( \& PeerHost => "$host:443", \& SSL_verify_mode => 0x02, \& SSL_ca_file => Mozilla::CA::SSL_ca_file(), \& ) \& || die "Can\*(Aqt connect: $@"; \& \& $client\->verify_hostname($host, "http") \& || die "hostname verification failure"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Mozilla::CA provides a copy of Mozilla's bundle of Certificate Authority certificates in a form that can be consumed by modules and libraries based on OpenSSL. .PP The module provide a single function: .IP "\fBSSL_ca_file()\fR" 4 .IX Item "SSL_ca_file()" Returns the absolute path to the Mozilla's \s-1CA\s0 cert bundle \s-1PEM\s0 file. .SH "SEE ALSO" .IX Header "SEE ALSO" .SH "LICENSE" .IX Header "LICENSE" For the bundled Mozilla \s-1CA PEM\s0 file the following applies: .Sp .RS 4 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the \s-1MPL\s0 was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. .RE .PP The Mozilla::CA distribution itself is available under the same license. man/man3/DBD::DBM.3pm000044400000120310152462503210007671 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::DBM 3" .TH DBD::DBM 3 "2013-09-08" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::DBM \- a DBI driver for DBM & MLDBM files .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 5 \& use DBI; \& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); # defaults to SDBM_File \& $dbh = DBI\->connect(\*(AqDBI:DBM(RaiseError=1):\*(Aq); # defaults to SDBM_File \& $dbh = DBI\->connect(\*(Aqdbi:DBM:dbm_type=DB_File\*(Aq); # defaults to DB_File \& $dbh = DBI\->connect(\*(Aqdbi:DBM:dbm_mldbm=Storable\*(Aq); # MLDBM with SDBM_File \& \& # or \& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef); \& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { \& f_ext => \*(Aq.db/r\*(Aq, \& f_dir => \*(Aq/path/to/dbfiles/\*(Aq, \& f_lockfile => \*(Aq.lck\*(Aq, \& dbm_type => \*(AqBerkeleyDB\*(Aq, \& dbm_mldbm => \*(AqFreezeThaw\*(Aq, \& dbm_store_metadata => 1, \& dbm_berkeley_flags => { \& \*(Aq\-Cachesize\*(Aq => 1000, # set a ::Hash flag \& }, \& }); .Ve .PP and other variations on \fBconnect()\fR as shown in the \s-1DBI\s0 docs, DBD::File metadata and \*(L"Metadata\*(R" shown below. .PP Use standard \s-1DBI\s0 prepare, execute, fetch, placeholders, etc., see \*(L"\s-1QUICK START\*(R"\s0 for an example. .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1DBD::DBM\s0 is a database management system that works right out of the box. If you have a standard installation of Perl and \s-1DBI\s0 you can begin creating, accessing, and modifying simple database tables without any further modules. You can add other modules (e.g., SQL::Statement, DB_File etc) for improved functionality. .PP The module uses a \s-1DBM\s0 file storage layer. \s-1DBM\s0 file storage is common on many platforms and files can be created with it in many programming languages using different APIs. That means, in addition to creating files with \s-1DBI/SQL,\s0 you can also use \s-1DBI/SQL\s0 to access and modify files created by other \s-1DBM\s0 modules and programs and vice versa. \fBNote\fR that in those cases it might be necessary to use a common subset of the provided features. .PP \&\s-1DBM\s0 files are stored in binary format optimized for quick retrieval when using a key field. That optimization can be used advantageously to make \s-1DBD::DBM SQL\s0 operations that use key fields very fast. There are several different \*(L"flavors\*(R" of \s-1DBM\s0 which use different storage formats supported by perl modules such as SDBM_File and \s-1MLDBM.\s0 This module supports all of the flavors that perl supports and, when used with \s-1MLDBM,\s0 supports tables with any number of columns and insertion of Perl objects into tables. .PP \&\s-1DBD::DBM\s0 has been tested with the following \s-1DBM\s0 types: SDBM_File, NDBM_File, ODBM_File, GDBM_File, DB_File, BerkeleyDB. Each type was tested both with and without \s-1MLDBM\s0 and with the Data::Dumper, Storable, FreezeThaw, \s-1YAML\s0 and \s-1JSON\s0 serializers using the DBI::SQL::Nano or the SQL::Statement engines. .SH "QUICK START" .IX Header "QUICK START" \&\s-1DBD::DBM\s0 operates like all other \s-1DBD\s0 drivers \- it's basic syntax and operation is specified by \s-1DBI.\s0 If you're not familiar with \s-1DBI,\s0 you should start by reading \s-1DBI\s0 and the documents it points to and then come back and read this file. If you are familiar with \s-1DBI,\s0 you already know most of what you need to know to operate this module. Just jump in and create a test script something like the one shown below. .PP You should be aware that there are several options for the \s-1SQL\s0 engine underlying \s-1DBD::DBM,\s0 see \*(L"Supported \s-1SQL\s0 syntax\*(R". There are also many options for \s-1DBM\s0 support, see especially the section on \*(L"Adding multi-column support with \s-1MLDBM\*(R"\s0. .PP But here's a sample to get you started. .PP .Vb 10 \& use DBI; \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); \& $dbh\->{RaiseError} = 1; \& for my $sql( split /;\en+/," \& CREATE TABLE user ( user_name TEXT, phone TEXT ); \& INSERT INTO user VALUES (\*(AqFred Bloggs\*(Aq,\*(Aq233\-7777\*(Aq); \& INSERT INTO user VALUES (\*(AqSanjay Patel\*(Aq,\*(Aq777\-3333\*(Aq); \& INSERT INTO user VALUES (\*(AqJunk\*(Aq,\*(Aqxxx\-xxxx\*(Aq); \& DELETE FROM user WHERE user_name = \*(AqJunk\*(Aq; \& UPDATE user SET phone = \*(Aq999\-4444\*(Aq WHERE user_name = \*(AqSanjay Patel\*(Aq; \& SELECT * FROM user \& "){ \& my $sth = $dbh\->prepare($sql); \& $sth\->execute; \& $sth\->dump_results if $sth\->{NUM_OF_FIELDS}; \& } \& $dbh\->disconnect; .Ve .SH "USAGE" .IX Header "USAGE" This section will explain some usage cases in more detail. To get an overview about the available attributes, see \*(L"Metadata\*(R". .SS "Specifying Files and Directories" .IX Subsection "Specifying Files and Directories" \&\s-1DBD::DBM\s0 will automatically supply an appropriate file extension for the type of \s-1DBM\s0 you are using. For example, if you use SDBM_File, a table called \*(L"fruit\*(R" will be stored in two files called \*(L"fruit.pag\*(R" and \&\*(L"fruit.dir\*(R". You should \fBnever\fR specify the file extensions in your \s-1SQL\s0 statements. .PP \&\s-1DBD::DBM\s0 recognizes following default extensions for following types: .IP ".pag/r" 4 .IX Item ".pag/r" Chosen for dbm_type \f(CW\*(C`SDBM_File\*(C'\fR, \f(CW\*(C`ODBM_File\*(C'\fR and \f(CW\*(C`NDBM_File\*(C'\fR when an implementation is detected which wraps \f(CW\*(C`\-ldbm\*(C'\fR for \&\f(CW\*(C`NDBM_File\*(C'\fR (e.g. Solaris, \s-1AIX, ...\s0). .Sp For those types, the \f(CW\*(C`.dir\*(C'\fR extension is recognized, too (for being deleted when dropping a table). .IP ".db/r" 4 .IX Item ".db/r" Chosen for dbm_type \f(CW\*(C`NDBM_File\*(C'\fR when an implementation is detected which wraps BerkeleyDB 1.x for \f(CW\*(C`NDBM_File\*(C'\fR (typically \s-1BSD\s0's, Darwin). .PP \&\f(CW\*(C`GDBM_File\*(C'\fR, \f(CW\*(C`DB_File\*(C'\fR and \f(CW\*(C`BerkeleyDB\*(C'\fR don't usually use a file extension. .PP If your \s-1DBM\s0 type uses an extension other than one of the recognized types of extensions, you should set the \fIf_ext\fR attribute to the extension \fBand\fR file a bug report as described in \s-1DBI\s0 with the name of the implementation and extension so we can add it to \s-1DBD::DBM.\s0 Thanks in advance for that :\-). .PP .Vb 2 \& $dbh = DBI\->connect(\*(Aqdbi:DBM:f_ext=.db\*(Aq); # .db extension is used \& $dbh = DBI\->connect(\*(Aqdbi:DBM:f_ext=\*(Aq); # no extension is used \& \& # or \& $dbh\->{f_ext}=\*(Aq.db\*(Aq; # global setting \& $dbh\->{f_meta}\->{\*(Aqqux\*(Aq}\->{f_ext}=\*(Aq.db\*(Aq; # setting for table \*(Aqqux\*(Aq .Ve .PP By default files are assumed to be in the current working directory. To use other directories specify the \fIf_dir\fR attribute in either the connect string or by setting the database handle attribute. .PP For example, this will look for the file /foo/bar/fruit (or /foo/bar/fruit.pag for \s-1DBM\s0 types that use that extension) .PP .Vb 6 \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:f_dir=/foo/bar\*(Aq); \& # and this will too: \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); \& $dbh\->{f_dir} = \*(Aq/foo/bar\*(Aq; \& # but this is recommended \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { f_dir => \*(Aq/foo/bar\*(Aq } ); \& \& # now you can do \& my $ary = $dbh\->selectall_arrayref(q{ SELECT x FROM fruit }); .Ve .PP You can also use delimited identifiers to specify paths directly in \s-1SQL\s0 statements. This looks in the same place as the two examples above but without setting \fIf_dir\fR: .PP .Vb 4 \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); \& my $ary = $dbh\->selectall_arrayref(q{ \& SELECT x FROM "/foo/bar/fruit" \& }); .Ve .PP You can also tell \s-1DBD::DBM\s0 to use a specified path for a specific table: .PP .Vb 1 \& $dbh\->{dbm_tables}\->{f}\->{file} = q(/foo/bar/fruit); .Ve .PP Please be aware that you cannot specify this during connection. .PP If you have SQL::Statement installed, you can use table aliases: .PP .Vb 4 \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); \& my $ary = $dbh\->selectall_arrayref(q{ \& SELECT f.x FROM "/foo/bar/fruit" AS f \& }); .Ve .PP See the \*(L"\s-1GOTCHAS AND WARNINGS\*(R"\s0 for using \s-1DROP\s0 on tables. .SS "Table locking and \fBflock()\fP" .IX Subsection "Table locking and flock()" Table locking is accomplished using a lockfile which has the same basename as the table's file but with the file extension '.lck' (or a lockfile extension that you supply, see below). This lock file is created with the table during a \s-1CREATE\s0 and removed during a \s-1DROP.\s0 Every time the table itself is opened, the lockfile is \fBflocked()\fR. For \&\s-1SELECT,\s0 this is a shared lock. For all other operations, it is an exclusive lock (except when you specify something different using the \&\fIf_lock\fR attribute). .PP Since the locking depends on \fBflock()\fR, it only works on operating systems that support \fBflock()\fR. In cases where \fBflock()\fR is not implemented, \s-1DBD::DBM\s0 will simply behave as if the \fBflock()\fR had occurred although no actual locking will happen. Read the documentation for \fBflock()\fR for more information. .PP Even on those systems that do support \fBflock()\fR, locking is only advisory \- as is always the case with \fBflock()\fR. This means that if another program tries to access the table file while \s-1DBD::DBM\s0 has the table locked, that other program will *succeed* at opening unless it is also using flock on the '.lck' file. As a result \s-1DBD::DBM\s0's locking only really applies to other programs using \s-1DBD::DBM\s0 or other program written to cooperate with \s-1DBD::DBM\s0 locking. .SS "Specifying the \s-1DBM\s0 type" .IX Subsection "Specifying the DBM type" Each \*(L"flavor\*(R" of \s-1DBM\s0 stores its files in a different format and has different capabilities and limitations. See AnyDBM_File for a comparison of \s-1DBM\s0 types. .PP By default, \s-1DBD::DBM\s0 uses the \f(CW\*(C`SDBM_File\*(C'\fR type of storage since \&\f(CW\*(C`SDBM_File\*(C'\fR comes with Perl itself. If you have other types of \&\s-1DBM\s0 storage available, you can use any of them with \s-1DBD::DBM.\s0 It is strongly recommended to use at least \f(CW\*(C`DB_File\*(C'\fR, because \f(CW\*(C`SDBM_File\*(C'\fR has quirks and limitations and \f(CW\*(C`ODBM_file\*(C'\fR, \f(CW\*(C`NDBM_File\*(C'\fR and \f(CW\*(C`GDBM_File\*(C'\fR are not always available. .PP You can specify the \s-1DBM\s0 type using the \fIdbm_type\fR attribute which can be set in the connection string or with \f(CW\*(C`$dbh\->{dbm_type}\*(C'\fR and \&\f(CW\*(C`$dbh\->{f_meta}\->{$table_name}\->{type}\*(C'\fR for per-table settings in cases where a single script is accessing more than one kind of \s-1DBM\s0 file. .PP In the connection string, just set \f(CW\*(C`dbm_type=TYPENAME\*(C'\fR where \&\f(CW\*(C`TYPENAME\*(C'\fR is any \s-1DBM\s0 type such as GDBM_File, DB_File, etc. Do \fInot\fR use \s-1MLDBM\s0 as your \fIdbm_type\fR as that is set differently, see below. .PP .Vb 2 \& my $dbh=DBI\->connect(\*(Aqdbi:DBM:\*(Aq); # uses the default SDBM_File \& my $dbh=DBI\->connect(\*(Aqdbi:DBM:dbm_type=GDBM_File\*(Aq); # uses the GDBM_File \& \& # You can also use $dbh\->{dbm_type} to set the DBM type for the connection: \& $dbh\->{dbm_type} = \*(AqDB_File\*(Aq; # set the global DBM type \& print $dbh\->{dbm_type}; # display the global DBM type .Ve .PP If you have several tables in your script that use different \s-1DBM\s0 types, you can use the \f(CW$dbh\fR\->{dbm_tables} hash to store different settings for the various tables. You can even use this to perform joins on files that have completely different storage mechanisms. .PP .Vb 2 \& # sets global default of GDBM_File \& my $dbh\->(\*(Aqdbi:DBM:type=GDBM_File\*(Aq); \& \& # overrides the global setting, but only for the tables called \& # I and I \& my $dbh\->{f_meta}\->{foo}\->{dbm_type} = \*(AqDB_File\*(Aq; \& my $dbh\->{f_meta}\->{bar}\->{dbm_type} = \*(AqBerkeleyDB\*(Aq; \& \& # prints the dbm_type for the table "foo" \& print $dbh\->{f_meta}\->{foo}\->{dbm_type}; .Ve .PP \&\fBNote\fR that you must change the \fIdbm_type\fR of a table before you access it for first time. .SS "Adding multi-column support with \s-1MLDBM\s0" .IX Subsection "Adding multi-column support with MLDBM" Most of the \s-1DBM\s0 types only support two columns and even if it would support more, \s-1DBD::DBM\s0 would only use two. However a \s-1CPAN\s0 module called \s-1MLDBM\s0 overcomes this limitation by allowing more than two columns. \s-1MLDBM\s0 does this by serializing the data \- basically it puts a reference to an array into the second column. It can also put almost any kind of Perl object or even \fBPerl coderefs\fR into columns. .PP If you want more than two columns, you \fBmust\fR install \s-1MLDBM.\s0 It's available for many platforms and is easy to install. .PP \&\s-1MLDBM\s0 is by default distributed with three serializers \- Data::Dumper, Storable, and FreezeThaw. Data::Dumper is the default and Storable is the fastest. \s-1MLDBM\s0 can also make use of user-defined serialization methods or other serialization modules (e.g. \s-1YAML::MLDBM\s0 or MLDBM::Serializer::JSON. You select the serializer using the \&\fIdbm_mldbm\fR attribute. .PP Some examples: .PP .Vb 10 \& $dbh=DBI\->connect(\*(Aqdbi:DBM:dbm_mldbm=Storable\*(Aq); # use MLDBM with Storable \& $dbh=DBI\->connect( \& \*(Aqdbi:DBM:dbm_mldbm=MySerializer\*(Aq # use MLDBM with a user defined module \& ); \& $dbh=DBI\->connect(\*(Aqdbi::dbm:\*(Aq, undef, \& undef, { dbm_mldbm => \*(AqYAML\*(Aq }); # use 3rd party serializer \& $dbh\->{dbm_mldbm} = \*(AqYAML\*(Aq; # same as above \& print $dbh\->{dbm_mldbm} # show the MLDBM serializer \& $dbh\->{f_meta}\->{foo}\->{dbm_mldbm}=\*(AqData::Dumper\*(Aq; # set Data::Dumper for table "foo" \& print $dbh\->{f_meta}\->{foo}\->{mldbm}; # show serializer for table "foo" .Ve .PP \&\s-1MLDBM\s0 works on top of other \s-1DBM\s0 modules so you can also set a \s-1DBM\s0 type along with setting dbm_mldbm. The examples above would default to using SDBM_File with \s-1MLDBM.\s0 If you wanted GDBM_File instead, here's how: .PP .Vb 5 \& # uses DB_File with MLDBM and Storable \& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { \& dbm_type => \*(AqDB_File\*(Aq, \& dbm_mldbm => \*(AqStorable\*(Aq, \& }); .Ve .PP SDBM_File, the default \fIdbm_type\fR is quite limited, so if you are going to use \s-1MLDBM,\s0 you should probably use a different type, see AnyDBM_File. .PP See below for some \*(L"\s-1GOTCHAS AND WARNINGS\*(R"\s0 about \s-1MLDBM.\s0 .SS "Support for Berkeley \s-1DB\s0" .IX Subsection "Support for Berkeley DB" The Berkeley \s-1DB\s0 storage type is supported through two different Perl modules \- DB_File (which supports only features in old versions of Berkeley \&\s-1DB\s0) and BerkeleyDB (which supports all versions). \s-1DBD::DBM\s0 supports specifying either \*(L"DB_File\*(R" or \*(L"BerkeleyDB\*(R" as a \fIdbm_type\fR, with or without \s-1MLDBM\s0 support. .PP The \*(L"BerkeleyDB\*(R" dbm_type is experimental and it's interface is likely to change. It currently defaults to BerkeleyDB::Hash and does not currently support ::Btree or ::Recno. .PP With BerkeleyDB, you can specify initialization flags by setting them in your script like this: .PP .Vb 12 \& use BerkeleyDB; \& my $env = new BerkeleyDB::Env \-Home => $dir; # and/or other Env flags \& $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { \& dbm_type => \*(AqBerkeleyDB\*(Aq, \& dbm_mldbm => \*(AqStorable\*(Aq, \& dbm_berkeley_flags => { \& \*(AqDB_CREATE\*(Aq => DB_CREATE, # pass in constants \& \*(AqDB_RDONLY\*(Aq => DB_RDONLY, # pass in constants \& \*(Aq\-Cachesize\*(Aq => 1000, # set a ::Hash flag \& \*(Aq\-Env\*(Aq => $env, # pass in an environment \& }, \& }); .Ve .PP Do \fInot\fR set the \-Flags or \-Filename flags as those are determined and overwritten by the \s-1SQL\s0 (e.g. \-Flags => \s-1DB_RDONLY\s0 is set automatically when you issue a \s-1SELECT\s0 statement). .PP Time has not permitted us to provide support in this release of \s-1DBD::DBM\s0 for further Berkeley \s-1DB\s0 features such as transactions, concurrency, locking, etc. We will be working on these in the future and would value suggestions, patches, etc. .PP See DB_File and BerkeleyDB for further details. .SS "Optimizing the use of key fields" .IX Subsection "Optimizing the use of key fields" Most \*(L"flavors\*(R" of \s-1DBM\s0 have only two physical columns (but can contain multiple logical columns as explained above in \&\*(L"Adding multi-column support with \s-1MLDBM\*(R"\s0). They work similarly to a Perl hash with the first column serving as the key. Like a Perl hash, \s-1DBM\s0 files permit you to do quick lookups by specifying the key and thus avoid looping through all records (supported by DBI::SQL::Nano only). Also like a Perl hash, the keys must be unique. It is impossible to create two records with the same key. To put this more simply and in \s-1SQL\s0 terms, the key column functions as the \fI\s-1PRIMARY KEY\s0\fR or \s-1UNIQUE INDEX.\s0 .PP In \s-1DBD::DBM,\s0 you can take advantage of the speed of keyed lookups by using DBI::SQL::Nano and a \s-1WHERE\s0 clause with a single equal comparison on the key field. For example, the following \s-1SQL\s0 statements are optimized for keyed lookup: .PP .Vb 4 \& CREATE TABLE user ( user_name TEXT, phone TEXT); \& INSERT INTO user VALUES (\*(AqFred Bloggs\*(Aq,\*(Aq233\-7777\*(Aq); \& # ... many more inserts \& SELECT phone FROM user WHERE user_name=\*(AqFred Bloggs\*(Aq; .Ve .PP The \*(L"user_name\*(R" column is the key column since it is the first column. The \s-1SELECT\s0 statement uses the key column in a single equal comparison \- \*(L"user_name='Fred Bloggs'\*(R" \- so the search will find it very quickly without having to loop through all the names which were inserted into the table. .PP In contrast, these searches on the same table are not optimized: .PP .Vb 2 \& 1. SELECT phone FROM user WHERE user_name < \*(AqFred\*(Aq; \& 2. SELECT user_name FROM user WHERE phone = \*(Aq233\-7777\*(Aq; .Ve .PP In #1, the operation uses a less-than (<) comparison rather than an equals comparison, so it will not be optimized for key searching. In #2, the key field \*(L"user_name\*(R" is not specified in the \s-1WHERE\s0 clause, and therefore the search will need to loop through all rows to find the requested row(s). .PP \&\fBNote\fR that the underlying \s-1DBM\s0 storage needs to loop over all \fIkey/value\fR pairs when the optimized fetch is used. SQL::Statement has a massively improved where clause evaluation which costs around 15% of the evaluation in DBI::SQL::Nano \- combined with the loop in the \s-1DBM\s0 storage the speed improvement isn't so impressive. .PP Even if lookups are faster by around 50%, DBI::SQL::Nano and SQL::Statement can benefit from the key field optimizations on updating and deleting rows \- and here the improved where clause evaluation of SQL::Statement might beat DBI::SQL::Nano every time the where clause contains not only the key field (or more than one). .SS "Supported \s-1SQL\s0 syntax" .IX Subsection "Supported SQL syntax" \&\s-1DBD::DBM\s0 uses a subset of \s-1SQL.\s0 The robustness of that subset depends on what other modules you have installed. Both options support basic \s-1SQL\s0 operations including \s-1CREATE TABLE, DROP TABLE, INSERT, DELETE, UPDATE,\s0 and \&\s-1SELECT.\s0 .PP \&\fBOption #1:\fR By default, this module inherits its \s-1SQL\s0 support from DBI::SQL::Nano that comes with \s-1DBI.\s0 Nano is, as its name implies, a *very* small \s-1SQL\s0 engine. Although limited in scope, it is faster than option #2 for some operations (especially single \fIprimary key\fR lookups). See DBI::SQL::Nano for a description of the \s-1SQL\s0 it supports and comparisons of it with option #2. .PP \&\fBOption #2:\fR If you install the pure Perl \s-1CPAN\s0 module SQL::Statement, \&\s-1DBD::DBM\s0 will use it instead of Nano. This adds support for table aliases, functions, joins, and much more. If you're going to use \s-1DBD::DBM\s0 for anything other than very simple tables and queries, you should install SQL::Statement. You don't have to change \s-1DBD::DBM\s0 or your scripts in any way, simply installing SQL::Statement will give you the more robust \s-1SQL\s0 capabilities without breaking scripts written for DBI::SQL::Nano. See SQL::Statement for a description of the \s-1SQL\s0 it supports. .PP To find out which \s-1SQL\s0 module is working in a given script, you can use the \&\fBdbm_versions()\fR method or, if you don't need the full output and version numbers, just do this: .PP .Vb 1 \& print $dbh\->{sql_handler}, "\en"; .Ve .PP That will print out either \*(L"SQL::Statement\*(R" or \*(L"DBI::SQL::Nano\*(R". .PP Baring the section about optimized access to the \s-1DBM\s0 storage in mind, comparing the benefits of both engines: .PP .Vb 6 \& # DBI::SQL::Nano is faster \& $sth = $dbh\->prepare( "update foo set value=\*(Aqnew\*(Aq where key=15" ); \& $sth\->execute(); \& $sth = $dbh\->prepare( "delete from foo where key=27" ); \& $sth\->execute(); \& $sth = $dbh\->prepare( "select * from foo where key=\*(Aqabc\*(Aq" ); \& \& # SQL::Statement might faster (depending on DB size) \& $sth = $dbh\->prepare( "update foo set value=\*(Aqnew\*(Aq where key=?" ); \& $sth\->execute(15); \& $sth = $dbh\->prepare( "update foo set value=? where key=15" ); \& $sth\->execute(\*(Aqnew\*(Aq); \& $sth = $dbh\->prepare( "delete from foo where key=?" ); \& $sth\->execute(27); \& \& # SQL::Statement is faster \& $sth = $dbh\->prepare( "update foo set value=\*(Aqnew\*(Aq where value=\*(Aqold\*(Aq" ); \& $sth\->execute(); \& # must be expressed using "where key = 15 or key = 27 or key = 42 or key = \*(Aqabc\*(Aq" \& # in DBI::SQL::Nano \& $sth = $dbh\->prepare( "delete from foo where key in (15,27,42,\*(Aqabc\*(Aq)" ); \& $sth\->execute(); \& # must be expressed using "where key > 10 and key < 90" in DBI::SQL::Nano \& $sth = $dbh\->prepare( "select * from foo where key between (10,90)" ); \& $sth\->execute(); \& \& # only SQL::Statement can handle \& $sth\->prepare( "select * from foo,bar where foo.name = bar.name" ); \& $sth\->execute(); \& $sth\->prepare( "insert into foo values ( 1, \*(Aqfoo\*(Aq ), ( 2, \*(Aqbar\*(Aq )" ); \& $sth\->execute(); .Ve .SS "Specifying Column Names" .IX Subsection "Specifying Column Names" \&\s-1DBM\s0 files don't have a standard way to store column names. \s-1DBD::DBM\s0 gets around this issue with a \s-1DBD::DBM\s0 specific way of storing the column names. \&\fBIf you are working only with \s-1DBD::DBM\s0 and not using files created by or accessed with other \s-1DBM\s0 programs, you can ignore this section.\fR .PP \&\s-1DBD::DBM\s0 stores column names as a row in the file with the key \fI_metadata \&\e0\fR. So this code .PP .Vb 3 \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq); \& $dbh\->do("CREATE TABLE baz (foo CHAR(10), bar INTEGER)"); \& $dbh\->do("INSERT INTO baz (foo,bar) VALUES (\*(Aqzippy\*(Aq,1)"); .Ve .PP Will create a file that has a structure something like this: .PP .Vb 2 \& _metadata \e0 | foo,bar \& zippy | 1 .Ve .PP The next time you access this table with \s-1DBD::DBM,\s0 it will treat the \&\fI_metadata \e0\fR row as a header rather than as data and will pull the column names from there. However, if you access the file with something other than \s-1DBD::DBM,\s0 the row will be treated as a regular data row. .PP If you do not want the column names stored as a data row in the table you can set the \fIdbm_store_metadata\fR attribute to 0. .PP .Vb 1 \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { dbm_store_metadata => 0 }); \& \& # or \& $dbh\->{dbm_store_metadata} = 0; \& \& # or for per\-table setting \& $dbh\->{f_meta}\->{qux}\->{dbm_store_metadata} = 0; .Ve .PP By default, \s-1DBD::DBM\s0 assumes that you have two columns named \*(L"k\*(R" and \*(L"v\*(R" (short for \*(L"key\*(R" and \*(L"value\*(R"). So if you have \fIdbm_store_metadata\fR set to 1 and you want to use alternate column names, you need to specify the column names like this: .PP .Vb 4 \& my $dbh = DBI\->connect(\*(Aqdbi:DBM:\*(Aq, undef, undef, { \& dbm_store_metadata => 0, \& dbm_cols => [ qw(foo bar) ], \& }); \& \& # or \& $dbh\->{dbm_store_metadata} = 0; \& $dbh\->{dbm_cols} = \*(Aqfoo,bar\*(Aq; \& \& # or to set the column names on per\-table basis, do this: \& # sets the column names only for table "qux" \& $dbh\->{f_meta}\->{qux}\->{dbm_store_metadata} = 0; \& $dbh\->{f_meta}\->{qux}\->{col_names} = [qw(foo bar)]; .Ve .PP If you have a file that was created by another \s-1DBM\s0 program or created with \&\fIdbm_store_metadata\fR set to zero and you want to convert it to using \&\s-1DBD::DBM\s0's column name storage, just use one of the methods above to name the columns but *without* specifying \fIdbm_store_metadata\fR as zero. You only have to do that once \- thereafter you can get by without setting either \fIdbm_store_metadata\fR or setting \fIdbm_cols\fR because the names will be stored in the file. .SH "DBI database handle attributes" .IX Header "DBI database handle attributes" .SS "Metadata" .IX Subsection "Metadata" \fIStatement handle ($sth) attributes and methods\fR .IX Subsection "Statement handle ($sth) attributes and methods" .PP Most statement handle attributes such as \s-1NAME, NUM_OF_FIELDS,\s0 etc. are available only after an execute. The same is true of \f(CW$sth\fR\->rows which is available after the execute but does \fInot\fR require a fetch. .PP \fIDriver handle ($dbh) attributes\fR .IX Subsection "Driver handle ($dbh) attributes" .PP It is not supported anymore to use dbm-attributes without the dbm_\-prefix. Currently, if an \s-1DBD::DBM\s0 private attribute is accessed without an underscore in it's name, dbm_ is prepended to that attribute and it's processed further. If the resulting attribute name is invalid, an error is thrown. .PP dbm_cols .IX Subsection "dbm_cols" .PP Contains a comma separated list of column names or an array reference to the column names. .PP dbm_type .IX Subsection "dbm_type" .PP Contains the \s-1DBM\s0 storage type. Currently known supported type are \&\f(CW\*(C`ODBM_File\*(C'\fR, \f(CW\*(C`NDBM_File\*(C'\fR, \f(CW\*(C`SDBM_File\*(C'\fR, \f(CW\*(C`GDBM_File\*(C'\fR, \&\f(CW\*(C`DB_File\*(C'\fR and \f(CW\*(C`BerkeleyDB\*(C'\fR. It is not recommended to use one of the first three types \- even if \f(CW\*(C`SDBM_File\*(C'\fR is the most commonly available \fIdbm_type\fR. .PP dbm_mldbm .IX Subsection "dbm_mldbm" .PP Contains the serializer for \s-1DBM\s0 storage (value column). Requires the \&\s-1CPAN\s0 module \s-1MLDBM\s0 installed. Currently known supported serializers are: .IP "Data::Dumper" 8 .IX Item "Data::Dumper" Default serializer. Deployed with Perl core. .IP "Storable" 8 .IX Item "Storable" Faster serializer. Deployed with Perl core. .IP "FreezeThaw" 8 .IX Item "FreezeThaw" Pure Perl serializer, requires FreezeThaw to be installed. .IP "\s-1YAML\s0" 8 .IX Item "YAML" Portable serializer (between languages but not architectures). Requires \s-1YAML::MLDBM\s0 installation. .IP "\s-1JSON\s0" 8 .IX Item "JSON" Portable, fast serializer (between languages but not architectures). Requires MLDBM::Serializer::JSON installation. .PP dbm_store_metadata .IX Subsection "dbm_store_metadata" .PP Boolean value which determines if the metadata in \s-1DBM\s0 is stored or not. .PP dbm_berkeley_flags .IX Subsection "dbm_berkeley_flags" .PP Hash reference with additional flags for BerkeleyDB::Hash instantiation. .PP dbm_version .IX Subsection "dbm_version" .PP Readonly attribute containing the version of \s-1DBD::DBM.\s0 .PP f_meta .IX Subsection "f_meta" .PP In addition to the attributes DBD::File recognizes, \s-1DBD::DBM\s0 knows about the (public) attributes \f(CW\*(C`col_names\*(C'\fR (\fBNote\fR not \fIdbm_cols\fR here!), \f(CW\*(C`dbm_type\*(C'\fR, \f(CW\*(C`dbm_mldbm\*(C'\fR, \f(CW\*(C`dbm_store_metadata\*(C'\fR and \&\f(CW\*(C`dbm_berkeley_flags\*(C'\fR. As in DBD::File, there are undocumented, internal attributes in \s-1DBD::DBM.\s0 Be very careful when modifying attributes you do not know; the consequence might a destroyed or corrupted table. .PP dbm_tables .IX Subsection "dbm_tables" .PP This attribute provides restricted access to the table meta data. See f_meta and \*(L"f_meta\*(R" in DBD::File for attribute details. .PP dbm_tables is a tied hash providing the internal table names as keys (accessing unknown tables might create an entry) and their meta data as another tied hash. The table meta storage is obtained via the \f(CW\*(C`get_table_meta\*(C'\fR method from the table implementation (see DBD::File::Developers). Attribute setting and getting within the table meta data is handled via the methods \f(CW\*(C`set_table_meta_attr\*(C'\fR and \&\f(CW\*(C`get_table_meta_attr\*(C'\fR. .PP \fIFollowing attributes are no longer handled by \s-1DBD::DBM:\s0\fR .IX Subsection "Following attributes are no longer handled by DBD::DBM:" .PP dbm_ext .IX Subsection "dbm_ext" .PP This attribute is silently mapped to DBD::File's attribute \fIf_ext\fR. Later versions of \s-1DBI\s0 might show a depreciated warning when this attribute is used and eventually it will be removed. .PP dbm_lockfile .IX Subsection "dbm_lockfile" .PP This attribute is silently mapped to DBD::File's attribute \fIf_lockfile\fR. Later versions of \s-1DBI\s0 might show a depreciated warning when this attribute is used and eventually it will be removed. .SH "DBI database handle methods" .IX Header "DBI database handle methods" .ie n .SS "The $dbh\->\fBdbm_versions()\fP method" .el .SS "The \f(CW$dbh\fP\->\fBdbm_versions()\fP method" .IX Subsection "The $dbh->dbm_versions() method" The private method \fBdbm_versions()\fR returns a summary of what other modules are being used at any given time. \s-1DBD::DBM\s0 can work with or without many other modules \- it can use either SQL::Statement or DBI::SQL::Nano as its \&\s-1SQL\s0 engine, it can be run with \s-1DBI\s0 or DBI::PurePerl, it can use many kinds of \s-1DBM\s0 modules, and many kinds of serializers when run with \s-1MLDBM.\s0 The \&\fBdbm_versions()\fR method reports all of that and more. .PP .Vb 2 \& print $dbh\->dbm_versions; # displays global settings \& print $dbh\->dbm_versions($table_name); # displays per table settings .Ve .PP An important thing to note about this method is that when it called with no arguments, it displays the *global* settings. If you override these by setting per-table attributes, these will \fInot\fR be shown unless you specify a table name as an argument to the method call. .SS "Storing Objects" .IX Subsection "Storing Objects" If you are using \s-1MLDBM,\s0 you can use \s-1DBD::DBM\s0 to take advantage of its serializing abilities to serialize any Perl object that \s-1MLDBM\s0 can handle. To store objects in columns, you should (but don't absolutely need to) declare it as a column of type \s-1BLOB\s0 (the type is *currently* ignored by the \s-1SQL\s0 engine, but it's good form). .SH "EXTENSIBILITY" .IX Header "EXTENSIBILITY" .ie n .IP """SQL::Statement""" 8 .el .IP "\f(CWSQL::Statement\fR" 8 .IX Item "SQL::Statement" Improved \s-1SQL\s0 engine compared to the built-in DBI::SQL::Nano \- see \&\*(L"Supported \s-1SQL\s0 syntax\*(R". .ie n .IP """DB_File""" 8 .el .IP "\f(CWDB_File\fR" 8 .IX Item "DB_File" Berkeley \s-1DB\s0 version 1. This database library is available on many systems without additional installation and most systems are supported. .ie n .IP """GDBM_File""" 8 .el .IP "\f(CWGDBM_File\fR" 8 .IX Item "GDBM_File" Simple dbm type (comparable to \f(CW\*(C`DB_File\*(C'\fR) under the \s-1GNU\s0 license. Typically not available (or requires extra installation) on non-GNU operating systems. .ie n .IP """BerkeleyDB""" 8 .el .IP "\f(CWBerkeleyDB\fR" 8 .IX Item "BerkeleyDB" Berkeley \s-1DB\s0 version up to v4 (and maybe higher) \- requires additional installation but is easier than GDBM_File on non-GNU systems. .Sp db4 comes with a many tools which allow repairing and migrating databases. This is the \fBrecommended\fR dbm type for production use. .ie n .IP """MLDBM""" 8 .el .IP "\f(CWMLDBM\fR" 8 .IX Item "MLDBM" Serializer wrapper to support more than one column for the files. Comes with serializers using \f(CW\*(C`Data::Dumper\*(C'\fR, \f(CW\*(C`FreezeThaw\*(C'\fR and \&\f(CW\*(C`Storable\*(C'\fR. .ie n .IP """YAML::MLDBM""" 8 .el .IP "\f(CWYAML::MLDBM\fR" 8 .IX Item "YAML::MLDBM" Additional serializer for \s-1MLDBM. YAML\s0 is very portable between languages. .ie n .IP """MLDBM::Serializer::JSON""" 8 .el .IP "\f(CWMLDBM::Serializer::JSON\fR" 8 .IX Item "MLDBM::Serializer::JSON" Additional serializer for \s-1MLDBM. JSON\s0 is very portable between languages, probably more than \s-1YAML.\s0 .SH "GOTCHAS AND WARNINGS" .IX Header "GOTCHAS AND WARNINGS" Using the \s-1SQL DROP\s0 command will remove any file that has the name specified in the command with either '.pag' and '.dir', '.db' or your {f_ext} appended to it. So this be dangerous if you aren't sure what file it refers to: .PP .Vb 1 \& $dbh\->do(qq{DROP TABLE "/path/to/any/file"}); .Ve .PP Each \s-1DBM\s0 type has limitations. SDBM_File, for example, can only store values of less than 1,000 characters. *You* as the script author must ensure that you don't exceed those bounds. If you try to insert a value that is larger than \s-1DBM\s0 can store, the results will be unpredictable. See the documentation for whatever \s-1DBM\s0 you are using for details. .PP Different \s-1DBM\s0 implementations return records in different orders. That means that you \fIshould not\fR rely on the order of records unless you use an \s-1ORDER BY\s0 statement. .PP \&\s-1DBM\s0 data files are platform-specific. To move them from one platform to another, you'll need to do something along the lines of dumping your data to \s-1CSV\s0 on platform #1 and then dumping from \s-1CSV\s0 to \s-1DBM\s0 on platform #2. DBD::AnyData and \s-1DBD::CSV\s0 can help with that. There may also be \s-1DBM\s0 conversion tools for your platforms which would probably be quicker. .PP When using \s-1MLDBM,\s0 there is a very powerful serializer \- it will allow you to store Perl code or objects in database columns. When these get de-serialized, they may be eval'ed \- in other words \s-1MLDBM\s0 (or actually Data::Dumper when used by \s-1MLDBM\s0) may take the values and try to execute them in Perl. Obviously, this can present dangers, so if you do not know what is in a file, be careful before you access it with \&\s-1MLDBM\s0 turned on! .PP See the entire section on \*(L"Table locking and \fBflock()\fR\*(R" for gotchas and warnings about the use of \fBflock()\fR. .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" This module uses hash interfaces of two column file databases. While none of supported \s-1SQL\s0 engines have support for indices, the following statements really do the same (even if they mean something completely different) for each dbm type which lacks \f(CW\*(C`EXISTS\*(C'\fR support: .PP .Vb 1 \& $sth\->do( "insert into foo values (1, \*(Aqhello\*(Aq)" ); \& \& # this statement does ... \& $sth\->do( "update foo set v=\*(Aqworld\*(Aq where k=1" ); \& # ... the same as this statement \& $sth\->do( "insert into foo values (1, \*(Aqworld\*(Aq)" ); .Ve .PP This is considered to be a bug and might change in a future release. .PP Known affected dbm types are \f(CW\*(C`ODBM_File\*(C'\fR and \f(CW\*(C`NDBM_File\*(C'\fR. We highly recommended you use a more modern dbm type such as \f(CW\*(C`DB_File\*(C'\fR. .SH "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" .IX Header "GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS" If you need help installing or using \s-1DBD::DBM,\s0 please write to the \s-1DBI\s0 users mailing list at dbi\-users@perl.org or to the comp.lang.perl.modules newsgroup on usenet. I cannot always answer every question quickly but there are many on the mailing list or in the newsgroup who can. .PP \&\s-1DBD\s0 developers for \s-1DBD\s0's which rely on DBD::File or \s-1DBD::DBM\s0 or use one of them as an example are suggested to join the \s-1DBI\s0 developers mailing list at dbi\-dev@perl.org and strongly encouraged to join our \&\s-1IRC\s0 channel at . .PP If you have suggestions, ideas for improvements, or bugs to report, please report a bug as described in \s-1DBI.\s0 Do not mail any of the authors directly, you might not get an answer. .PP When reporting bugs, please send the output of \f(CW$dbh\fR\->dbm_versions($table) for a table that exhibits the bug and as small a sample as you can make of the code that produces the bug. And of course, patches are welcome, too :\-). .PP If you need enhancements quickly, you can get commercial support as described at or you can contact Jens Rehsack at rehsack@cpan.org for commercial support in Germany. .PP Please don't bother Jochen Wiedmann or Jeff Zucker for support \- they handed over further maintenance to H.Merijn Brand and Jens Rehsack. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" Many, many thanks to Tim Bunce for prodding me to write this, and for copious, wise, and patient suggestions all along the way. (Jeff Zucker) .PP I send my thanks and acknowledgements to H.Merijn Brand for his initial refactoring of DBD::File and his strong and ongoing support of SQL::Statement. Without him, the current progress would never have been made. And I have to name Martin J. Evans for each laugh (and correction) of all those funny word creations I (as non-native speaker) made to the documentation. And \- of course \- I have to thank all those unnamed contributors and testers from the Perl community. (Jens Rehsack) .SH "AUTHOR AND COPYRIGHT" .IX Header "AUTHOR AND COPYRIGHT" This module is written by Jeff Zucker < jzucker \s-1AT\s0 cpan.org >, who also maintained it till 2007. After that, in 2010, Jens Rehsack & H.Merijn Brand took over maintenance. .PP .Vb 2 \& Copyright (c) 2004 by Jeff Zucker, all rights reserved. \& Copyright (c) 2010\-2013 by Jens Rehsack & H.Merijn Brand, all rights reserved. .Ve .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1DBI\s0, SQL::Statement, DBI::SQL::Nano, AnyDBM_File, DB_File, BerkeleyDB, \&\s-1MLDBM\s0, \s-1YAML::MLDBM\s0, MLDBM::Serializer::JSON man/man3/DBI::DBD::SqlEngine::HowTo.3pm000044400000035733152462503210013042 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::DBD::SqlEngine::HowTo 3" .TH DBI::DBD::SqlEngine::HowTo 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::DBD::SqlEngine::HowTo \- Guide to create DBI::DBD::SqlEngine based driver .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 8 \& perldoc DBI::DBD::SqlEngine::HowTo \& perldoc DBI \& perldoc DBI::DBD \& perldoc DBI::DBD::SqlEngine::Developers \& perldoc SQL::Eval \& perldoc DBI::DBD::SqlEngine \& perldoc DBI::DBD::SqlEngine::HowTo \& perldoc SQL::Statement::Embed .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document provides a step-by-step guide, how to create a new \&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR based \s-1DBD.\s0 It expects that you carefully read the \&\s-1DBI\s0 documentation and that you're familiar with \s-1DBI::DBD\s0 and had read and understood DBD::ExampleP. .PP This document addresses experienced developers who are really sure that they need to invest time when writing a new \s-1DBI\s0 Driver. Writing a \s-1DBI\s0 Driver is neither a weekend project nor an easy job for hobby coders after work. Expect one or two man-month of time for the first start. .PP Those who are still reading, should be able to sing the rules of \&\*(L"\s-1CREATING A NEW DRIVER\*(R"\s0 in \s-1DBI::DBD\s0. .SH "CREATING DRIVER CLASSES" .IX Header "CREATING DRIVER CLASSES" Do you have an entry in \s-1DBI\s0's \s-1DBD\s0 registry? DBI::DBD::SqlEngine expect having a unique prefix for every driver class in inheritance chain. .PP It's easy to get a prefix \- just drop the \s-1DBI\s0 team a note (\*(L"\s-1GETTING_HELP\*(R"\s0 in \s-1DBI\s0). If you want for some reason hide your work, take a look at Class::Method::Modifiers how to wrap a private prefix method around existing \f(CW\*(C`driver_prefix\*(C'\fR. .PP For this guide, a prefix of \f(CW\*(C`foo_\*(C'\fR is assumed. .SS "Sample Skeleton" .IX Subsection "Sample Skeleton" .Vb 1 \& package DBD::Foo; \& \& use strict; \& use warnings; \& use vars qw($VERSION); \& use base qw(DBI::DBD::SqlEngine); \& \& use DBI (); \& \& $VERSION = "0.001"; \& \& package DBD::Foo::dr; \& \& use vars qw(@ISA $imp_data_size); \& \& @ISA = qw(DBI::DBD::SqlEngine::dr); \& $imp_data_size = 0; \& \& package DBD::Foo::db; \& \& use vars qw(@ISA $imp_data_size); \& \& @ISA = qw(DBI::DBD::SqlEngine::db); \& $imp_data_size = 0; \& \& package DBD::Foo::st; \& \& use vars qw(@ISA $imp_data_size); \& \& @ISA = qw(DBI::DBD::SqlEngine::st); \& $imp_data_size = 0; \& \& package DBD::Foo::Statement; \& \& use vars qw(@ISA); \& \& @ISA = qw(DBI::DBD::SqlEngine::Statement); \& \& package DBD::Foo::Table; \& \& use vars qw(@ISA); \& \& @ISA = qw(DBI::DBD::SqlEngine::Table); \& \& 1; .Ve .PP Tiny, eh? And all you have now is a \s-1DBD\s0 named foo which will is able to deal with temporary tables, as long as you use SQL::Statement. In DBI::SQL::Nano environments, this \s-1DBD\s0 can do nothing. .SS "Deal with own attributes" .IX Subsection "Deal with own attributes" Before we start doing usable stuff with our \s-1DBI\s0 driver, we need to think about what we want to do and how we want to do it. .PP Do we need tunable knobs accessible by users? Do we need status information? All this is handled in attributes of the database handles (be careful when your \s-1DBD\s0 is running \*(L"behind\*(R" a DBD::Gofer proxy). .PP How come the attributes into the \s-1DBD\s0 and how are they fetchable by the user? Good question, but you should know because you've read the \s-1DBI\s0 documentation. .PP \&\f(CW\*(C`DBI::DBD::SqlEngine::db::FETCH\*(C'\fR and \f(CW\*(C`DBI::DBD::SqlEngine::db::STORE\*(C'\fR taking care for you \- all they need to know is which attribute names are valid and mutable or immutable. Tell them by adding \&\f(CW\*(C`init_valid_attributes\*(C'\fR to your db class: .PP .Vb 3 \& sub init_valid_attributes \& { \& my $dbh = $_[0]; \& \& $dbh\->SUPER::init_valid_attributes (); \& \& $dbh\->{foo_valid_attrs} = { \& foo_version => 1, # contains version of this driver \& foo_valid_attrs => 1, # contains the valid attributes of foo drivers \& foo_readonly_attrs => 1, # contains immutable attributes of foo drivers \& foo_bar => 1, # contains the bar attribute \& foo_baz => 1, # contains the baz attribute \& foo_manager => 1, # contains the manager of the driver instance \& foo_manager_type => 1, # contains the manager class of the driver instance \& }; \& $dbh\->{foo_readonly_attrs} = { \& foo_version => 1, # ensure no\-one modifies the driver version \& foo_valid_attrs => 1, # do not permit one to add more valid attributes ... \& foo_readonly_attrs => 1, # ... or make the immutable mutable \& foo_manager => 1, # manager is set internally only \& }; \& \& return $dbh; \& } .Ve .PP Woooho \- but now the user cannot assign new managers? This is intended, overwrite \f(CW\*(C`STORE\*(C'\fR to handle it! .PP .Vb 3 \& sub STORE ($$$) \& { \& my ( $dbh, $attrib, $value ) = @_; \& \& $dbh\->SUPER::STORE( $attrib, $value ); \& \& # we\*(Aqre still alive, so no exception is thrown ... \& # by DBI::DBD::SqlEngine::db::STORE \& if ( $attrib eq "foo_manager_type" ) \& { \& $dbh\->{foo_manager} = $dbh\->{foo_manager_type}\->new(); \& # ... probably correct some states based on the new \& # foo_manager_type \- see DBD::Sys for an example \& } \& } .Ve .PP But ... my driver runs without a manager until someone first assignes a \f(CW\*(C`foo_manager_type\*(C'\fR. Well, no \- there're two places where you can initialize defaults: .PP .Vb 3 \& sub init_default_attributes \& { \& my ($dbh, $phase) = @_; \& \& $dbh\->SUPER::init_default_attributes($phase); \& \& if( 0 == $phase ) \& { \& # init all attributes which have no knowledge about \& # user settings from DSN or the attribute hash \& $dbh\->{foo_manager_type} = "DBD::Foo::Manager"; \& } \& elsif( 1 == $phase ) \& { \& # init phase with more knowledge from DSN or attribute \& # hash \& $dbh\->{foo_manager} = $dbh\->{foo_manager_type}\->new(); \& } \& \& return $dbh; \& } .Ve .PP So far we can prevent the users to use our database driver as data storage for anything and everything. We care only about the real important stuff for peace on earth and alike attributes. But in fact, the driver still can't do anything. It can do less than nothing \- meanwhile it's not a stupid storage area anymore. .SS "User comfort" .IX Subsection "User comfort" \&\f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR since \f(CW0.05\fR consolidates all persistent meta data of a table into a single structure stored in \f(CW\*(C`$dbh\->{sql_meta}\*(C'\fR. While DBI::DBD::SqlEngine provides only readonly access to this structure, modifications are still allowed. .PP Primarily DBI::DBD::SqlEngine provides access via the setters \&\f(CW\*(C`new_sql_engine_meta\*(C'\fR, \f(CW\*(C`get_sql_engine_meta\*(C'\fR, \f(CW\*(C`get_single_table_meta\*(C'\fR, \&\f(CW\*(C`set_single_table_meta\*(C'\fR, \f(CW\*(C`set_sql_engine_meta\*(C'\fR and \f(CW\*(C`clear_sql_engine_meta\*(C'\fR. Those methods are easily accessible by the users via the \f(CW\*(C`$dbh\->func ()\*(C'\fR interface provided by \s-1DBI.\s0 Well, many users don't feel comfortize when calling .PP .Vb 2 \& # don\*(Aqt require extension for tables cars \& $dbh\->func ("cars", "f_ext", ".csv", "set_sql_engine_meta"); .Ve .PP DBI::DBD::SqlEngine will inject a method into your driver to increase the user comfort to allow: .PP .Vb 2 \& # don\*(Aqt require extension for tables cars \& $dbh\->foo_set_meta ("cars", "f_ext", ".csv"); .Ve .PP Better, but here and there users likes to do: .PP .Vb 2 \& # don\*(Aqt require extension for tables cars \& $dbh\->{foo_tables}\->{cars}\->{f_ext} = ".csv"; .Ve .PP This interface is provided when derived \s-1DBD\s0's define following in \&\f(CW\*(C`init_valid_attributes\*(C'\fR (re-capture \*(L"Deal with own attributes\*(R"): .PP .Vb 3 \& sub init_valid_attributes \& { \& my $dbh = $_[0]; \& \& $dbh\->SUPER::init_valid_attributes (); \& \& $dbh\->{foo_valid_attrs} = { \& foo_version => 1, # contains version of this driver \& foo_valid_attrs => 1, # contains the valid attributes of foo drivers \& foo_readonly_attrs => 1, # contains immutable attributes of foo drivers \& foo_bar => 1, # contains the bar attribute \& foo_baz => 1, # contains the baz attribute \& foo_manager => 1, # contains the manager of the driver instance \& foo_manager_type => 1, # contains the manager class of the driver instance \& foo_meta => 1, # contains the public interface to modify table meta attributes \& }; \& $dbh\->{foo_readonly_attrs} = { \& foo_version => 1, # ensure no\-one modifies the driver version \& foo_valid_attrs => 1, # do not permit one to add more valid attributes ... \& foo_readonly_attrs => 1, # ... or make the immutable mutable \& foo_manager => 1, # manager is set internally only \& foo_meta => 1, # ensure public interface to modify table meta attributes are immutable \& }; \& \& $dbh\->{foo_meta} = "foo_tables"; \& \& return $dbh; \& } .Ve .PP This provides a tied hash in \f(CW\*(C`$dbh\->{foo_tables}\*(C'\fR and a tied hash for each table's meta data in \f(CW\*(C`$dbh\->{foo_tables}\->{$table_name}\*(C'\fR. Modifications on the table meta attributes are done using the table methods: .PP .Vb 2 \& sub get_table_meta_attr { ... } \& sub set_table_meta_attr { ... } .Ve .PP Both methods can adjust the attribute name for compatibility reasons, e.g. when former versions of the \s-1DBD\s0 allowed different names to be used for the same flag: .PP .Vb 5 \& my %compat_map = ( \& abc => \*(Aqfoo_abc\*(Aq, \& xyz => \*(Aqfoo_xyz\*(Aq, \& ); \& _\|_PACKAGE_\|_\->register_compat_map( \e%compat_map ); .Ve .PP If any user modification on a meta attribute needs reinitialization of the meta structure (in case of \f(CW\*(C`DBI::DBD::SqlEngine\*(C'\fR these are the attributes \&\f(CW\*(C`f_file\*(C'\fR, \f(CW\*(C`f_dir\*(C'\fR, \f(CW\*(C`f_ext\*(C'\fR and \f(CW\*(C`f_lockfile\*(C'\fR), inform DBI::DBD::SqlEngine by doing .PP .Vb 5 \& my %reset_on_modify = ( \& foo_xyz => "foo_bar", \& foo_abc => "foo_bar", \& ); \& _\|_PACKAGE_\|_\->register_reset_on_modify( \e%reset_on_modify ); .Ve .PP The next access to the table meta data will force DBI::DBD::SqlEngine to re-do the entire meta initialization process. .PP Any further action which needs to be taken can handled in \&\f(CW\*(C`table_meta_attr_changed\*(C'\fR: .PP .Vb 6 \& sub table_meta_attr_changed \& { \& my ($class, $meta, $attrib, $value) = @_; \& ... \& $class\->SUPER::table_meta_attr_changed ($meta, $attrib, $value); \& } .Ve .PP This is done before the new value is set in \f(CW$meta\fR, so the attribute changed handler can act depending on the old value. .SS "Dealing with Tables" .IX Subsection "Dealing with Tables" Let's put some life into it \- it's going to be time for it. .PP This is a good point where a quick side step to SQL::Statement::Embed will help to shorten the next paragraph. The documentation in SQL::Statement::Embed regarding embedding in own \s-1DBD\s0's works pretty fine with SQL::Statement and DBI::SQL::Nano. .PP Second look should go to DBI::DBD::SqlEngine::Developers to get a picture over the driver part of the table \s-1API.\s0 Usually there isn't much to do for an easy driver. .SS "Testing" .IX Subsection "Testing" Now you should have your first own \s-1DBD.\s0 Was easy, wasn't it? But does it work well? Prove it by writing tests and remember to use dbd_edit_mm_attribs from \s-1DBI::DBD\s0 to ensure testing even rare cases. .SH "AUTHOR" .IX Header "AUTHOR" This guide is written by Jens Rehsack. DBI::DBD::SqlEngine is written by Jens Rehsack using code from DBD::File originally written by Jochen Wiedmann and Jeff Zucker. .PP The module DBI::DBD::SqlEngine is currently maintained by .PP H.Merijn Brand < h.m.brand at xs4all.nl > and Jens Rehsack < rehsack at googlemail.com > .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2010 by H.Merijn Brand & Jens Rehsack .PP All rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. man/man3/DBI::Gofer::Response.3pm000044400000005230152462503210012244 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Response 3" .TH DBI::Gofer::Response 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Response \- Encapsulate a response from DBI::Gofer::Execute to DBD::Gofer .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is an internal class. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/DBI::DBD.3pm000044400000426422152462503210007702 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::DBD 3" .TH DBI::DBD 3 "2016-04-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::DBD \- Perl DBI Database Driver Writer's Guide .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& perldoc DBI::DBD .Ve .SS "Version and volatility" .IX Subsection "Version and volatility" This document is \fIstill\fR a minimal draft which is in need of further work. .PP Please read the \fB\s-1DBI\s0\fR documentation first and fully. Then look at the implementation of some high-profile and regularly maintained drivers like DBD::Oracle, \s-1DBD::ODBC,\s0 DBD::Pg etc. (Those are no no particular order.) .PP Then reread the \fB\s-1DBI\s0\fR specification and the code of those drivers again as you're reading this. It'll help. Where this document and the driver code differ it's likely that the driver code is more correct, especially if multiple drivers do the same thing. .PP This document is a patchwork of contributions from various authors. More contributions (preferably as patches) are very welcome. .SH "DESCRIPTION" .IX Header "DESCRIPTION" This document is primarily intended to help people writing new database drivers for the Perl Database Interface (Perl \s-1DBI\s0). It may also help others interested in discovering why the internals of a \fB\s-1DBD\s0\fR driver are written the way they are. .PP This is a guide. Few (if any) of the statements in it are completely authoritative under all possible circumstances. This means you will need to use judgement in applying the guidelines in this document. If in \fIany\fR doubt at all, please do contact the \fIdbi-dev\fR mailing list (details given below) where Tim Bunce and other driver authors can help. .SH "CREATING A NEW DRIVER" .IX Header "CREATING A NEW DRIVER" The first rule for creating a new database driver for the Perl \s-1DBI\s0 is very simple: \fB\s-1DON\s0'T!\fR .PP There is usually a driver already available for the database you want to use, almost regardless of which database you choose. Very often, the database will provide an \s-1ODBC\s0 driver interface, so you can often use \&\fB\s-1DBD::ODBC\s0\fR to access the database. This is typically less convenient on a Unix box than on a Microsoft Windows box, but there are numerous options for \s-1ODBC\s0 driver managers on Unix too, and very often the \s-1ODBC\s0 driver is provided by the database supplier. .PP Before deciding that you need to write a driver, do your homework to ensure that you are not wasting your energies. .PP [As of December 2002, the consensus is that if you need an \s-1ODBC\s0 driver manager on Unix, then the unixODBC driver (available from ) is the way to go.] .PP The second rule for creating a new database driver for the Perl \s-1DBI\s0 is also very simple: \fBDon't \*(-- get someone else to do it for you!\fR .PP Nevertheless, there are occasions when it is necessary to write a new driver, often to use a proprietary language or \s-1API\s0 to access the database more swiftly, or more comprehensively, than an \s-1ODBC\s0 driver can. Then you should read this document very carefully, but with a suitably sceptical eye. .PP If there is something in here that does not make any sense, question it. You might be right that the information is bogus, but don't come to that conclusion too quickly. .SS "URLs and mailing lists" .IX Subsection "URLs and mailing lists" The primary web-site for locating \fB\s-1DBI\s0\fR software and information is .PP .Vb 1 \& http://dbi.perl.org/ .Ve .PP There are two main and one auxiliary mailing lists for people working with \fB\s-1DBI\s0\fR. The primary lists are \fIdbi\-users@perl.org\fR for general users of \fB\s-1DBI\s0\fR and \fB\s-1DBD\s0\fR drivers, and \fIdbi\-dev@perl.org\fR mainly for \fB\s-1DBD\s0\fR driver writers (don't join the \fIdbi-dev\fR list unless you have a good reason). The auxiliary list is \fIdbi\-announce@perl.org\fR for announcing new releases of \fB\s-1DBI\s0\fR or \fB\s-1DBD\s0\fR drivers. .PP You can join these lists by accessing the web-site . The lists are closed so you cannot send email to any of the lists unless you join the list first. .PP You should also consider monitoring the \fIcomp.lang.perl.*\fR newsgroups, especially \fIcomp.lang.perl.modules\fR. .SS "The Cheetah book" .IX Subsection "The Cheetah book" The definitive book on Perl \s-1DBI\s0 is the Cheetah book, so called because of the picture on the cover. Its proper title is '\fIProgramming the Perl \s-1DBI:\s0 Database programming with Perl\fR' by Alligator Descartes and Tim Bunce, published by O'Reilly Associates, February 2000, \s-1ISBN 1\-56592\-699\-4.\s0 Buy it now if you have not already done so, and read it. .SS "Locating drivers" .IX Subsection "Locating drivers" Before writing a new driver, it is in your interests to find out whether there already is a driver for your database. If there is such a driver, it would be much easier to make use of it than to write your own! .PP The primary web-site for locating Perl software is . You should look under the various modules listings for the software you are after. For example: .PP .Vb 1 \& http://search.cpan.org/modlist/Database_Interfaces .Ve .PP Follow the \fB\s-1DBD::\s0\fR and \fBDBIx::\fR links at the top to see those subsets. .PP See the \fB\s-1DBI\s0\fR docs for information on \fB\s-1DBI\s0\fR web sites and mailing lists. .SS "Registering a new driver" .IX Subsection "Registering a new driver" Before going through any official registration process, you will need to establish that there is no driver already in the works. You'll do that by asking the \fB\s-1DBI\s0\fR mailing lists whether there is such a driver available, or whether anybody is working on one. .PP When you get the go ahead, you will need to establish the name of the driver and a prefix for the driver. Typically, the name is based on the name of the database software it uses, and the prefix is a contraction of that. Hence, \fBDBD::Oracle\fR has the name \fIOracle\fR and the prefix \&'\fIora_\fR'. The prefix must be lowercase and contain no underscores other than the one at the end. .PP This information will be recorded in the \fB\s-1DBI\s0\fR module. Apart from documentation purposes, registration is a prerequisite for installing private methods. .PP If you are writing a driver which will not be distributed on \s-1CPAN,\s0 then you should choose a prefix beginning with '\fIx_\fR', to avoid potential prefix collisions with drivers registered in the future. Thus, if you wrote a non-CPAN distributed driver called \fBDBD::CustomDB\fR, the prefix might be '\fIx_cdb_\fR'. .PP This document assumes you are writing a driver called \fBDBD::Driver\fR, and that the prefix '\fIdrv_\fR' is assigned to the driver. .SS "Two styles of database driver" .IX Subsection "Two styles of database driver" There are two distinct styles of database driver that can be written to work with the Perl \s-1DBI.\s0 .PP Your driver can be written in pure Perl, requiring no C compiler. When feasible, this is the best solution, but most databases are not written in such a way that this can be done. Some examples of pure Perl drivers are \fBDBD::File\fR and \fB\s-1DBD::CSV\s0\fR. .PP Alternatively, and most commonly, your driver will need to use some C code to gain access to the database. This will be classified as a C/XS driver. .SS "What code will you write?" .IX Subsection "What code will you write?" There are a number of files that need to be written for either a pure Perl driver or a C/XS driver. There are no extra files needed only by a pure Perl driver, but there are several extra files needed only by a C/XS driver. .PP \fIFiles common to pure Perl and C/XS drivers\fR .IX Subsection "Files common to pure Perl and C/XS drivers" .PP Assuming that your driver is called \fBDBD::Driver\fR, these files are: .IP "\(bu" 4 \&\fIMakefile.PL\fR .IP "\(bu" 4 \&\fI\s-1META\s0.yml\fR .IP "\(bu" 4 \&\fI\s-1README\s0\fR .IP "\(bu" 4 \&\fI\s-1MANIFEST\s0\fR .IP "\(bu" 4 \&\fIDriver.pm\fR .IP "\(bu" 4 \&\fIlib/Bundle/DBD/Driver.pm\fR .IP "\(bu" 4 \&\fIlib/DBD/Driver/Summary.pm\fR .IP "\(bu" 4 \&\fIt/*.t\fR .PP The first four files are mandatory. \fIMakefile.PL\fR is used to control how the driver is built and installed. The \fI\s-1README\s0\fR file tells people who download the file about how to build the module and any prerequisite software that must be installed. The \fI\s-1MANIFEST\s0\fR file is used by the standard Perl module distribution mechanism. It lists all the source files that need to be distributed with your module. \fIDriver.pm\fR is what is loaded by the \fB\s-1DBI\s0\fR code; it contains the methods peculiar to your driver. .PP Although the \fI\s-1META\s0.yml\fR file is not \fBrequired\fR you are advised to create one. Of particular importance are the \fIbuild_requires\fR and \&\fIconfigure_requires\fR attributes which newer \s-1CPAN\s0 modules understand. You use these to tell the \s-1CPAN\s0 module (and \s-1CPANPLUS\s0) that your build and configure mechanisms require \s-1DBI.\s0 The best reference for \s-1META\s0.yml (at the time of writing) is . You can find a reasonable example of a \fI\s-1META\s0.yml\fR in \s-1DBD::ODBC.\s0 .PP The \fIlib/Bundle/DBD/Driver.pm\fR file allows you to specify other Perl modules on which yours depends in a format that allows someone to type a simple command and ensure that all the pre-requisites are in place as well as building your driver. .PP The \fIlib/DBD/Driver/Summary.pm\fR file contains (an updated version of) the information that was included \- or that would have been included \- in the appendices of the Cheetah book as a summary of the abilities of your driver and the associated database. .PP The files in the \fIt\fR subdirectory are unit tests for your driver. You should write your tests as stringently as possible, while taking into account the diversity of installations that you can encounter: .IP "\(bu" 4 Your tests should not casually modify operational databases. .IP "\(bu" 4 You should never damage existing tables in a database. .IP "\(bu" 4 You should code your tests to use a constrained name space within the database. For example, the tables (and all other named objects) that are created could all begin with '\fIdbd_drv_\fR'. .IP "\(bu" 4 At the end of a test run, there should be no testing objects left behind in the database. .IP "\(bu" 4 If you create any databases, you should remove them. .IP "\(bu" 4 If your database supports temporary tables that are automatically removed at the end of a session, then exploit them as often as possible. .IP "\(bu" 4 Try to make your tests independent of each other. If you have a test \fIt/t11dowhat.t\fR that depends upon the successful running of \fIt/t10thingamy.t\fR, people cannot run the single test case \&\fIt/t11dowhat.t\fR. Further, running \fIt/t11dowhat.t\fR twice in a row is likely to fail (at least, if \fIt/t11dowhat.t\fR modifies the database at all) because the database at the start of the second run is not what you saw at the start of the first run. .IP "\(bu" 4 Document in your \fI\s-1README\s0\fR file what you do, and what privileges people need to do it. .IP "\(bu" 4 You can, and probably should, sequence your tests by including a test number before an abbreviated version of the test name; the tests are run in the order in which the names are expanded by shell-style globbing. .IP "\(bu" 4 It is in your interests to ensure that your tests work as widely as possible. .PP Many drivers also install sub-modules \fBDBD::Driver::SubModule\fR for any of a variety of different reasons, such as to support the metadata methods (see the discussion of \*(L"\s-1METADATA METHODS\*(R"\s0 below). Such sub-modules are conventionally stored in the directory \&\fIlib/DBD/Driver\fR. The module itself would usually be in a file \&\fISubModule.pm\fR. All such sub-modules should themselves be version stamped (see the discussions far below). .PP \fIExtra files needed by C/XS drivers\fR .IX Subsection "Extra files needed by C/XS drivers" .PP The software for a C/XS driver will typically contain at least four extra files that are not relevant to a pure Perl driver. .IP "\(bu" 4 \&\fIDriver.xs\fR .IP "\(bu" 4 \&\fIDriver.h\fR .IP "\(bu" 4 \&\fIdbdimp.h\fR .IP "\(bu" 4 \&\fIdbdimp.c\fR .PP The \fIDriver.xs\fR file is used to generate C code that Perl can call to gain access to the C functions you write that will, in turn, call down onto your database software. .PP The \fIDriver.h\fR header is a stylized header that ensures you can access the necessary Perl and \fB\s-1DBI\s0\fR macros, types, and function declarations. .PP The \fIdbdimp.h\fR is used to specify which functions have been implemented by your driver. .PP The \fIdbdimp.c\fR file is where you write the C code that does the real work of translating between Perl-ish data types and what the database expects to use and return. .PP There are some (mainly small, but very important) differences between the contents of \fIMakefile.PL\fR and \fIDriver.pm\fR for pure Perl and C/XS drivers, so those files are described both in the section on creating a pure Perl driver and in the section on creating a C/XS driver. .PP Obviously, you can add extra source code files to the list. .SS "Requirements on a driver and driver writer" .IX Subsection "Requirements on a driver and driver writer" To be remotely useful, your driver must be implemented in a format that allows it to be distributed via \s-1CPAN,\s0 the Comprehensive Perl Archive Network ( and ). Of course, it is easier if you do not have to meet this criterion, but you will not be able to ask for much help if you do not do so, and no-one is likely to want to install your module if they have to learn a new installation mechanism. .SH "CREATING A PURE PERL DRIVER" .IX Header "CREATING A PURE PERL DRIVER" Writing a pure Perl driver is surprisingly simple. However, there are some problems you should be aware of. The best option is of course picking up an existing driver and carefully modifying one method after the other. .PP Also look carefully at \fBDBD::AnyData\fR and \fBDBD::Template\fR. .PP As an example we take a look at the \fBDBD::File\fR driver, a driver for accessing plain files as tables, which is part of the \fB\s-1DBD::CSV\s0\fR package. .PP The minimal set of files we have to implement are \fIMakefile.PL\fR, \&\fI\s-1README\s0\fR, \fI\s-1MANIFEST\s0\fR and \fIDriver.pm\fR. .SS "Pure Perl version of Makefile.PL" .IX Subsection "Pure Perl version of Makefile.PL" You typically start with writing \fIMakefile.PL\fR, a Makefile generator. The contents of this file are described in detail in the ExtUtils::MakeMaker man pages. It is definitely a good idea if you start reading them. At least you should know about the variables \fI\s-1CONFIGURE\s0\fR, \fI\s-1DEFINED\s0\fR, \fI\s-1PM\s0\fR, \fI\s-1DIR\s0\fR, \fI\s-1EXE_FILES\s0\fR, \&\fI\s-1INC\s0\fR, \fI\s-1LIBS\s0\fR, \fI\s-1LINKTYPE\s0\fR, \fI\s-1NAME\s0\fR, \fI\s-1OPTIMIZE\s0\fR, \fI\s-1PL_FILES\s0\fR, \&\fI\s-1VERSION\s0\fR, \fI\s-1VERSION_FROM\s0\fR, \fIclean\fR, \fIdepend\fR, \fIrealclean\fR from the ExtUtils::MakeMaker man page: these are used in almost any \&\fIMakefile.PL\fR. .PP Additionally read the section on \fIOverriding MakeMaker Methods\fR and the descriptions of the \fIdistcheck\fR, \fIdisttest\fR and \fIdist\fR targets: They will definitely be useful for you. .PP Of special importance for \fB\s-1DBI\s0\fR drivers is the \fIpostamble\fR method from the ExtUtils::MM_Unix man page. .PP For Emacs users, I recommend the \fIlibscan\fR method, which removes Emacs backup files (file names which end with a tilde '~') from lists of files. .PP Now an example, I use the word \f(CW\*(C`Driver\*(C'\fR wherever you should insert your driver's name: .PP .Vb 1 \& # \-*\- perl \-*\- \& \& use ExtUtils::MakeMaker; \& \& WriteMakefile( \& dbd_edit_mm_attribs( { \& \*(AqNAME\*(Aq => \*(AqDBD::Driver\*(Aq, \& \*(AqVERSION_FROM\*(Aq => \*(AqDriver.pm\*(Aq, \& \*(AqINC\*(Aq => \*(Aq\*(Aq, \& \*(Aqdist\*(Aq => { \*(AqSUFFIX\*(Aq => \*(Aq.gz\*(Aq, \& \*(AqCOMPRESS\*(Aq => \*(Aqgzip \-9f\*(Aq }, \& \*(Aqrealclean\*(Aq => { FILES => \*(Aq*.xsi\*(Aq }, \& \*(AqPREREQ_PM\*(Aq => \*(Aq1.03\*(Aq, \& \*(AqCONFIGURE\*(Aq => sub { \& eval {require DBI::DBD;}; \& if ($@) { \& warn $@; \& exit 0; \& } \& my $dbi_arch_dir = dbd_dbi_arch_dir(); \& if (exists($opts{INC})) { \& return {INC => "$opts{INC} \-I$dbi_arch_dir"}; \& } else { \& return {INC => "\-I$dbi_arch_dir"}; \& } \& } \& }, \& { create_pp_tests => 1}) \& ); \& \& package MY; \& sub postamble { return main::dbd_postamble(@_); } \& sub libscan { \& my ($self, $path) = @_; \& ($path =~ m/\e~$/) ? undef : $path; \& } .Ve .PP Note the calls to \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR and \f(CW\*(C`dbd_postamble()\*(C'\fR. .PP The second hash reference in the call to \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR (containing \f(CW\*(C`create_pp_tests()\*(C'\fR) is optional; you should not use it unless your driver is a pure Perl driver (that is, it does not use C and \&\s-1XS\s0 code). Therefore, the call to \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR is not relevant for C/XS drivers and may be omitted; simply use the (single) hash reference containing \s-1NAME\s0 etc as the only argument to \f(CW\*(C`WriteMakefile()\*(C'\fR. .PP Note that the \f(CW\*(C`dbd_edit_mm_attribs()\*(C'\fR code will fail if you do not have a \&\fIt\fR sub-directory containing at least one test case. .PP \&\fI\s-1PREREQ_PM\s0\fR tells MakeMaker that \s-1DBI\s0 (version 1.03 in this case) is required for this module. This will issue a warning that \s-1DBI 1.03\s0 is missing if someone attempts to install your \s-1DBD\s0 without \s-1DBI 1.03.\s0 See \&\fI\s-1CONFIGURE\s0\fR below for why this does not work reliably in stopping cpan testers failing your module if \s-1DBI\s0 is not installed. .PP \&\fI\s-1CONFIGURE\s0\fR is a subroutine called by MakeMaker during \&\f(CW\*(C`WriteMakefile\*(C'\fR. By putting the \f(CW\*(C`require DBI::DBD\*(C'\fR in this section we can attempt to load \s-1DBI::DBD\s0 but if it is missing we exit with success. As we exit successfully without creating a Makefile when \&\s-1DBI::DBD\s0 is missing cpan testers will not report a failure. This may seem at odds with \fI\s-1PREREQ_PM\s0\fR but \fI\s-1PREREQ_PM\s0\fR does not cause \&\f(CW\*(C`WriteMakefile\*(C'\fR to fail (unless you also specify \s-1PREREQ_FATAL\s0 which is strongly discouraged by MakeMaker) so \f(CW\*(C`WriteMakefile\*(C'\fR would continue to call \f(CW\*(C`dbd_dbi_arch_dir\*(C'\fR and fail. .PP All drivers must use \f(CW\*(C`dbd_postamble()\*(C'\fR or risk running into problems. .PP Note the specification of \fI\s-1VERSION_FROM\s0\fR; the named file (\fIDriver.pm\fR) will be scanned for the first line that looks like an assignment to \fI\f(CI$VERSION\fI\fR, and the subsequent text will be used to determine the version number. Note the commentary in ExtUtils::MakeMaker on the subject of correctly formatted version numbers. .PP If your driver depends upon external software (it usually will), you will need to add code to ensure that your environment is workable before the call to \f(CW\*(C`WriteMakefile()\*(C'\fR. If you need to check for the existence of an external library and perhaps modify \fI\s-1INC\s0\fR to include the paths to where the external library header files are located and you cannot find the library or header files make sure you output a message saying they cannot be found but \f(CW\*(C`exit 0\*(C'\fR (success) \fBbefore\fR calling \f(CW\*(C`WriteMakefile\*(C'\fR or \s-1CPAN\s0 testers will fail your module if the external library is not found. .PP A full-fledged \fIMakefile.PL\fR can be quite large (for example, the files for \fBDBD::Oracle\fR and \fBDBD::Informix\fR are both over 1000 lines long, and the Informix one uses \- and creates \- auxiliary modules too). .PP See also ExtUtils::MakeMaker and ExtUtils::MM_Unix. Consider using CPAN::MakeMaker in place of \fIExtUtils::MakeMaker\fR. .SS "\s-1README\s0" .IX Subsection "README" The \s-1README\s0 file should describe what the driver is for, the pre-requisites for the build process, the actual build process, how to report errors, and who to report them to. .PP Users will find ways of breaking the driver build and test process which you would never even have dreamed to be possible in your worst nightmares. Therefore, you need to write this document defensively, precisely and concisely. .PP As always, use the \fI\s-1README\s0\fR from one of the established drivers as a basis for your own; the version in \fBDBD::Informix\fR is worth a look as it has been quite successful in heading off problems. .IP "\(bu" 4 Note that users will have versions of Perl and \fB\s-1DBI\s0\fR that are both older and newer than you expected, but this will seldom cause much trouble. When it does, it will be because you are using features of \fB\s-1DBI\s0\fR that are not supported in the version they are using. .IP "\(bu" 4 Note that users will have versions of the database software that are both older and newer than you expected. You will save yourself time in the long run if you can identify the range of versions which have been tested and warn about versions which are not known to be \s-1OK.\s0 .IP "\(bu" 4 Note that many people trying to install your driver will not be experts in the database software. .IP "\(bu" 4 Note that many people trying to install your driver will not be experts in C or Perl. .SS "\s-1MANIFEST\s0" .IX Subsection "MANIFEST" The \fI\s-1MANIFEST\s0\fR will be used by the Makefile's dist target to build the distribution tar file that is uploaded to \s-1CPAN.\s0 It should list every file that you want to include in your distribution, one per line. .SS "lib/Bundle/DBD/Driver.pm" .IX Subsection "lib/Bundle/DBD/Driver.pm" The \s-1CPAN\s0 module provides an extremely powerful bundle mechanism that allows you to specify pre-requisites for your driver. .PP The primary pre-requisite is \fBBundle::DBI\fR; you may want or need to add some more. With the bundle set up correctly, the user can type: .PP .Vb 1 \& perl \-MCPAN \-e \*(Aqinstall Bundle::DBD::Driver\*(Aq .Ve .PP and Perl will download, compile, test and install all the Perl modules needed to build your driver. .PP The prerequisite modules are listed in the \f(CW\*(C`CONTENTS\*(C'\fR section, with the official name of the module followed by a dash and an informal name or description. .IP "\(bu" 4 Listing \fBBundle::DBI\fR as the main pre-requisite simplifies life. .IP "\(bu" 4 Don't forget to list your driver. .IP "\(bu" 4 Note that unless the \s-1DBMS\s0 is itself a Perl module, you cannot list it as a pre-requisite in this file. .IP "\(bu" 4 You should keep the version of the bundle the same as the version of your driver. .IP "\(bu" 4 You should add configuration management, copyright, and licencing information at the top. .PP A suitable skeleton for this file is shown below. .PP .Vb 1 \& package Bundle::DBD::Driver; \& \& $VERSION = \*(Aq0.01\*(Aq; \& \& 1; \& \& _\|_END_\|_ \& \& =head1 NAME \& \& Bundle::DBD::Driver \- A bundle to install all DBD::Driver related modules \& \& =head1 SYNOPSIS \& \& C \& \& =head1 CONTENTS \& \& Bundle::DBI \- Bundle for DBI by TIMB (Tim Bunce) \& \& DBD::Driver \- DBD::Driver by YOU (Your Name) \& \& =head1 DESCRIPTION \& \& This bundle includes all the modules used by the Perl Database \& Interface (DBI) driver for Driver (DBD::Driver), assuming the \& use of DBI version 1.13 or later, created by Tim Bunce. \& \& If you\*(Aqve not previously used the CPAN module to install any \& bundles, you will be interrogated during its setup phase. \& But when you\*(Aqve done it once, it remembers what you told it. \& You could start by running: \& \& C \& \& =head1 SEE ALSO \& \& Bundle::DBI \& \& =head1 AUTHOR \& \& Your Name EFE \& \& =head1 THANKS \& \& This bundle was created by ripping off Bundle::libnet created by \& Graham Barr EFE, and radically simplified \& with some information from Jochen Wiedmann EFE. \& The template was then included in the DBI::DBD documentation by \& Jonathan Leffler EFE. \& \& =cut .Ve .SS "lib/DBD/Driver/Summary.pm" .IX Subsection "lib/DBD/Driver/Summary.pm" There is no substitute for taking the summary file from a driver that was documented in the Perl book (such as \fBDBD::Oracle\fR or \fBDBD::Informix\fR or \&\fB\s-1DBD::ODBC\s0\fR, to name but three), and adapting it to describe the facilities available via \fBDBD::Driver\fR when accessing the Driver database. .SS "Pure Perl version of Driver.pm" .IX Subsection "Pure Perl version of Driver.pm" The \fIDriver.pm\fR file defines the Perl module \fBDBD::Driver\fR for your driver. It will define a package \fBDBD::Driver\fR along with some version information, some variable definitions, and a function \f(CW\*(C`driver()\*(C'\fR which will have a more or less standard structure. .PP It will also define three sub-packages of \fBDBD::Driver\fR: .IP "DBD::Driver::dr" 4 .IX Item "DBD::Driver::dr" with methods \f(CW\*(C`connect()\*(C'\fR, \f(CW\*(C`data_sources()\*(C'\fR and \f(CW\*(C`disconnect_all()\*(C'\fR; .IP "DBD::Driver::db" 4 .IX Item "DBD::Driver::db" with methods such as \f(CW\*(C`prepare()\*(C'\fR; .IP "DBD::Driver::st" 4 .IX Item "DBD::Driver::st" with methods such as \f(CW\*(C`execute()\*(C'\fR and \f(CW\*(C`fetch()\*(C'\fR. .PP The \fIDriver.pm\fR file will also contain the documentation specific to \&\fBDBD::Driver\fR in the format used by perldoc. .PP In a pure Perl driver, the \fIDriver.pm\fR file is the core of the implementation. You will need to provide all the key methods needed by \fB\s-1DBI\s0\fR. .PP Now let's take a closer look at an excerpt of \fIFile.pm\fR as an example. We ignore things that are common to any module (even non-DBI modules) or really specific to the \fBDBD::File\fR package. .PP \fIThe DBD::Driver package\fR .IX Subsection "The DBD::Driver package" .PP The header .IX Subsection "The header" .PP .Vb 1 \& package DBD::File; \& \& use strict; \& use vars qw($VERSION $drh); \& \& $VERSION = "1.23.00" # Version number of DBD::File .Ve .PP This is where the version number of your driver is specified, and is where \fIMakefile.PL\fR looks for this information. Please ensure that any other modules added with your driver are also version stamped so that \&\s-1CPAN\s0 does not get confused. .PP It is recommended that you use a two-part (1.23) or three-part (1.23.45) version number. Also consider the \s-1CPAN\s0 system, which gets confused and considers version 1.10 to precede version 1.9, so that using a raw \s-1CVS, RCS\s0 or \s-1SCCS\s0 version number is probably not appropriate (despite being very common). .PP For Subversion you could use: .PP .Vb 1 \& $VERSION = "12.012346"; .Ve .PP (use lots of leading zeros on the second portion so if you move the code to a shared repository like svn.perl.org the much larger revision numbers won't cause a problem, at least not for a few years). For \s-1RCS\s0 or \s-1CVS\s0 you can use: .PP .Vb 1 \& $VERSION = "11.22"; .Ve .PP which pads out the fractional part with leading zeros so all is well (so long as you don't go past x.99) .PP .Vb 1 \& $drh = undef; # holds driver handle once initialized .Ve .PP This is where the driver handle will be stored, once created. Note that you may assume there is only one handle for your driver. .PP The driver constructor .IX Subsection "The driver constructor" .PP The \f(CW\*(C`driver()\*(C'\fR method is the driver handle constructor. Note that the \f(CW\*(C`driver()\*(C'\fR method is in the \fBDBD::Driver\fR package, not in one of the sub-packages \fBDBD::Driver::dr\fR, \fBDBD::Driver::db\fR, or \&\fBDBD::Driver::db\fR. .PP .Vb 4 \& sub driver \& { \& return $drh if $drh; # already created \- return same one \& my ($class, $attr) = @_; \& \& $class .= "::dr"; \& \& DBD::Driver::db\->install_method(\*(Aqdrv_example_dbh_method\*(Aq); \& DBD::Driver::st\->install_method(\*(Aqdrv_example_sth_method\*(Aq); \& \& # not a \*(Aqmy\*(Aq since we use it above to prevent multiple drivers \& $drh = DBI::_new_drh($class, { \& \*(AqName\*(Aq => \*(AqFile\*(Aq, \& \*(AqVersion\*(Aq => $VERSION, \& \*(AqAttribution\*(Aq => \*(AqDBD::File by Jochen Wiedmann\*(Aq, \& }) \& or return undef; \& \& return $drh; \& } .Ve .PP This is a reasonable example of how \fB\s-1DBI\s0\fR implements its handles. There are three kinds: \fBdriver handles\fR (typically stored in \fI\f(CI$drh\fI\fR; from now on called \fIdrh\fR or \fI\f(CI$drh\fI\fR), \fBdatabase handles\fR (from now on called \fIdbh\fR or \fI\f(CI$dbh\fI\fR) and \fBstatement handles\fR (from now on called \&\fIsth\fR or \fI\f(CI$sth\fI\fR). .PP The prototype of \f(CW\*(C`DBI::_new_drh()\*(C'\fR is .PP .Vb 1 \& $drh = DBI::_new_drh($class, $public_attrs, $private_attrs); .Ve .PP with the following arguments: .IP "\fI\f(CI$class\fI\fR" 4 .IX Item "$class" is typically the class for your driver, (for example, \*(L"DBD::File::dr\*(R"), passed as the first argument to the \f(CW\*(C`driver()\*(C'\fR method. .IP "\fI\f(CI$public_attrs\fI\fR" 4 .IX Item "$public_attrs" is a hash ref to attributes like \fIName\fR, \fIVersion\fR, and \fIAttribution\fR. These are processed and used by \fB\s-1DBI\s0\fR. You had better not make any assumptions about them nor should you add private attributes here. .IP "\fI\f(CI$private_attrs\fI\fR" 4 .IX Item "$private_attrs" This is another (optional) hash ref with your private attributes. \&\fB\s-1DBI\s0\fR will store them and otherwise leave them alone. .PP The \f(CW\*(C`DBI::_new_drh()\*(C'\fR method and the \f(CW\*(C`driver()\*(C'\fR method both return \f(CW\*(C`undef\*(C'\fR for failure (in which case you must look at \fI\f(CI$DBI::err\fI\fR and \fI\f(CI$DBI::errstr\fI\fR for the failure information, because you have no driver handle to use). .PP Using \fBinstall_method()\fR to expose driver-private methods .IX Subsection "Using install_method() to expose driver-private methods" .PP .Vb 1 \& DBD::Foo::db\->install_method($method_name, \e%attr); .Ve .PP Installs the driver-private method named by \f(CW$method_name\fR into the \&\s-1DBI\s0 method dispatcher so it can be called directly, avoiding the need to use the \fBfunc()\fR method. .PP It is called as a static method on the driver class to which the method belongs. The method name must begin with the corresponding registered driver-private prefix. For example, for DBD::Oracle \&\f(CW$method_name\fR must being with '\f(CW\*(C`ora_\*(C'\fR', and for DBD::AnyData it must begin with '\f(CW\*(C`ad_\*(C'\fR'. .PP The \f(CW\*(C`\e%attr\*(C'\fR attributes can be used to provide fine control over how the \s-1DBI\s0 dispatcher handles the dispatching of the method. However it's undocumented at the moment. See the IMA_* #define's in \s-1DBI\s0.xs and the O=>0x000x values in the initialization of \f(CW%DBI::DBI_methods\fR in \s-1DBI\s0.pm. (Volunteers to polish up and document the interface are very welcome to get in touch via dbi\-dev@perl.org). .PP Methods installed using install_method default to the standard error handling behaviour for \s-1DBI\s0 methods: clearing err and errstr before calling the method, and checking for errors to trigger RaiseError etc. on return. This differs from the default behaviour of \fBfunc()\fR. .PP Note for driver authors: The DBD::Foo::xx\->install_method call won't work until the class-hierarchy has been setup. Normally the \s-1DBI\s0 looks after that just after the driver is loaded. This means \&\fBinstall_method()\fR can't be called at the time the driver is loaded unless the class-hierarchy is set up first. The way to do that is to call the \fBsetup_driver()\fR method: .PP .Vb 1 \& DBI\->setup_driver(\*(AqDBD::Foo\*(Aq); .Ve .PP before using \fBinstall_method()\fR. .PP The \s-1CLONE\s0 special subroutine .IX Subsection "The CLONE special subroutine" .PP Also needed here, in the \fBDBD::Driver\fR package, is a \f(CW\*(C`CLONE()\*(C'\fR method that will be called by perl when an interpreter is cloned. All your \&\f(CW\*(C`CLONE()\*(C'\fR method needs to do, currently, is clear the cached \fI\f(CI$drh\fI\fR so the new interpreter won't start using the cached \fI\f(CI$drh\fI\fR from the old interpreter: .PP .Vb 3 \& sub CLONE { \& undef $drh; \& } .Ve .PP See for details. .PP \fIThe DBD::Driver::dr package\fR .IX Subsection "The DBD::Driver::dr package" .PP The next lines of code look as follows: .PP .Vb 1 \& package DBD::Driver::dr; # ====== DRIVER ====== \& \& $DBD::Driver::dr::imp_data_size = 0; .Ve .PP Note that no \fI\f(CI@ISA\fI\fR is needed here, or for the other \fBDBD::Driver::*\fR classes, because the \fB\s-1DBI\s0\fR takes care of that for you when the driver is loaded. .PP .Vb 2 \& *FIX ME* Explain what the imp_data_size is, so that implementors aren\*(Aqt \& practicing cargo\-cult programming. .Ve .PP The database handle constructor .IX Subsection "The database handle constructor" .PP The database handle constructor is the driver's (hence the changed namespace) \f(CW\*(C`connect()\*(C'\fR method: .PP .Vb 3 \& sub connect \& { \& my ($drh, $dr_dsn, $user, $auth, $attr) = @_; \& \& # Some database specific verifications, default settings \& # and the like can go here. This should only include \& # syntax checks or similar stuff where it\*(Aqs legal to \& # \*(Aqdie\*(Aq in case of errors. \& # For example, many database packages requires specific \& # environment variables to be set; this could be where you \& # validate that they are set, or default them if they are not set. \& \& my $driver_prefix = "drv_"; # the assigned prefix for this driver \& \& # Process attributes from the DSN; we assume ODBC syntax \& # here, that is, the DSN looks like var1=val1;...;varN=valN \& foreach my $var ( split /;/, $dr_dsn ) { \& my ($attr_name, $attr_value) = split \*(Aq=\*(Aq, $var, 2; \& return $drh\->set_err($DBI::stderr, "Can\*(Aqt parse DSN part \*(Aq$var\*(Aq") \& unless defined $attr_value; \& \& # add driver prefix to attribute name if it doesn\*(Aqt have it already \& $attr_name = $driver_prefix.$attr_name \& unless $attr_name =~ /^$driver_prefix/o; \& \& # Store attribute into %$attr, replacing any existing value. \& # The DBI will STORE() these into $dbh after we\*(Aqve connected \& $attr\->{$attr_name} = $attr_value; \& } \& \& # Get the attributes we\*(Aqll use to connect. \& # We use delete here because these no need to STORE them \& my $db = delete $attr\->{drv_database} || delete $attr\->{drv_db} \& or return $drh\->set_err($DBI::stderr, "No database name given in DSN \*(Aq$dr_dsn\*(Aq"); \& my $host = delete $attr\->{drv_host} || \*(Aqlocalhost\*(Aq; \& my $port = delete $attr\->{drv_port} || 123456; \& \& # Assume you can attach to your database via drv_connect: \& my $connection = drv_connect($db, $host, $port, $user, $auth) \& or return $drh\->set_err($DBI::stderr, "Can\*(Aqt connect to $dr_dsn: ..."); \& \& # create a \*(Aqblank\*(Aq dbh (call superclass constructor) \& my ($outer, $dbh) = DBI::_new_dbh($drh, { Name => $dr_dsn }); \& \& $dbh\->STORE(\*(AqActive\*(Aq, 1 ); \& $dbh\->{drv_connection} = $connection; \& \& return $outer; \& } .Ve .PP This is mostly the same as in the \fIdriver handle constructor\fR above. The arguments are described in \s-1DBI\s0. .PP The constructor \f(CW\*(C`DBI::_new_dbh()\*(C'\fR is called, returning a database handle. The constructor's prototype is: .PP .Vb 1 \& ($outer, $inner) = DBI::_new_dbh($drh, $public_attr, $private_attr); .Ve .PP with similar arguments to those in the \fIdriver handle constructor\fR, except that the \fI\f(CI$class\fI\fR is replaced by \fI\f(CI$drh\fI\fR. The \fIName\fR attribute is a standard \fB\s-1DBI\s0\fR attribute (see \*(L"Database Handle Attributes\*(R" in \s-1DBI\s0). .PP In scalar context, only the outer handle is returned. .PP Note the use of the \f(CW\*(C`STORE()\*(C'\fR method for setting the \fIdbh\fR attributes. That's because within the driver code, the handle object you have is the 'inner' handle of a tied hash, not the outer handle that the users of your driver have. .PP Because you have the inner handle, tie magic doesn't get invoked when you get or set values in the hash. This is often very handy for speed when you want to get or set simple non-special driver-specific attributes. .PP However, some attribute values, such as those handled by the \fB\s-1DBI\s0\fR like \&\fIPrintError\fR, don't actually exist in the hash and must be read via \&\f(CW\*(C`$h\->FETCH($attrib)\*(C'\fR and set via \f(CW\*(C`$h\->STORE($attrib, $value)\*(C'\fR. If in any doubt, use these methods. .PP The \fBdata_sources()\fR method .IX Subsection "The data_sources() method" .PP The \f(CW\*(C`data_sources()\*(C'\fR method must populate and return a list of valid data sources, prefixed with the "\fIdbi:Driver\fR" incantation that allows them to be used in the first argument of the \f(CW\*(C`DBI\->connect()\*(C'\fR method. An example of this might be scanning the \fI\f(CI$HOME\fI/.odbcini\fR file on Unix for \s-1ODBC\s0 data sources (DSNs). .PP As a trivial example, consider a fixed list of data sources: .PP .Vb 11 \& sub data_sources \& { \& my($drh, $attr) = @_; \& my(@list) = (); \& # You need more sophisticated code than this to set @list... \& push @list, "dbi:Driver:abc"; \& push @list, "dbi:Driver:def"; \& push @list, "dbi:Driver:ghi"; \& # End of code to set @list \& return @list; \& } .Ve .PP The \fBdisconnect_all()\fR method .IX Subsection "The disconnect_all() method" .PP If you need to release any resources when the driver is unloaded, you can provide a disconnect_all method. .PP Other driver handle methods .IX Subsection "Other driver handle methods" .PP If you need any other driver handle methods, they can follow here. .PP Error handling .IX Subsection "Error handling" .PP It is quite likely that something fails in the connect method. With \fBDBD::File\fR for example, you might catch an error when setting the current directory to something not existent by using the (driver-specific) \fIf_dir\fR attribute. .PP To report an error, you use the \f(CW\*(C`set_err()\*(C'\fR method: .PP .Vb 1 \& $h\->set_err($err, $errmsg, $state); .Ve .PP This will ensure that the error is recorded correctly and that \&\fIRaiseError\fR and \fIPrintError\fR etc are handled correctly. .PP Typically you'll always use the method instance, aka your method's first argument. .PP As \f(CW\*(C`set_err()\*(C'\fR always returns \f(CW\*(C`undef\*(C'\fR your error handling code can usually be simplified to something like this: .PP .Vb 1 \& return $h\->set_err($err, $errmsg, $state) if ...; .Ve .PP \fIThe DBD::Driver::db package\fR .IX Subsection "The DBD::Driver::db package" .PP .Vb 1 \& package DBD::Driver::db; # ====== DATABASE ====== \& \& $DBD::Driver::db::imp_data_size = 0; .Ve .PP The statement handle constructor .IX Subsection "The statement handle constructor" .PP There's nothing much new in the statement handle constructor, which is the \f(CW\*(C`prepare()\*(C'\fR method: .PP .Vb 3 \& sub prepare \& { \& my ($dbh, $statement, @attribs) = @_; \& \& # create a \*(Aqblank\*(Aq sth \& my ($outer, $sth) = DBI::_new_sth($dbh, { Statement => $statement }); \& \& $sth\->STORE(\*(AqNUM_OF_PARAMS\*(Aq, ($statement =~ tr/?//)); \& \& $sth\->{drv_params} = []; \& \& return $outer; \& } .Ve .PP This is still the same \*(-- check the arguments and call the super class constructor \f(CW\*(C`DBI::_new_sth()\*(C'\fR. Again, in scalar context, only the outer handle is returned. The \fIStatement\fR attribute should be cached as shown. .PP Note the prefix \fIdrv_\fR in the attribute names: it is required that all your private attributes use a lowercase prefix unique to your driver. As mentioned earlier in this document, the \fB\s-1DBI\s0\fR contains a registry of known driver prefixes and may one day warn about unknown attributes that don't have a registered prefix. .PP Note that we parse the statement here in order to set the attribute \&\fI\s-1NUM_OF_PARAMS\s0\fR. The technique illustrated is not very reliable; it can be confused by question marks appearing in quoted strings, delimited identifiers or in \s-1SQL\s0 comments that are part of the \s-1SQL\s0 statement. We could set \fI\s-1NUM_OF_PARAMS\s0\fR in the \f(CW\*(C`execute()\*(C'\fR method instead because the \fB\s-1DBI\s0\fR specification explicitly allows a driver to defer this, but then the user could not call \f(CW\*(C`bind_param()\*(C'\fR. .PP Transaction handling .IX Subsection "Transaction handling" .PP Pure Perl drivers will rarely support transactions. Thus your \f(CW\*(C`commit()\*(C'\fR and \f(CW\*(C`rollback()\*(C'\fR methods will typically be quite simple: .PP .Vb 8 \& sub commit \& { \& my ($dbh) = @_; \& if ($dbh\->FETCH(\*(AqWarn\*(Aq)) { \& warn("Commit ineffective while AutoCommit is on"); \& } \& 0; \& } \& \& sub rollback { \& my ($dbh) = @_; \& if ($dbh\->FETCH(\*(AqWarn\*(Aq)) { \& warn("Rollback ineffective while AutoCommit is on"); \& } \& 0; \& } .Ve .PP Or even simpler, just use the default methods provided by the \fB\s-1DBI\s0\fR that do nothing except return \f(CW\*(C`undef\*(C'\fR. .PP The \fB\s-1DBI\s0\fR's default \f(CW\*(C`begin_work()\*(C'\fR method can be used by inheritance. .PP The \s-1\fBSTORE\s0()\fR and \s-1\fBFETCH\s0()\fR methods .IX Subsection "The STORE() and FETCH() methods" .PP These methods (that we have already used, see above) are called for you, whenever the user does a: .PP .Vb 1 \& $dbh\->{$attr} = $val; .Ve .PP or, respectively, .PP .Vb 1 \& $val = $dbh\->{$attr}; .Ve .PP See perltie for details on tied hash refs to understand why these methods are required. .PP The \fB\s-1DBI\s0\fR will handle most attributes for you, in particular attributes like \fIRaiseError\fR or \fIPrintError\fR. All you have to do is handle your driver's private attributes and any attributes, like \fIAutoCommit\fR and \&\fIChopBlanks\fR, that the \fB\s-1DBI\s0\fR can't handle for you. .PP A good example might look like this: .PP .Vb 10 \& sub STORE \& { \& my ($dbh, $attr, $val) = @_; \& if ($attr eq \*(AqAutoCommit\*(Aq) { \& # AutoCommit is currently the only standard attribute we have \& # to consider. \& if (!$val) { die "Can\*(Aqt disable AutoCommit"; } \& return 1; \& } \& if ($attr =~ m/^drv_/) { \& # Handle only our private attributes here \& # Note that we could trigger arbitrary actions. \& # Ideally we should warn about unknown attributes. \& $dbh\->{$attr} = $val; # Yes, we are allowed to do this, \& return 1; # but only for our private attributes \& } \& # Else pass up to DBI to handle for us \& $dbh\->SUPER::STORE($attr, $val); \& } \& \& sub FETCH \& { \& my ($dbh, $attr) = @_; \& if ($attr eq \*(AqAutoCommit\*(Aq) { return 1; } \& if ($attr =~ m/^drv_/) { \& # Handle only our private attributes here \& # Note that we could trigger arbitrary actions. \& return $dbh\->{$attr}; # Yes, we are allowed to do this, \& # but only for our private attributes \& } \& # Else pass up to DBI to handle \& $dbh\->SUPER::FETCH($attr); \& } .Ve .PP The \fB\s-1DBI\s0\fR will actually store and fetch driver-specific attributes (with all lowercase names) without warning or error, so there's actually no need to implement driver-specific any code in your \f(CW\*(C`FETCH()\*(C'\fR and \f(CW\*(C`STORE()\*(C'\fR methods unless you need extra logic/checks, beyond getting or setting the value. .PP Unless your driver documentation indicates otherwise, the return value of the \f(CW\*(C`STORE()\*(C'\fR method is unspecified and the caller shouldn't use that value. .PP Other database handle methods .IX Subsection "Other database handle methods" .PP As with the driver package, other database handle methods may follow here. In particular you should consider a (possibly empty) \f(CW\*(C`disconnect()\*(C'\fR method and possibly a \f(CW\*(C`quote()\*(C'\fR method if \fB\s-1DBI\s0\fR's default isn't correct for you. You may also need the \f(CW\*(C`type_info_all()\*(C'\fR and \f(CW\*(C`get_info()\*(C'\fR methods, as described elsewhere in this document. .PP Where reasonable use \f(CW\*(C`$h\->SUPER::foo()\*(C'\fR to call the \fB\s-1DBI\s0\fR's method in some or all cases and just wrap your custom behavior around that. .PP If you want to use private trace flags you'll probably want to be able to set them by name. To do that you'll need to define a \&\f(CW\*(C`parse_trace_flag()\*(C'\fR method (note that's \*(L"parse_trace_flag\*(R", singular, not \*(L"parse_trace_flags\*(R", plural). .PP .Vb 9 \& sub parse_trace_flag { \& my ($h, $name) = @_; \& return 0x01000000 if $name eq \*(Aqfoo\*(Aq; \& return 0x02000000 if $name eq \*(Aqbar\*(Aq; \& return 0x04000000 if $name eq \*(Aqbaz\*(Aq; \& return 0x08000000 if $name eq \*(Aqboo\*(Aq; \& return 0x10000000 if $name eq \*(Aqbop\*(Aq; \& return $h\->SUPER::parse_trace_flag($name); \& } .Ve .PP All private flag names must be lowercase, and all private flags must be in the top 8 of the 32 bits. .PP \fIThe DBD::Driver::st package\fR .IX Subsection "The DBD::Driver::st package" .PP This package follows the same pattern the others do: .PP .Vb 1 \& package DBD::Driver::st; \& \& $DBD::Driver::st::imp_data_size = 0; .Ve .PP The \fBexecute()\fR and \fBbind_param()\fR methods .IX Subsection "The execute() and bind_param() methods" .PP This is perhaps the most difficult method because we have to consider parameter bindings here. In addition to that, there are a number of statement attributes which must be set for inherited \fB\s-1DBI\s0\fR methods to function correctly (see \*(L"Statement attributes\*(R" below). .PP We present a simplified implementation by using the \fIdrv_params\fR attribute from above: .PP .Vb 12 \& sub bind_param \& { \& my ($sth, $pNum, $val, $attr) = @_; \& my $type = (ref $attr) ? $attr\->{TYPE} : $attr; \& if ($type) { \& my $dbh = $sth\->{Database}; \& $val = $dbh\->quote($sth, $type); \& } \& my $params = $sth\->{drv_params}; \& $params\->[$pNum\-1] = $val; \& 1; \& } \& \& sub execute \& { \& my ($sth, @bind_values) = @_; \& \& # start of by finishing any previous execution if still active \& $sth\->finish if $sth\->FETCH(\*(AqActive\*(Aq); \& \& my $params = (@bind_values) ? \& \e@bind_values : $sth\->{drv_params}; \& my $numParam = $sth\->FETCH(\*(AqNUM_OF_PARAMS\*(Aq); \& return $sth\->set_err($DBI::stderr, "Wrong number of parameters") \& if @$params != $numParam; \& my $statement = $sth\->{\*(AqStatement\*(Aq}; \& for (my $i = 0; $i < $numParam; $i++) { \& $statement =~ s/?/$params\->[$i]/; # XXX doesn\*(Aqt deal with quoting etc! \& } \& # Do anything ... we assume that an array ref of rows is \& # created and store it: \& $sth\->{\*(Aqdrv_data\*(Aq} = $data; \& $sth\->{\*(Aqdrv_rows\*(Aq} = @$data; # number of rows \& $sth\->STORE(\*(AqNUM_OF_FIELDS\*(Aq) = $numFields; \& $sth\->{Active} = 1; \& @$data || \*(Aq0E0\*(Aq; \& } .Ve .PP There are a number of things you should note here. .PP We initialize the \fI\s-1NUM_OF_FIELDS\s0\fR and \fIActive\fR attributes here, because they are essential for \f(CW\*(C`bind_columns()\*(C'\fR to work. .PP We use attribute \f(CW\*(C`$sth\->{Statement}\*(C'\fR which we created within \f(CW\*(C`prepare()\*(C'\fR. The attribute \f(CW\*(C`$sth\->{Database}\*(C'\fR, which is nothing else than the \fIdbh\fR, was automatically created by \fB\s-1DBI\s0\fR. .PP Finally, note that (as specified in the \fB\s-1DBI\s0\fR specification) we return the string \f(CW\*(Aq0E0\*(Aq\fR instead of the number 0, so that the result tests true but equal to zero. .PP .Vb 1 \& $sth\->execute() or die $sth\->errstr; .Ve .PP The \fBexecute_array()\fR, \fBexecute_for_fetch()\fR and \fBbind_param_array()\fR methods .IX Subsection "The execute_array(), execute_for_fetch() and bind_param_array() methods" .PP In general, \s-1DBD\s0's only need to implement \f(CW\*(C`execute_for_fetch()\*(C'\fR and \&\f(CW\*(C`bind_param_array\*(C'\fR. \s-1DBI\s0's default \f(CW\*(C`execute_array()\*(C'\fR will invoke the \&\s-1DBD\s0's \f(CW\*(C`execute_for_fetch()\*(C'\fR as needed. .PP The following sequence describes the interaction between \&\s-1DBI\s0 \f(CW\*(C`execute_array\*(C'\fR and a \s-1DBD\s0's \f(CW\*(C`execute_for_fetch\*(C'\fR: .IP "1." 4 App calls \f(CW\*(C`$sth\->execute_array(\e%attrs, @array_of_arrays)\*(C'\fR .IP "2." 4 If \f(CW@array_of_arrays\fR was specified, \s-1DBI\s0 processes \f(CW@array_of_arrays\fR by calling \&\s-1DBD\s0's \f(CW\*(C`bind_param_array()\*(C'\fR. Alternately, App may have directly called \&\f(CW\*(C`bind_param_array()\*(C'\fR .IP "3." 4 \&\s-1DBD\s0 validates and binds each array .IP "4." 4 \&\s-1DBI\s0 retrieves the validated param arrays from \s-1DBD\s0's ParamArray attribute .IP "5." 4 \&\s-1DBI\s0 calls \s-1DBD\s0's \f(CW\*(C`execute_for_fetch($fetch_tuple_sub, \e@tuple_status)\*(C'\fR, where \f(CW&$fetch_tuple_sub\fR is a closure to iterate over the returned ParamArray values, and \f(CW\*(C`\e@tuple_status\*(C'\fR is an array to receive the disposition status of each tuple. .IP "6." 4 \&\s-1DBD\s0 iteratively calls \f(CW&$fetch_tuple_sub\fR to retrieve parameter tuples to be added to its bulk database operation/request. .IP "7." 4 when \s-1DBD\s0 reaches the limit of tuples it can handle in a single database operation/request, or the \f(CW&$fetch_tuple_sub\fR indicates no more tuples by returning undef, the \s-1DBD\s0 executes the bulk operation, and reports the disposition of each tuple in \e@tuple_status. .IP "8." 4 \&\s-1DBD\s0 repeats steps 6 and 7 until all tuples are processed. .PP E.g., here's the essence of DBD::Oracle's execute_for_fetch: .PP .Vb 10 \& while (1) { \& my @tuple_batch; \& for (my $i = 0; $i < $batch_size; $i++) { \& push @tuple_batch, [ @{$fetch_tuple_sub\->() || last} ]; \& } \& last unless @tuple_batch; \& my $res = ora_execute_array($sth, \e@tuple_batch, \& scalar(@tuple_batch), $tuple_batch_status); \& push @$tuple_status, @$tuple_batch_status; \& } .Ve .PP Note that \s-1DBI\s0's default \fBexecute_array()\fR/\fBexecute_for_fetch()\fR implementation requires the use of positional (i.e., '?') placeholders. Drivers which \fBrequire\fR named placeholders must either emulate positional placeholders (e.g., see DBD::Oracle), or must implement their own \&\fBexecute_array()\fR/\fBexecute_for_fetch()\fR methods to properly sequence bound parameter arrays. .PP Fetching data .IX Subsection "Fetching data" .PP Only one method needs to be written for fetching data, \f(CW\*(C`fetchrow_arrayref()\*(C'\fR. The other methods, \f(CW\*(C`fetchrow_array()\*(C'\fR, \f(CW\*(C`fetchall_arrayref()\*(C'\fR, etc, as well as the database handle's \f(CW\*(C`select*\*(C'\fR methods are part of \fB\s-1DBI\s0\fR, and call \&\f(CW\*(C`fetchrow_arrayref()\*(C'\fR as necessary. .PP .Vb 10 \& sub fetchrow_arrayref \& { \& my ($sth) = @_; \& my $data = $sth\->{drv_data}; \& my $row = shift @$data; \& if (!$row) { \& $sth\->STORE(Active => 0); # mark as no longer active \& return undef; \& } \& if ($sth\->FETCH(\*(AqChopBlanks\*(Aq)) { \& map { $_ =~ s/\es+$//; } @$row; \& } \& return $sth\->_set_fbav($row); \& } \& *fetch = \e&fetchrow_arrayref; # required alias for fetchrow_arrayref .Ve .PP Note the use of the method \f(CW\*(C`_set_fbav()\*(C'\fR \*(-- this is required so that \&\f(CW\*(C`bind_col()\*(C'\fR and \f(CW\*(C`bind_columns()\*(C'\fR work. .PP If an error occurs which leaves the \fI\f(CI$sth\fI\fR in a state where remaining rows can't be fetched then \fIActive\fR should be turned off before the method returns. .PP The \f(CW\*(C`rows()\*(C'\fR method for this driver can be implemented like this: .PP .Vb 1 \& sub rows { shift\->{drv_rows} } .Ve .PP because it knows in advance how many rows it has fetched. Alternatively you could delete that method and so fallback to the \fB\s-1DBI\s0\fR's own method which does the right thing based on the number of calls to \f(CW\*(C`_set_fbav()\*(C'\fR. .PP The more_results method .IX Subsection "The more_results method" .PP If your driver doesn't support multiple result sets, then don't even implement this method. .PP Otherwise, this method needs to get the statement handle ready to fetch results from the next result set, if there is one. Typically you'd start with: .PP .Vb 1 \& $sth\->finish; .Ve .PP then you should delete all the attributes from the attribute cache that may no longer be relevant for the new result set: .PP .Vb 2 \& delete $sth\->{$_} \& for qw(NAME TYPE PRECISION SCALE ...); .Ve .PP for drivers written in C use: .PP .Vb 6 \& hv_delete((HV*)SvRV(sth), "NAME", 4, G_DISCARD); \& hv_delete((HV*)SvRV(sth), "NULLABLE", 8, G_DISCARD); \& hv_delete((HV*)SvRV(sth), "NUM_OF_FIELDS", 13, G_DISCARD); \& hv_delete((HV*)SvRV(sth), "PRECISION", 9, G_DISCARD); \& hv_delete((HV*)SvRV(sth), "SCALE", 5, G_DISCARD); \& hv_delete((HV*)SvRV(sth), "TYPE", 4, G_DISCARD); .Ve .PP Don't forget to also delete, or update, any driver-private attributes that may not be correct for the next resultset. .PP The \s-1NUM_OF_FIELDS\s0 attribute is a special case. It should be set using \s-1STORE:\s0 .PP .Vb 2 \& $sth\->STORE(NUM_OF_FIELDS => 0); /* for DBI <= 1.53 */ \& $sth\->STORE(NUM_OF_FIELDS => $new_value); .Ve .PP for drivers written in C use this incantation: .PP .Vb 5 \& /* Adjust NUM_OF_FIELDS \- which also adjusts the row buffer size */ \& DBIc_NUM_FIELDS(imp_sth) = 0; /* for DBI <= 1.53 */ \& DBIc_STATE(imp_xxh)\->set_attr_k(sth, sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0, \& sv_2mortal(newSViv(mysql_num_fields(imp_sth\->result))) \& ); .Ve .PP For \s-1DBI\s0 versions prior to 1.54 you'll also need to explicitly adjust the number of elements in the row buffer array (\f(CW\*(C`DBIc_FIELDS_AV(imp_sth)\*(C'\fR) to match the new result set. Fill any new values with \fBnewSV\fR\|(0) not &sv_undef. Alternatively you could free DBIc_FIELDS_AV(imp_sth) and set it to null, but that would mean \fBbind_columns()\fR wouldn't work across result sets. .PP Statement attributes .IX Subsection "Statement attributes" .PP The main difference between \fIdbh\fR and \fIsth\fR attributes is, that you should implement a lot of attributes here that are required by the \fB\s-1DBI\s0\fR, such as \fI\s-1NAME\s0\fR, \fI\s-1NULLABLE\s0\fR, \fI\s-1TYPE\s0\fR, etc. See \&\*(L"Statement Handle Attributes\*(R" in \s-1DBI\s0 for a complete list. .PP Pay attention to attributes which are marked as read only, such as \&\fI\s-1NUM_OF_PARAMS\s0\fR. These attributes can only be set the first time a statement is executed. If a statement is prepared, then executed multiple times, warnings may be generated. .PP You can protect against these warnings, and prevent the recalculation of attributes which might be expensive to calculate (such as the \&\fI\s-1NAME\s0\fR and \fINAME_*\fR attributes): .PP .Vb 3 \& my $storedNumParams = $sth\->FETCH(\*(AqNUM_OF_PARAMS\*(Aq); \& if (!defined $storedNumParams or $storedNumFields < 0) { \& $sth\->STORE(\*(AqNUM_OF_PARAMS\*(Aq) = $numParams; \& \& # Set other useful attributes that only need to be set once \& # for a statement, like $sth\->{NAME} and $sth\->{TYPE} \& } .Ve .PP One particularly important attribute to set correctly (mentioned in \&\*(L"\s-1ATTRIBUTES COMMON TO ALL HANDLES\*(R"\s0 in \s-1DBI\s0 is \fIActive\fR. Many \fB\s-1DBI\s0\fR methods, including \f(CW\*(C`bind_columns()\*(C'\fR, depend on this attribute. .PP Besides that the \f(CW\*(C`STORE()\*(C'\fR and \f(CW\*(C`FETCH()\*(C'\fR methods are mainly the same as above for \fIdbh\fR's. .PP Other statement methods .IX Subsection "Other statement methods" .PP A trivial \f(CW\*(C`finish()\*(C'\fR method to discard stored data, reset any attributes (such as \fIActive\fR) and do \f(CW\*(C`$sth\->SUPER::finish()\*(C'\fR. .PP If you've defined a \f(CW\*(C`parse_trace_flag()\*(C'\fR method in \fB::db\fR you'll also want it in \fB::st\fR, so just alias it in: .PP .Vb 1 \& *parse_trace_flag = \e&DBD::foo:db::parse_trace_flag; .Ve .PP And perhaps some other methods that are not part of the \fB\s-1DBI\s0\fR specification, in particular to make metadata available. Remember that they must have names that begin with your drivers registered prefix so they can be installed using \f(CW\*(C`install_method()\*(C'\fR. .PP If \f(CW\*(C`DESTROY()\*(C'\fR is called on a statement handle that's still active (\f(CW\*(C`$sth\->{Active}\*(C'\fR is true) then it should effectively call \f(CW\*(C`finish()\*(C'\fR. .PP .Vb 4 \& sub DESTROY { \& my $sth = shift; \& $sth\->finish if $sth\->FETCH(\*(AqActive\*(Aq); \& } .Ve .SS "Tests" .IX Subsection "Tests" The test process should conform as closely as possibly to the Perl standard test harness. .PP In particular, most (all) of the tests should be run in the \fIt\fR sub-directory, and should simply produce an \f(CW\*(C`ok\*(C'\fR when run under \f(CW\*(C`make test\*(C'\fR. For details on how this is done, see the Camel book and the section in Chapter 7, \*(L"The Standard Perl Library\*(R" on Test::Harness. .PP The tests may need to adapt to the type of database which is being used for testing, and to the privileges of the user testing the driver. For example, the \fBDBD::Informix\fR test code has to adapt in a number of places to the type of database to which it is connected as different Informix databases have different capabilities: some of the tests are for databases without transaction logs; others are for databases with a transaction log; some versions of the server have support for blobs, or stored procedures, or user-defined data types, and others do not. .PP When a complete file of tests must be skipped, you can provide a reason in a pseudo-comment: .PP .Vb 5 \& if ($no_transactions_available) \& { \& print "1..0 # Skip: No transactions available\en"; \& exit 0; \& } .Ve .PP Consider downloading the \fBDBD::Informix\fR code and look at the code in \&\fIDBD/Informix/TestHarness.pm\fR which is used throughout the \&\fBDBD::Informix\fR tests in the \fIt\fR sub-directory. .SH "CREATING A C/XS DRIVER" .IX Header "CREATING A C/XS DRIVER" Please also see the section under \*(L"\s-1CREATING A PURE PERL DRIVER\*(R"\s0 regarding the creation of the \fIMakefile.PL\fR. .PP Creating a new C/XS driver from scratch will always be a daunting task. You can and should greatly simplify your task by taking a good reference driver implementation and modifying that to match the database product for which you are writing a driver. .PP The de facto reference driver has been the one for \fBDBD::Oracle\fR written by Tim Bunce, who is also the author of the \fB\s-1DBI\s0\fR package. The \fBDBD::Oracle\fR module is a good example of a driver implemented around a C\-level \s-1API.\s0 .PP Nowadays it it seems better to base on \fB\s-1DBD::ODBC\s0\fR, another driver maintained by Tim and Jeff Urlwin, because it offers a lot of metadata and seems to become the guideline for the future development. (Also as \&\fBDBD::Oracle\fR digs deeper into the Oracle 8 \s-1OCI\s0 interface it'll get even more hairy than it is now.) .PP The \fBDBD::Informix\fR driver is one driver implemented using embedded \s-1SQL\s0 instead of a function-based \s-1API.\s0 \&\fBDBD::Ingres\fR may also be worth a look. .SS "C/XS version of Driver.pm" .IX Subsection "C/XS version of Driver.pm" A lot of the code in the \fIDriver.pm\fR file is very similar to the code for pure Perl modules \&\- see above. However, there are also some subtle (and not so subtle) differences, including: .IP "\(bu" 8 The variables \fI\f(CI$DBD::Driver::\fI{dr|db|st}::imp_data_size\fR are not defined here, but in the \s-1XS\s0 code, because they declare the size of certain C structures. .IP "\(bu" 8 Some methods are typically moved to the \s-1XS\s0 code, in particular \&\f(CW\*(C`prepare()\*(C'\fR, \f(CW\*(C`execute()\*(C'\fR, \f(CW\*(C`disconnect()\*(C'\fR, \f(CW\*(C`disconnect_all()\*(C'\fR and the \&\f(CW\*(C`STORE()\*(C'\fR and \f(CW\*(C`FETCH()\*(C'\fR methods. .IP "\(bu" 8 Other methods are still part of \fIDriver.pm\fR, but have callbacks to the \s-1XS\s0 code. .IP "\(bu" 8 If the driver-specific parts of the \fIimp_drh_t\fR structure need to be formally initialized (which does not seem to be a common requirement), then you need to add a call to an appropriate \s-1XS\s0 function in the driver method of \f(CW\*(C`DBD::Driver::driver()\*(C'\fR, and you define the corresponding function in \fIDriver.xs\fR, and you define the C code in \fIdbdimp.c\fR and the prototype in \&\fIdbdimp.h\fR. .Sp For example, \fBDBD::Informix\fR has such a requirement, and adds the following call after the call to \f(CW\*(C`_new_drh()\*(C'\fR in \fIInformix.pm\fR: .Sp .Vb 1 \& DBD::Informix::dr::driver_init($drh); .Ve .Sp and the following code in \fIInformix.xs\fR: .Sp .Vb 6 \& # Initialize the DBD::Informix driver data structure \& void \& driver_init(drh) \& SV *drh \& CODE: \& ST(0) = dbd_ix_dr_driver_init(drh) ? &sv_yes : &sv_no; .Ve .Sp and the code in \fIdbdimp.h\fR declares: .Sp .Vb 1 \& extern int dbd_ix_dr_driver_init(SV *drh); .Ve .Sp and the code in \fIdbdimp.ec\fR (equivalent to \fIdbdimp.c\fR) defines: .Sp .Vb 11 \& /* Formally initialize the DBD::Informix driver structure */ \& int \& dbd_ix_dr_driver(SV *drh) \& { \& D_imp_drh(drh); \& imp_drh\->n_connections = 0; /* No active connections */ \& imp_drh\->current_connection = 0; /* No current connection */ \& imp_drh\->multipleconnections = (ESQLC_VERSION >= 600) ? True : False; \& dbd_ix_link_newhead(&imp_drh\->head); /* Empty linked list of connections */ \& return 1; \& } .Ve .Sp \&\fBDBD::Oracle\fR has a similar requirement but gets around it by checking whether the private data part of the driver handle is all zeroed out, rather than add extra functions. .PP Now let's take a closer look at an excerpt from \fIOracle.pm\fR (revised heavily to remove idiosyncrasies) as an example, ignoring things that were already discussed for pure Perl drivers. .PP \fIThe connect method\fR .IX Subsection "The connect method" .PP The connect method is the database handle constructor. You could write either of two versions of this method: either one which takes connection attributes (new code) and one which ignores them (old code only). .PP If you ignore the connection attributes, then you omit all mention of the \fI\f(CI$auth\fI\fR variable (which is a reference to a hash of attributes), and the \s-1XS\s0 system manages the differences for you. .PP .Vb 3 \& sub connect \& { \& my ($drh, $dbname, $user, $auth, $attr) = @_; \& \& # Some database specific verifications, default settings \& # and the like following here. This should only include \& # syntax checks or similar stuff where it\*(Aqs legal to \& # \*(Aqdie\*(Aq in case of errors. \& \& my $dbh = DBI::_new_dbh($drh, { \& \*(AqName\*(Aq => $dbname, \& }) \& or return undef; \& \& # Call the driver\-specific function _login in Driver.xs file which \& # calls the DBMS\-specific function(s) to connect to the database, \& # and populate internal handle data. \& DBD::Driver::db::_login($dbh, $dbname, $user, $auth, $attr) \& or return undef; \& \& $dbh; \& } .Ve .PP This is mostly the same as in the pure Perl case, the exception being the use of the private \f(CW\*(C`_login()\*(C'\fR callback, which is the function that will really connect to the database. It is implemented in \&\fIDriver.xst\fR (you should not implement it) and calls \&\f(CW\*(C`dbd_db_login6()\*(C'\fR or \f(CW\*(C`dbd_db_login6_sv\*(C'\fR from \fIdbdimp.c\fR. See below for details. .PP If your driver has driver-specific attributes which may be passed in the connect method and hence end up in \f(CW$attr\fR in \f(CW\*(C`dbd_db_login6\*(C'\fR then it is best to delete any you process so \s-1DBI\s0 does not send them again via \s-1STORE\s0 after connect. You can do this in C like this: .PP .Vb 2 \& DBD_ATTRIB_DELETE(attr, "my_attribute_name", \& strlen("my_attribute_name")); .Ve .PP However, prior to \s-1DBI\s0 subversion version 11605 (and fixed post 1.607) \&\s-1DBD_ATTRIB_DELETE\s0 segfaulted so if you cannot guarantee the \s-1DBI\s0 version will be post 1.607 you need to use: .PP .Vb 2 \& hv_delete((HV*)SvRV(attr), "my_attribute_name", \& strlen("my_attribute_name"), G_DISCARD); \& \& *FIX ME* Discuss removing attributes in Perl code. .Ve .PP \fIThe disconnect_all method\fR .IX Subsection "The disconnect_all method" .PP .Vb 1 \& *FIX ME* T.B.S .Ve .PP \fIThe data_sources method\fR .IX Subsection "The data_sources method" .PP If your \f(CW\*(C`data_sources()\*(C'\fR method can be implemented in pure Perl, then do so because it is easier than doing it in \s-1XS\s0 code (see the section above for pure Perl drivers). .PP If your \f(CW\*(C`data_sources()\*(C'\fR method must call onto compiled functions, then you will need to define \fIdbd_dr_data_sources\fR in your \fIdbdimp.h\fR file, which will trigger \fIDriver.xst\fR (in \fB\s-1DBI\s0\fR v1.33 or greater) to generate the \s-1XS\s0 code that calls your actual C function (see the discussion below for details) and you do not code anything in \fIDriver.pm\fR to handle it. .PP \fIThe prepare method\fR .IX Subsection "The prepare method" .PP The prepare method is the statement handle constructor, and most of it is not new. Like the \f(CW\*(C`connect()\*(C'\fR method, it now has a C callback: .PP .Vb 2 \& package DBD::Driver::db; # ====== DATABASE ====== \& use strict; \& \& sub prepare \& { \& my ($dbh, $statement, $attribs) = @_; \& \& # create a \*(Aqblank\*(Aq sth \& my $sth = DBI::_new_sth($dbh, { \& \*(AqStatement\*(Aq => $statement, \& }) \& or return undef; \& \& # Call the driver\-specific function _prepare in Driver.xs file \& # which calls the DBMS\-specific function(s) to prepare a statement \& # and populate internal handle data. \& DBD::Driver::st::_prepare($sth, $statement, $attribs) \& or return undef; \& $sth; \& } .Ve .PP \fIThe execute method\fR .IX Subsection "The execute method" .PP .Vb 1 \& *FIX ME* T.B.S .Ve .PP \fIThe fetchrow_arrayref method\fR .IX Subsection "The fetchrow_arrayref method" .PP .Vb 1 \& *FIX ME* T.B.S .Ve .PP \fIOther methods?\fR .IX Subsection "Other methods?" .PP .Vb 1 \& *FIX ME* T.B.S .Ve .SS "Driver.xs" .IX Subsection "Driver.xs" \&\fIDriver.xs\fR should look something like this: .PP .Vb 1 \& #include "Driver.h" \& \& DBISTATE_DECLARE; \& \& INCLUDE: Driver.xsi \& \& MODULE = DBD::Driver PACKAGE = DBD::Driver::dr \& \& /* Non\-standard drh XS methods following here, if any. */ \& /* If none (the usual case), omit the MODULE line above too. */ \& \& MODULE = DBD::Driver PACKAGE = DBD::Driver::db \& \& /* Non\-standard dbh XS methods following here, if any. */ \& /* Currently this includes things like _list_tables from */ \& /* DBD::mSQL and DBD::mysql. */ \& \& MODULE = DBD::Driver PACKAGE = DBD::Driver::st \& \& /* Non\-standard sth XS methods following here, if any. */ \& /* In particular this includes things like _list_fields from */ \& /* DBD::mSQL and DBD::mysql for accessing metadata. */ .Ve .PP Note especially the include of \fIDriver.xsi\fR here: \fB\s-1DBI\s0\fR inserts stub functions for almost all private methods here which will typically do much work for you. .PP Wherever you really have to implement something, it will call a private function in \fIdbdimp.c\fR, and this is what you have to implement. .PP You need to set up an extra routine if your driver needs to export constants of its own, analogous to the \s-1SQL\s0 types available when you say: .PP .Vb 1 \& use DBI qw(:sql_types); \& \& *FIX ME* T.B.S .Ve .SS "Driver.h" .IX Subsection "Driver.h" \&\fIDriver.h\fR is very simple and the operational contents should look like this: .PP .Vb 2 \& #ifndef DRIVER_H_INCLUDED \& #define DRIVER_H_INCLUDED \& \& #define NEED_DBIXS_VERSION 93 /* 93 for DBI versions 1.00 to 1.51+ */ \& #define PERL_NO_GET_CONTEXT /* if used require DBI 1.51+ */ \& \& #include /* installed by the DBI module */ \& \& #include "dbdimp.h" \& \& #include "dbivport.h" /* see below */ \& \& #include /* installed by the DBI module */ \& \& #endif /* DRIVER_H_INCLUDED */ .Ve .PP The \fI\s-1DBIXS\s0.h\fR header defines most of the interesting information that the writer of a driver needs. .PP The file \fIdbd_xsh.h\fR header provides prototype declarations for the C functions that you might decide to implement. Note that you should normally only define one of \f(CW\*(C`dbd_db_login()\*(C'\fR, \f(CW\*(C`dbd_db_login6()\*(C'\fR or \&\f(CW\*(C`dbd_db_login6_sv\*(C'\fR unless you are intent on supporting really old versions of \fB\s-1DBI\s0\fR (prior to \fB\s-1DBI\s0\fR 1.06) as well as modern versions. The only standard, \fB\s-1DBI\s0\fR\-mandated functions that you need write are those specified in the \fIdbd_xsh.h\fR header. You might also add extra driver-specific functions in \fIDriver.xs\fR. .PP The \fIdbivport.h\fR file should be \fIcopied\fR from the latest \fB\s-1DBI\s0\fR release into your distribution each time you modify your driver. Its job is to allow you to enhance your code to work with the latest \fB\s-1DBI\s0\fR \s-1API\s0 while still allowing your driver to be compiled and used with older versions of the \fB\s-1DBI\s0\fR (for example, when the \f(CW\*(C`DBIh_SET_ERR_CHAR()\*(C'\fR macro was added to \fB\s-1DBI\s0\fR 1.41, an emulation of it was added to \fIdbivport.h\fR). This makes users happy and your life easier. Always read the notes in \fIdbivport.h\fR to check for any limitations in the emulation that you should be aware of. .PP With \fB\s-1DBI\s0\fR v1.51 or better I recommend that the driver defines \&\fI\s-1PERL_NO_GET_CONTEXT\s0\fR before \fI\s-1DBIXS\s0.h\fR is included. This can significantly improve efficiency when running under a thread enabled perl. (Remember that the standard perl in most Linux distributions is built with threads enabled. So is ActiveState perl for Windows, and perl built for Apache mod_perl2.) If you do this there are some things to keep in mind: .IP "\(bu" 4 If \fI\s-1PERL_NO_GET_CONTEXT\s0\fR is defined, then every function that calls the Perl \&\s-1API\s0 will need to start out with a \f(CW\*(C`dTHX;\*(C'\fR declaration. .IP "\(bu" 4 You'll know which functions need this, because the C compiler will complain that the undeclared identifier \f(CW\*(C`my_perl\*(C'\fR is used if \fIand only if\fR the perl you are using to develop and test your driver has threads enabled. .IP "\(bu" 4 If you don't remember to test with a thread-enabled perl before making a release it's likely that you'll get failure reports from users who are. .IP "\(bu" 4 For driver private functions it is possible to gain even more efficiency by replacing \f(CW\*(C`dTHX;\*(C'\fR with \f(CW\*(C`pTHX_\*(C'\fR prepended to the parameter list and then \f(CW\*(C`aTHX_\*(C'\fR prepended to the argument list where the function is called. .PP See \*(L"How multiple interpreters and concurrency are supported\*(R" in perlguts for additional information about \fI\s-1PERL_NO_GET_CONTEXT\s0\fR. .SS "Implementation header dbdimp.h" .IX Subsection "Implementation header dbdimp.h" This header file has two jobs: .PP First it defines data structures for your private part of the handles. Note that the \s-1DBI\s0 provides many common fields for you. For example the statement handle (imp_sth) already has a row_count field with an \s-1IV\s0 type that accessed via the DBIc_ROW_COUNT(imp_sth) macro. Using this is strongly recommended as it's built in to some \s-1DBI\s0 internals so the \s-1DBI\s0 can 'just work' in more cases and you'll have less driver-specific code to write. Study \s-1DBIXS\s0.h to see what's included with each type of handle. .PP Second it defines macros that rename the generic names like \&\f(CW\*(C`dbd_db_login()\*(C'\fR to database specific names like \f(CW\*(C`ora_db_login()\*(C'\fR. This avoids name clashes and enables use of different drivers when you work with a statically linked perl. .PP It also will have the important task of disabling \s-1XS\s0 methods that you don't want to implement. .PP Finally, the macros will also be used to select alternate implementations of some functions. For example, the \f(CW\*(C`dbd_db_login()\*(C'\fR function is not passed the attribute hash. .PP Since \fB\s-1DBI\s0\fR v1.06, if a \f(CW\*(C`dbd_db_login6()\*(C'\fR macro is defined (for a function with 6 arguments), it will be used instead with the attribute hash passed as the sixth argument. .PP Since \fB\s-1DBI\s0\fR post v1.607, if a \f(CW\*(C`dbd_db_login6_sv()\*(C'\fR macro is defined (for a function like dbd_db_login6 but with scalar pointers for the dbname, username and password), it will be used instead. This will allow your login6 function to see if there are any Unicode characters in the dbname. .PP Similarly defining dbd_db_do4_iv is preferred over dbd_db_do4, dbd_st_rows_iv over dbd_st_rows, and dbd_st_execute_iv over dbd_st_execute. The *_iv forms are declared to return the \s-1IV\s0 type instead of an int. .PP People used to just pick Oracle's \fIdbdimp.c\fR and use the same names, structures and types. I strongly recommend against that. At first glance this saves time, but your implementation will be less readable. It was just hell when I had to separate \fB\s-1DBI\s0\fR specific parts, Oracle specific parts, mSQL specific parts and mysql specific parts in \fBDBD::mysql\fR's \&\fIdbdimp.h\fR and \fIdbdimp.c\fR. (\fBDBD::mysql\fR was a port of \fBDBD::mSQL\fR which was based on \fBDBD::Oracle\fR.) [Seconded, based on the experience taking \fBDBD::Informix\fR apart, even though the version inherited in 1996 was only based on \fBDBD::Oracle\fR.] .PP This part of the driver is \fIyour exclusive part\fR. Rewrite it from scratch, so it will be clean and short: in other words, a better piece of code. (Of course keep an eye on other people's work.) .PP .Vb 4 \& struct imp_drh_st { \& dbih_drc_t com; /* MUST be first element in structure */ \& /* Insert your driver handle attributes here */ \& }; \& \& struct imp_dbh_st { \& dbih_dbc_t com; /* MUST be first element in structure */ \& /* Insert your database handle attributes here */ \& }; \& \& struct imp_sth_st { \& dbih_stc_t com; /* MUST be first element in structure */ \& /* Insert your statement handle attributes here */ \& }; \& \& /* Rename functions for avoiding name clashes; prototypes are */ \& /* in dbd_xsh.h */ \& #define dbd_init drv_dr_init \& #define dbd_db_login6_sv drv_db_login_sv \& #define dbd_db_do drv_db_do \& ... many more here ... .Ve .PP These structures implement your private part of the handles. .PP You \fIhave\fR to use the name \f(CW\*(C`imp_dbh_{dr|db|st}\*(C'\fR and the first field \&\fImust\fR be of type \fIdbih_drc_t|_dbc_t|_stc_t\fR and \fImust\fR be called \&\f(CW\*(C`com\*(C'\fR. .PP You should never access these fields directly, except by using the \&\fI\f(BIDBIc_xxx()\fI\fR macros below. .SS "Implementation source dbdimp.c" .IX Subsection "Implementation source dbdimp.c" Conventionally, \fIdbdimp.c\fR is the main implementation file (but \&\fBDBD::Informix\fR calls the file \fIdbdimp.ec\fR). This section includes a short note on each function that is used in the \fIDriver.xsi\fR template and thus \fIhas\fR to be implemented. .PP Of course, you will probably also need to implement other support functions, which should usually be file static if they are placed in \&\fIdbdimp.c\fR. If they are placed in other files, you need to list those files in \fIMakefile.PL\fR (and \fI\s-1MANIFEST\s0\fR) to handle them correctly. .PP It is wise to adhere to a namespace convention for your functions to avoid conflicts. For example, for a driver with prefix \fIdrv_\fR, you might call externally visible functions \fIdbd_drv_xxxx\fR. You should also avoid non-constant global variables as much as possible to improve the support for threading. .PP Since Perl requires support for function prototypes (\s-1ANSI\s0 or \s-1ISO\s0 or Standard C), you should write your code using function prototypes too. .PP It is possible to use either the unmapped names such as \f(CW\*(C`dbd_init()\*(C'\fR or the mapped names such as \f(CW\*(C`dbd_ix_dr_init()\*(C'\fR in the \fIdbdimp.c\fR file. \&\fBDBD::Informix\fR uses the mapped names which makes it easier to identify where to look for linkage problems at runtime (which will report errors using the mapped names). .PP Most other drivers, and in particular \fBDBD::Oracle\fR, use the unmapped names in the source code which makes it a little easier to compare code between drivers and eases discussions on the \fIdbi-dev\fR mailing list. The majority of the code fragments here will use the unmapped names. .PP Ultimately, you should provide implementations for most of the functions listed in the \fIdbd_xsh.h\fR header. The exceptions are optional functions (such as \f(CW\*(C`dbd_st_rows()\*(C'\fR) and those functions with alternative signatures, such as \f(CW\*(C`dbd_db_login6_sv\*(C'\fR, \&\f(CW\*(C`dbd_db_login6()\*(C'\fR and \fI\f(BIdbd_db_login()\fI\fR. Then you should only implement one of the alternatives, and generally the newer one of the alternatives. .PP \fIThe dbd_init method\fR .IX Subsection "The dbd_init method" .PP .Vb 1 \& #include "Driver.h" \& \& DBISTATE_DECLARE; \& \& void dbd_init(dbistate_t* dbistate) \& { \& DBISTATE_INIT; /* Initialize the DBI macros */ \& } .Ve .PP The \f(CW\*(C`dbd_init()\*(C'\fR function will be called when your driver is first loaded; the bootstrap command in \f(CW\*(C`DBD::Driver::dr::driver()\*(C'\fR triggers this, and the call is generated in the \fI\s-1BOOT\s0\fR section of \fIDriver.xst\fR. These statements are needed to allow your driver to use the \fB\s-1DBI\s0\fR macros. They will include your private header file \fIdbdimp.h\fR in turn. Note that \fI\s-1DBISTATE_INIT\s0\fR requires the name of the argument to \f(CW\*(C`dbd_init()\*(C'\fR to be called \f(CW\*(C`dbistate()\*(C'\fR. .PP \fIThe dbd_drv_error method\fR .IX Subsection "The dbd_drv_error method" .PP You need a function to record errors so \fB\s-1DBI\s0\fR can access them properly. You can call it whatever you like, but we'll call it \f(CW\*(C`dbd_drv_error()\*(C'\fR here. .PP The argument list depends on your database software; different systems provide different ways to get at error information. .PP .Vb 2 \& static void dbd_drv_error(SV *h, int rc, const char *what) \& { .Ve .PP Note that \fIh\fR is a generic handle, may it be a driver handle, a database or a statement handle. .PP .Vb 1 \& D_imp_xxh(h); .Ve .PP This macro will declare and initialize a variable \fIimp_xxh\fR with a pointer to your private handle pointer. You may cast this to to \fIimp_drh_t\fR, \fIimp_dbh_t\fR or \fIimp_sth_t\fR. .PP To record the error correctly, equivalent to the \f(CW\*(C`set_err()\*(C'\fR method, use one of the \f(CW\*(C`DBIh_SET_ERR_CHAR(...)\*(C'\fR or \f(CW\*(C`DBIh_SET_ERR_SV(...)\*(C'\fR macros, which were added in \fB\s-1DBI\s0\fR 1.41: .PP .Vb 2 \& DBIh_SET_ERR_SV(h, imp_xxh, err, errstr, state, method); \& DBIh_SET_ERR_CHAR(h, imp_xxh, err_c, err_i, errstr, state, method); .Ve .PP For \f(CW\*(C`DBIh_SET_ERR_SV\*(C'\fR the \fIerr\fR, \fIerrstr\fR, \fIstate\fR, and \fImethod\fR parameters are \f(CW\*(C`SV*\*(C'\fR (use &sv_undef instead of \s-1NULL\s0). .PP For \f(CW\*(C`DBIh_SET_ERR_CHAR\*(C'\fR the \fIerr_c\fR, \fIerrstr\fR, \fIstate\fR, \fImethod\fR parameters are \f(CW\*(C`char*\*(C'\fR. .PP The \fIerr_i\fR parameter is an \f(CW\*(C`IV\*(C'\fR that's used instead of \fIerr_c\fR if \&\fIerr_c\fR is \f(CW\*(C`Null\*(C'\fR. .PP The \fImethod\fR parameter can be ignored. .PP The \f(CW\*(C`DBIh_SET_ERR_CHAR\*(C'\fR macro is usually the simplest to use when you just have an integer error code and an error message string: .PP .Vb 1 \& DBIh_SET_ERR_CHAR(h, imp_xxh, Nullch, rc, what, Nullch, Nullch); .Ve .PP As you can see, any parameters that aren't relevant to you can be \f(CW\*(C`Null\*(C'\fR. .PP To make drivers compatible with \fB\s-1DBI\s0\fR < 1.41 you should be using \fIdbivport.h\fR as described in \*(L"Driver.h\*(R" above. .PP The (obsolete) macros such as \f(CW\*(C`DBIh_EVENT2\*(C'\fR should be removed from drivers. .PP The names \f(CW\*(C`dbis\*(C'\fR and \f(CW\*(C`DBIS\*(C'\fR, which were used in previous versions of this document, should be replaced with the \f(CW\*(C`DBIc_DBISTATE(imp_xxh)\*(C'\fR macro. .PP The name \f(CW\*(C`DBILOGFP\*(C'\fR, which was also used in previous versions of this document, should be replaced by \f(CW\*(C`DBIc_LOGPIO(imp_xxh)\*(C'\fR. .PP Your code should not call the C \f(CW\*(C`\*(C'\fR I/O functions; you should use \f(CW\*(C`PerlIO_printf()\*(C'\fR as shown: .PP .Vb 3 \& if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) \& PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar %s: %s\en", \& foo, neatsvpv(errstr,0)); .Ve .PP That's the first time we see how tracing works within a \fB\s-1DBI\s0\fR driver. Make use of this as often as you can, but don't output anything at a trace level less than 3. Levels 1 and 2 are reserved for the \fB\s-1DBI\s0\fR. .PP You can define up to 8 private trace flags using the top 8 bits of \f(CW\*(C`DBIc_TRACE_FLAGS(imp)\*(C'\fR, that is: \f(CW0xFF000000\fR. See the \&\f(CW\*(C`parse_trace_flag()\*(C'\fR method elsewhere in this document. .PP \fIThe dbd_dr_data_sources method\fR .IX Subsection "The dbd_dr_data_sources method" .PP This method is optional; the support for it was added in \fB\s-1DBI\s0\fR v1.33. .PP As noted in the discussion of \fIDriver.pm\fR, if the data sources can be determined by pure Perl code, do it that way. If, as in \&\fBDBD::Informix\fR, the information is obtained by a C function call, then you need to define a function that matches the prototype: .PP .Vb 1 \& extern AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attrs); .Ve .PP An outline implementation for \fBDBD::Informix\fR follows, assuming that the \&\f(CW\*(C`sqgetdbs()\*(C'\fR function call shown will return up to 100 databases names, with the pointers to each name in the array dbsname and the name strings themselves being stores in dbsarea. .PP .Vb 7 \& AV *dbd_dr_data_sources(SV *drh, imp_drh_t *imp_drh, SV *attr) \& { \& int ndbs; \& int i; \& char *dbsname[100]; \& char dbsarea[10000]; \& AV *av = Nullav; \& \& if (sqgetdbs(&ndbs, dbsname, 100, dbsarea, sizeof(dbsarea)) == 0) \& { \& av = NewAV(); \& av_extend(av, (I32)ndbs); \& sv_2mortal((SV *)av); \& for (i = 0; i < ndbs; i++) \& av_store(av, i, newSVpvf("dbi:Informix:%s", dbsname[i])); \& } \& return(av); \& } .Ve .PP The actual \fBDBD::Informix\fR implementation has a number of extra lines of code, logs function entry and exit, reports the error from \f(CW\*(C`sqgetdbs()\*(C'\fR, and uses \f(CW\*(C`#define\*(C'\fR'd constants for the array sizes. .PP \fIThe dbd_db_login6 method\fR .IX Subsection "The dbd_db_login6 method" .PP .Vb 2 \& int dbd_db_login6_sv(SV* dbh, imp_dbh_t* imp_dbh, SV* dbname, \& SV* user, SV* auth, SV *attr); \& \& or \& \& int dbd_db_login6(SV* dbh, imp_dbh_t* imp_dbh, char* dbname, \& char* user, char* auth, SV *attr); .Ve .PP This function will really connect to the database. The argument \fIdbh\fR is the database handle. \fIimp_dbh\fR is the pointer to the handles private data, as is \fIimp_xxx\fR in \f(CW\*(C`dbd_drv_error()\*(C'\fR above. The arguments \&\fIdbname\fR, \fIuser\fR, \fIauth\fR and \fIattr\fR correspond to the arguments of the driver handle's \f(CW\*(C`connect()\*(C'\fR method. .PP You will quite often use database specific attributes here, that are specified in the \s-1DSN. I\s0 recommend you parse the \s-1DSN\s0 (using Perl) within the \f(CW\*(C`connect()\*(C'\fR method and pass the segments of the \s-1DSN\s0 via the attributes parameter through \f(CW\*(C`_login()\*(C'\fR to \f(CW\*(C`dbd_db_login6()\*(C'\fR. .PP Here's how you fetch them; as an example we use \fIhostname\fR attribute, which can be up to 12 characters long excluding null terminator: .PP .Vb 3 \& SV** svp; \& STRLEN len; \& char* hostname; \& \& if ( (svp = DBD_ATTRIB_GET_SVP(attr, "drv_hostname", 12)) && SvTRUE(*svp)) { \& hostname = SvPV(*svp, len); \& DBD_ATTRIB_DELETE(attr, "drv_hostname", 12); /* avoid later STORE */ \& } else { \& hostname = "localhost"; \& } .Ve .PP If you handle any driver specific attributes in the dbd_db_login6 method you probably want to delete them from \f(CW\*(C`attr\*(C'\fR (as above with \&\s-1DBD_ATTRIB_DELETE\s0). If you don't delete your handled attributes \s-1DBI\s0 will call \f(CW\*(C`STORE\*(C'\fR for each attribute after the connect/login and this is at best redundant for attributes you have already processed. .PP \&\fBNote: Until revision 11605 (post \s-1DBI 1.607\s0), there was a problem with \&\s-1DBD_ATTRIBUTE_DELETE\s0 so unless you require a \s-1DBI\s0 version after 1.607 you need to replace each \s-1DBD_ATTRIBUTE_DELETE\s0 call with:\fR .PP .Vb 1 \& hv_delete((HV*)SvRV(attr), key, key_len, G_DISCARD) .Ve .PP Note that you can also obtain standard attributes such as \fIAutoCommit\fR and \&\fIChopBlanks\fR from the attributes parameter, using \f(CW\*(C`DBD_ATTRIB_GET_IV\*(C'\fR for integer attributes. .PP If, for example, your database does not support transactions but \&\fIAutoCommit\fR is set off (requesting transaction support), then you can emulate a 'failure to connect'. .PP Now you should really connect to the database. In general, if the connection fails, it is best to ensure that all allocated resources are released so that the handle does not need to be destroyed separately. If you are successful (and possibly even if you fail but you have allocated some resources), you should use the following macros: .PP .Vb 1 \& DBIc_IMPSET_on(imp_dbh); .Ve .PP This indicates that the driver (implementor) has allocated resources in the \fIimp_dbh\fR structure and that the implementors private \f(CW\*(C`dbd_db_destroy()\*(C'\fR function should be called when the handle is destroyed. .PP .Vb 1 \& DBIc_ACTIVE_on(imp_dbh); .Ve .PP This indicates that the handle has an active connection to the server and that the \f(CW\*(C`dbd_db_disconnect()\*(C'\fR function should be called before the handle is destroyed. .PP Note that if you do need to fail, you should report errors via the \fIdrh\fR or \fIimp_drh\fR rather than via \fIdbh\fR or \fIimp_dbh\fR because \fIimp_dbh\fR will be destroyed by the failure, so errors recorded in that handle will not be visible to \fB\s-1DBI\s0\fR, and hence not the user either. .PP Note too, that the function is passed \fIdbh\fR and \fIimp_dbh\fR, and there is a macro \f(CW\*(C`D_imp_drh_from_dbh\*(C'\fR which can recover the \fIimp_drh\fR from the \fIimp_dbh\fR. However, there is no \fB\s-1DBI\s0\fR macro to provide you with the \&\fIdrh\fR given either the \fIimp_dbh\fR or the \fIdbh\fR or the \fIimp_drh\fR (and there's no way to recover the \fIdbh\fR given just the \fIimp_dbh\fR). .PP This suggests that, despite the above notes about \f(CW\*(C`dbd_drv_error()\*(C'\fR taking an \f(CW\*(C`SV *\*(C'\fR, it may be better to have two error routines, one taking \fIimp_dbh\fR and one taking \fIimp_drh\fR instead. With care, you can factor most of the formatting code out so that these are small routines calling a common error formatter. See the code in \fBDBD::Informix\fR 1.05.00 for more information. .PP The \f(CW\*(C`dbd_db_login6()\*(C'\fR function should return \fI\s-1TRUE\s0\fR for success, \&\fI\s-1FALSE\s0\fR otherwise. .PP Drivers implemented long ago may define the five-argument function \&\f(CW\*(C`dbd_db_login()\*(C'\fR instead of \f(CW\*(C`dbd_db_login6()\*(C'\fR. The missing argument is the attributes. There are ways to work around the missing attributes, but they are ungainly; it is much better to use the 6\-argument form. Even later drivers will use \f(CW\*(C`dbd_db_login6_sv()\*(C'\fR which provides the dbname, username and password as SVs. .PP \fIThe dbd_db_commit and dbd_db_rollback methods\fR .IX Subsection "The dbd_db_commit and dbd_db_rollback methods" .PP .Vb 2 \& int dbd_db_commit(SV *dbh, imp_dbh_t *imp_dbh); \& int dbd_db_rollback(SV* dbh, imp_dbh_t* imp_dbh); .Ve .PP These are used for commit and rollback. They should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR for error. .PP The arguments \fIdbh\fR and \fIimp_dbh\fR are the same as for \f(CW\*(C`dbd_db_login6()\*(C'\fR above; I will omit describing them in what follows, as they appear always. .PP These functions should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise. .PP \fIThe dbd_db_disconnect method\fR .IX Subsection "The dbd_db_disconnect method" .PP This is your private part of the \f(CW\*(C`disconnect()\*(C'\fR method. Any \fIdbh\fR with the \fI\s-1ACTIVE\s0\fR flag on must be disconnected. (Note that you have to set it in \f(CW\*(C`dbd_db_connect()\*(C'\fR above.) .PP .Vb 1 \& int dbd_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh); .Ve .PP The database handle will return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise. In any case it should do a: .PP .Vb 1 \& DBIc_ACTIVE_off(imp_dbh); .Ve .PP before returning so \fB\s-1DBI\s0\fR knows that \f(CW\*(C`dbd_db_disconnect()\*(C'\fR was executed. .PP Note that there's nothing to stop a \fIdbh\fR being \fIdisconnected\fR while it still have active children. If your database \s-1API\s0 reacts badly to trying to use an \fIsth\fR in this situation then you'll need to add code like this to all \fIsth\fR methods: .PP .Vb 2 \& if (!DBIc_ACTIVE(DBIc_PARENT_COM(imp_sth))) \& return 0; .Ve .PP Alternatively, you can add code to your driver to keep explicit track of the statement handles that exist for each database handle and arrange to destroy those handles before disconnecting from the database. There is code to do this in \fBDBD::Informix\fR. Similar comments apply to the driver handle keeping track of all the database handles. .PP Note that the code which destroys the subordinate handles should only release the associated database resources and mark the handles inactive; it does not attempt to free the actual handle structures. .PP This function should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise, but it is not clear what anything can do about a failure. .PP \fIThe dbd_db_discon_all method\fR .IX Subsection "The dbd_db_discon_all method" .PP .Vb 1 \& int dbd_discon_all (SV *drh, imp_drh_t *imp_drh); .Ve .PP This function may be called at shutdown time. It should make best-efforts to disconnect all database handles \- if possible. Some databases don't support that, in which case you can do nothing but return 'success'. .PP This function should return \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise, but it is not clear what anything can do about a failure. .PP \fIThe dbd_db_destroy method\fR .IX Subsection "The dbd_db_destroy method" .PP This is your private part of the database handle destructor. Any \fIdbh\fR with the \fI\s-1IMPSET\s0\fR flag on must be destroyed, so that you can safely free resources. (Note that you have to set it in \f(CW\*(C`dbd_db_connect()\*(C'\fR above.) .PP .Vb 4 \& void dbd_db_destroy(SV* dbh, imp_dbh_t* imp_dbh) \& { \& DBIc_IMPSET_off(imp_dbh); \& } .Ve .PP The \fB\s-1DBI\s0\fR \fIDriver.xst\fR code will have called \f(CW\*(C`dbd_db_disconnect()\*(C'\fR for you, if the handle is still 'active', before calling \f(CW\*(C`dbd_db_destroy()\*(C'\fR. .PP Before returning the function must switch \fI\s-1IMPSET\s0\fR to off, so \fB\s-1DBI\s0\fR knows that the destructor was called. .PP A \fB\s-1DBI\s0\fR handle doesn't keep references to its children. But children do keep references to their parents. So a database handle won't be \&\f(CW\*(C`DESTROY\*(C'\fR'd until all its children have been \f(CW\*(C`DESTROY\*(C'\fR'd. .PP \fIThe dbd_db_STORE_attrib method\fR .IX Subsection "The dbd_db_STORE_attrib method" .PP This function handles .PP .Vb 1 \& $dbh\->{$key} = $value; .Ve .PP Its prototype is: .PP .Vb 2 \& int dbd_db_STORE_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv, \& SV* valuesv); .Ve .PP You do not handle all attributes; on the contrary, you should not handle \&\fB\s-1DBI\s0\fR attributes here: leave this to \fB\s-1DBI\s0\fR. (There are two exceptions, \&\fIAutoCommit\fR and \fIChopBlanks\fR, which you should care about.) .PP The return value is \fI\s-1TRUE\s0\fR if you have handled the attribute or \fI\s-1FALSE\s0\fR otherwise. If you are handling an attribute and something fails, you should call \f(CW\*(C`dbd_drv_error()\*(C'\fR, so \fB\s-1DBI\s0\fR can raise exceptions, if desired. If \f(CW\*(C`dbd_drv_error()\*(C'\fR returns, however, you have a problem: the user will never know about the error, because he typically will not check \&\f(CW\*(C`$dbh\->errstr()\*(C'\fR. .PP I cannot recommend a general way of going on, if \f(CW\*(C`dbd_drv_error()\*(C'\fR returns, but there are examples where even the \fB\s-1DBI\s0\fR specification expects that you \f(CW\*(C`croak()\*(C'\fR. (See the \fIAutoCommit\fR method in \s-1DBI\s0.) .PP If you have to store attributes, you should either use your private data structure \fIimp_xxx\fR, the handle hash (via \f(CW\*(C`(HV*)SvRV(dbh)\*(C'\fR), or use the private \fIimp_data\fR. .PP The first is best for internal C values like integers or pointers and where speed is important within the driver. The handle hash is best for values the user may want to get/set via driver-specific attributes. The private \fIimp_data\fR is an additional \f(CW\*(C`SV\*(C'\fR attached to the handle. You could think of it as an unnamed handle attribute. It's not normally used. .PP \fIThe dbd_db_FETCH_attrib method\fR .IX Subsection "The dbd_db_FETCH_attrib method" .PP This is the counterpart of \f(CW\*(C`dbd_db_STORE_attrib()\*(C'\fR, needed for: .PP .Vb 1 \& $value = $dbh\->{$key}; .Ve .PP Its prototype is: .PP .Vb 1 \& SV* dbd_db_FETCH_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv); .Ve .PP Unlike all previous methods this returns an \f(CW\*(C`SV\*(C'\fR with the value. Note that you should normally execute \f(CW\*(C`sv_2mortal()\*(C'\fR, if you return a nonconstant value. (Constant values are \f(CW&sv_undef\fR, \f(CW&sv_no\fR and \f(CW&sv_yes\fR.) .PP Note, that \fB\s-1DBI\s0\fR implements a caching algorithm for attribute values. If you think, that an attribute may be fetched, you store it in the \&\fIdbh\fR itself: .PP .Vb 2 \& if (cacheit) /* cache value for later DBI \*(Aqquick\*(Aq fetch? */ \& hv_store((HV*)SvRV(dbh), key, kl, cachesv, 0); .Ve .PP \fIThe dbd_st_prepare method\fR .IX Subsection "The dbd_st_prepare method" .PP This is the private part of the \f(CW\*(C`prepare()\*(C'\fR method. Note that you \&\fBmust not\fR really execute the statement here. You may, however, preparse and validate the statement, or do similar things. .PP .Vb 2 \& int dbd_st_prepare(SV* sth, imp_sth_t* imp_sth, char* statement, \& SV* attribs); .Ve .PP A typical, simple, possibility is to do nothing and rely on the perl \&\f(CW\*(C`prepare()\*(C'\fR code that set the \fIStatement\fR attribute on the handle. This attribute can then be used by \f(CW\*(C`dbd_st_execute()\*(C'\fR. .PP If the driver supports placeholders then the \fI\s-1NUM_OF_PARAMS\s0\fR attribute must be set correctly by \f(CW\*(C`dbd_st_prepare()\*(C'\fR: .PP .Vb 1 \& DBIc_NUM_PARAMS(imp_sth) = ... .Ve .PP If you can, you should also setup attributes like \fI\s-1NUM_OF_FIELDS\s0\fR, \fI\s-1NAME\s0\fR, etc. here, but \fB\s-1DBI\s0\fR doesn't require that \- they can be deferred until \&\fBexecute()\fR is called. However, if you do, document it. .PP In any case you should set the \fI\s-1IMPSET\s0\fR flag, as you did in \&\f(CW\*(C`dbd_db_connect()\*(C'\fR above: .PP .Vb 1 \& DBIc_IMPSET_on(imp_sth); .Ve .PP \fIThe dbd_st_execute method\fR .IX Subsection "The dbd_st_execute method" .PP This is where a statement will really be executed. .PP .Vb 1 \& int dbd_st_execute(SV* sth, imp_sth_t* imp_sth); .Ve .PP \&\f(CW\*(C`dbd_st_execute\*(C'\fR should return \-2 for any error, \-1 if the number of rows affected is unknown else it should be the number of affected (updated, inserted) rows. .PP Note that you must be aware a statement may be executed repeatedly. Also, you should not expect that \f(CW\*(C`finish()\*(C'\fR will be called between two executions, so you might need code, like the following, near the start of the function: .PP .Vb 2 \& if (DBIc_ACTIVE(imp_sth)) \& dbd_st_finish(h, imp_sth); .Ve .PP If your driver supports the binding of parameters (it should!), but the database doesn't, you must do it here. This can be done as follows: .PP .Vb 4 \& SV *svp; \& char* statement = DBD_ATTRIB_GET_PV(h, "Statement", 9, svp, ""); \& int numParam = DBIc_NUM_PARAMS(imp_sth); \& int i; \& \& for (i = 0; i < numParam; i++) \& { \& char* value = dbd_db_get_param(sth, imp_sth, i); \& /* It is your drivers task to implement dbd_db_get_param, */ \& /* it must be setup as a counterpart of dbd_bind_ph. */ \& /* Look for \*(Aq?\*(Aq and replace it with \*(Aqvalue\*(Aq. Difficult */ \& /* task, note that you may have question marks inside */ \& /* quotes and comments the like ... :\-( */ \& /* See DBD::mysql for an example. (Don\*(Aqt look too deep into */ \& /* the example, you will notice where I was lazy ...) */ \& } .Ve .PP The next thing is to really execute the statement. .PP Note that you must set the attributes \fI\s-1NUM_OF_FIELDS\s0\fR, \fI\s-1NAME\s0\fR, etc when the statement is successfully executed if the driver has not already done so: they may be used even before a potential \f(CW\*(C`fetchrow()\*(C'\fR. In particular you have to tell \fB\s-1DBI\s0\fR the number of fields that the statement has, because it will be used by \fB\s-1DBI\s0\fR internally. Thus the function will typically ends with: .PP .Vb 4 \& if (isSelectStatement) { \& DBIc_NUM_FIELDS(imp_sth) = numFields; \& DBIc_ACTIVE_on(imp_sth); \& } .Ve .PP It is important that the \fI\s-1ACTIVE\s0\fR flag only be set for \f(CW\*(C`SELECT\*(C'\fR statements (or any other statements that can return many values from the database using a cursor-like mechanism). See \&\f(CW\*(C`dbd_db_connect()\*(C'\fR above for more explanations. .PP There plans for a preparse function to be provided by \fB\s-1DBI\s0\fR, but this has not reached fruition yet. Meantime, if you want to know how ugly it can get, try looking at the \&\f(CW\*(C`dbd_ix_preparse()\*(C'\fR in \fBDBD::Informix\fR \fIdbdimp.ec\fR and the related functions in \fIiustoken.c\fR and \fIsqltoken.c\fR. .PP \fIThe dbd_st_fetch method\fR .IX Subsection "The dbd_st_fetch method" .PP This function fetches a row of data. The row is stored in in an array, of \f(CW\*(C`SV\*(C'\fR's that \fB\s-1DBI\s0\fR prepares for you. This has two advantages: it is fast (you even reuse the \f(CW\*(C`SV\*(C'\fR's, so they don't have to be created after the first \f(CW\*(C`fetchrow()\*(C'\fR), and it guarantees that \fB\s-1DBI\s0\fR handles \f(CW\*(C`bind_cols()\*(C'\fR for you. .PP What you do is the following: .PP .Vb 6 \& AV* av; \& int numFields = DBIc_NUM_FIELDS(imp_sth); /* Correct, if NUM_FIELDS \& is constant for this statement. There are drivers where this is \& not the case! */ \& int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); \& int i; \& \& if (!fetch_new_row_of_data(...)) { \& ... /* check for error or end\-of\-data */ \& DBIc_ACTIVE_off(imp_sth); /* turn off Active flag automatically */ \& return Nullav; \& } \& /* get the fbav (field buffer array value) for this row */ \& /* it is very important to only call this after you know */ \& /* that you have a row of data to return. */ \& av = DBIc_DBISTATE(imp_sth)\->get_fbav(imp_sth); \& for (i = 0; i < numFields; i++) { \& SV* sv = fetch_a_field(..., i); \& if (chopBlanks && SvOK(sv) && type_is_blank_padded(field_type[i])) { \& /* Remove white space from end (only) of sv */ \& } \& sv_setsv(AvARRAY(av)[i], sv); /* Note: (re)use! */ \& } \& return av; .Ve .PP There's no need to use a \f(CW\*(C`fetch_a_field()\*(C'\fR function returning an \f(CW\*(C`SV*\*(C'\fR. It's more common to use your database \s-1API\s0 functions to fetch the data as character strings and use code like this: .PP .Vb 1 \& sv_setpvn(AvARRAY(av)[i], char_ptr, char_count); .Ve .PP \&\f(CW\*(C`NULL\*(C'\fR values must be returned as \f(CW\*(C`undef\*(C'\fR. You can use code like this: .PP .Vb 1 \& SvOK_off(AvARRAY(av)[i]); .Ve .PP The function returns the \f(CW\*(C`AV\*(C'\fR prepared by \fB\s-1DBI\s0\fR for success or \f(CW\*(C`Nullav\*(C'\fR otherwise. .PP .Vb 3 \& *FIX ME* Discuss what happens when there\*(Aqs no more data to fetch. \& Are errors permitted if another fetch occurs after the first fetch \& that reports no more data. (Permitted, not required.) .Ve .PP If an error occurs which leaves the \fI\f(CI$sth\fI\fR in a state where remaining rows can't be fetched then \fIActive\fR should be turned off before the method returns. .PP \fIThe dbd_st_finish3 method\fR .IX Subsection "The dbd_st_finish3 method" .PP The \f(CW\*(C`$sth\->finish()\*(C'\fR method can be called if the user wishes to indicate that no more rows will be fetched even if the database has more rows to offer, and the \fB\s-1DBI\s0\fR code can call the function when handles are being destroyed. See the \fB\s-1DBI\s0\fR specification for more background details. .PP In both circumstances, the \fB\s-1DBI\s0\fR code ends up calling the \&\f(CW\*(C`dbd_st_finish3()\*(C'\fR method (if you provide a mapping for \&\f(CW\*(C`dbd_st_finish3()\*(C'\fR in \fIdbdimp.h\fR), or \f(CW\*(C`dbd_st_finish()\*(C'\fR otherwise. The difference is that \f(CW\*(C`dbd_st_finish3()\*(C'\fR takes a third argument which is an \f(CW\*(C`int\*(C'\fR with the value 1 if it is being called from a \f(CW\*(C`destroy()\*(C'\fR method and 0 otherwise. .PP Note that \fB\s-1DBI\s0\fR v1.32 and earlier test on \f(CW\*(C`dbd_db_finish3()\*(C'\fR to call \&\f(CW\*(C`dbd_st_finish3()\*(C'\fR; if you provide \f(CW\*(C`dbd_st_finish3()\*(C'\fR, either define \&\f(CW\*(C`dbd_db_finish3()\*(C'\fR too, or insist on \fB\s-1DBI\s0\fR v1.33 or later. .PP All it \fIneeds\fR to do is turn off the \fIActive\fR flag for the \fIsth\fR. It will only be called by \fIDriver.xst\fR code, if the driver has set \fI\s-1ACTIVE\s0\fR to on for the \fIsth\fR. .PP Outline example: .PP .Vb 8 \& int dbd_st_finish3(SV* sth, imp_sth_t* imp_sth, int from_destroy) { \& if (DBIc_ACTIVE(imp_sth)) \& { \& /* close cursor or equivalent action */ \& DBIc_ACTIVE_off(imp_sth); \& } \& return 1; \& } .Ve .PP The from_destroy parameter is true if \f(CW\*(C`dbd_st_finish3()\*(C'\fR is being called from \f(CW\*(C`DESTROY()\*(C'\fR \- and so the statement is about to be destroyed. For many drivers there is no point in doing anything more than turning off the \fIActive\fR flag in this case. .PP The function returns \fI\s-1TRUE\s0\fR for success, \fI\s-1FALSE\s0\fR otherwise, but there isn't a lot anyone can do to recover if there is an error. .PP \fIThe dbd_st_destroy method\fR .IX Subsection "The dbd_st_destroy method" .PP This function is the private part of the statement handle destructor. .PP .Vb 4 \& void dbd_st_destroy(SV* sth, imp_sth_t* imp_sth) { \& ... /* any clean\-up that\*(Aqs needed */ \& DBIc_IMPSET_off(imp_sth); /* let DBI know we\*(Aqve done it */ \& } .Ve .PP The \fB\s-1DBI\s0\fR \fIDriver.xst\fR code will call \f(CW\*(C`dbd_st_finish()\*(C'\fR for you, if the \&\fIsth\fR has the \fI\s-1ACTIVE\s0\fR flag set, before calling \f(CW\*(C`dbd_st_destroy()\*(C'\fR. .PP \fIThe dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods\fR .IX Subsection "The dbd_st_STORE_attrib and dbd_st_FETCH_attrib methods" .PP These functions correspond to \f(CW\*(C`dbd_db_STORE()\*(C'\fR and \f(CW\*(C`dbd_db_FETCH()\*(C'\fR attrib above, except that they are for statement handles. See above. .PP .Vb 3 \& int dbd_st_STORE_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv, \& SV* valuesv); \& SV* dbd_st_FETCH_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv); .Ve .PP \fIThe dbd_bind_ph method\fR .IX Subsection "The dbd_bind_ph method" .PP This function is internally used by the \f(CW\*(C`bind_param()\*(C'\fR method, the \&\f(CW\*(C`bind_param_inout()\*(C'\fR method and by the \fB\s-1DBI\s0\fR \fIDriver.xst\fR code if \&\f(CW\*(C`execute()\*(C'\fR is called with any bind parameters. .PP .Vb 3 \& int dbd_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param, \& SV *value, IV sql_type, SV *attribs, \& int is_inout, IV maxlen); .Ve .PP The \fIparam\fR argument holds an \f(CW\*(C`IV\*(C'\fR with the parameter number (1, 2, ...). The \fIvalue\fR argument is the parameter value and \fIsql_type\fR is its type. .PP If your driver does not support \f(CW\*(C`bind_param_inout()\*(C'\fR then you should ignore \fImaxlen\fR and croak if \fIis_inout\fR is \fI\s-1TRUE\s0\fR. .PP If your driver \fIdoes\fR support \f(CW\*(C`bind_param_inout()\*(C'\fR then you should note that \fIvalue\fR is the \f(CW\*(C`SV\*(C'\fR \fIafter\fR dereferencing the reference passed to \f(CW\*(C`bind_param_inout()\*(C'\fR. .PP In drivers of simple databases the function will, for example, store the value in a parameter array and use it later in \f(CW\*(C`dbd_st_execute()\*(C'\fR. See the \fBDBD::mysql\fR driver for an example. .PP \fIImplementing bind_param_inout support\fR .IX Subsection "Implementing bind_param_inout support" .PP To provide support for parameters bound by reference rather than by value, the driver must do a number of things. First, and most importantly, it must note the references and stash them in its own driver structure. Secondly, when a value is bound to a column, the driver must discard any previous reference bound to the column. On each execute, the driver must evaluate the references and internally bind the values resulting from the references. This is only applicable if the user writes: .PP .Vb 1 \& $sth\->execute; .Ve .PP If the user writes: .PP .Vb 1 \& $sth\->execute(@values); .Ve .PP then \fB\s-1DBI\s0\fR automatically calls the binding code for each element of \&\fI\f(CI@values\fI\fR. These calls are indistinguishable from explicit user calls to \&\f(CW\*(C`bind_param()\*(C'\fR. .SS "C/XS version of Makefile.PL" .IX Subsection "C/XS version of Makefile.PL" The \fIMakefile.PL\fR file for a C/XS driver is similar to the code needed for a pure Perl driver, but there are a number of extra bits of information needed by the build system. .PP For example, the attributes list passed to \f(CW\*(C`WriteMakefile()\*(C'\fR needs to specify the object files that need to be compiled and built into the shared object (\s-1DLL\s0). This is often, but not necessarily, just \&\fIdbdimp.o\fR (unless that should be \fIdbdimp.obj\fR because you're building on \s-1MS\s0 Windows). .PP Note that you can reliably determine the extension of the object files from the \fI\f(CI$Config\fI{obj_ext}\fR values, and there are many other useful pieces of configuration information lurking in that hash. You get access to it with: .PP .Vb 1 \& use Config; .Ve .SS "Methods which do not need to be written" .IX Subsection "Methods which do not need to be written" The \fB\s-1DBI\s0\fR code implements the majority of the methods which are accessed using the notation \f(CW\*(C`DBI\->function()\*(C'\fR, the only exceptions being \&\f(CW\*(C`DBI\->connect()\*(C'\fR and \f(CW\*(C`DBI\->data_sources()\*(C'\fR which require support from the driver. .PP The \fB\s-1DBI\s0\fR code implements the following documented driver, database and statement functions which do not need to be written by the \fB\s-1DBD\s0\fR driver writer. .ie n .IP "$dbh\->\fBdo()\fR" 4 .el .IP "\f(CW$dbh\fR\->\fBdo()\fR" 4 .IX Item "$dbh->do()" The default implementation of this function prepares, executes and destroys the statement. This can be replaced if there is a better way to implement this, such as \f(CW\*(C`EXECUTE IMMEDIATE\*(C'\fR which can sometimes be used if there are no parameters. .ie n .IP "$h\->\fBerrstr()\fR" 4 .el .IP "\f(CW$h\fR\->\fBerrstr()\fR" 4 .IX Item "$h->errstr()" .PD 0 .ie n .IP "$h\->\fBerr()\fR" 4 .el .IP "\f(CW$h\fR\->\fBerr()\fR" 4 .IX Item "$h->err()" .ie n .IP "$h\->\fBstate()\fR" 4 .el .IP "\f(CW$h\fR\->\fBstate()\fR" 4 .IX Item "$h->state()" .ie n .IP "$h\->\fBtrace()\fR" 4 .el .IP "\f(CW$h\fR\->\fBtrace()\fR" 4 .IX Item "$h->trace()" .PD The \fB\s-1DBD\s0\fR driver does not need to worry about these routines at all. .ie n .IP "$h\->{ChopBlanks}" 4 .el .IP "\f(CW$h\fR\->{ChopBlanks}" 4 .IX Item "$h->{ChopBlanks}" This attribute needs to be honored during \f(CW\*(C`fetch()\*(C'\fR operations, but does not need to be handled by the attribute handling code. .ie n .IP "$h\->{RaiseError}" 4 .el .IP "\f(CW$h\fR\->{RaiseError}" 4 .IX Item "$h->{RaiseError}" The \fB\s-1DBD\s0\fR driver does not need to worry about this attribute at all. .ie n .IP "$h\->{PrintError}" 4 .el .IP "\f(CW$h\fR\->{PrintError}" 4 .IX Item "$h->{PrintError}" The \fB\s-1DBD\s0\fR driver does not need to worry about this attribute at all. .ie n .IP "$sth\->\fBbind_col()\fR" 4 .el .IP "\f(CW$sth\fR\->\fBbind_col()\fR" 4 .IX Item "$sth->bind_col()" Assuming the driver uses the \f(CW\*(C`DBIc_DBISTATE(imp_xxh)\->get_fbav()\*(C'\fR function (C drivers, see below), or the \f(CW\*(C`$sth\->_set_fbav($data)\*(C'\fR method (Perl drivers) the driver does not need to do anything about this routine. .ie n .IP "$sth\->\fBbind_columns()\fR" 4 .el .IP "\f(CW$sth\fR\->\fBbind_columns()\fR" 4 .IX Item "$sth->bind_columns()" Regardless of whether the driver uses \&\f(CW\*(C`DBIc_DBISTATE(imp_xxh)\->get_fbav()\*(C'\fR, the driver does not need to do anything about this routine as it simply iteratively calls \&\f(CW\*(C`$sth\->bind_col()\*(C'\fR. .PP The \fB\s-1DBI\s0\fR code implements a default implementation of the following functions which do not need to be written by the \fB\s-1DBD\s0\fR driver writer unless the default implementation is incorrect for the Driver. .ie n .IP "$dbh\->\fBquote()\fR" 4 .el .IP "\f(CW$dbh\fR\->\fBquote()\fR" 4 .IX Item "$dbh->quote()" This should only be written if the database does not accept the \s-1ANSI SQL\s0 standard for quoting strings, with the string enclosed in single quotes and any embedded single quotes replaced by two consecutive single quotes. .Sp For the two argument form of quote, you need to implement the \&\f(CW\*(C`type_info()\*(C'\fR method to provide the information that quote needs. .ie n .IP "$dbh\->\fBping()\fR" 4 .el .IP "\f(CW$dbh\fR\->\fBping()\fR" 4 .IX Item "$dbh->ping()" This should be implemented as a simple efficient way to determine whether the connection to the database is still alive. Typically code like this: .Sp .Vb 9 \& sub ping { \& my $dbh = shift; \& $sth = $dbh\->prepare_cached(q{ \& select * from A_TABLE_NAME where 1=0 \& }) or return 0; \& $sth\->execute or return 0; \& $sth\->finish; \& return 1; \& } .Ve .Sp where \fIA_TABLE_NAME\fR is the name of a table that always exists (such as a database system catalogue). .ie n .IP "$drh\->default_user" 4 .el .IP "\f(CW$drh\fR\->default_user" 4 .IX Item "$drh->default_user" The default implementation of default_user will get the database username and password fields from \f(CW$ENV{DBI_USER}\fR and \&\f(CW$ENV{DBI_PASS}\fR. You can override this method. It is called as follows: .Sp .Vb 1 \& ($user, $pass) = $drh\->default_user($user, $pass, $attr) .Ve .SH "METADATA METHODS" .IX Header "METADATA METHODS" The exposition above ignores the \fB\s-1DBI\s0\fR MetaData methods. The metadata methods are all associated with a database handle. .SS "Using DBI::DBD::Metadata" .IX Subsection "Using DBI::DBD::Metadata" The \fBDBI::DBD::Metadata\fR module is a good semi-automatic way for the developer of a \fB\s-1DBD\s0\fR module to write the \f(CW\*(C`get_info()\*(C'\fR and \f(CW\*(C`type_info()\*(C'\fR functions quickly and accurately. .PP \fIGenerating the get_info method\fR .IX Subsection "Generating the get_info method" .PP Prior to \fB\s-1DBI\s0\fR v1.33, this existed as the method \f(CW\*(C`write_getinfo_pm()\*(C'\fR in the \fB\s-1DBI::DBD\s0\fR module. From \fB\s-1DBI\s0\fR v1.33, it exists as the method \&\f(CW\*(C`write_getinfo_pm()\*(C'\fR in the \fBDBI::DBD::Metadata\fR module. This discussion assumes you have \fB\s-1DBI\s0\fR v1.33 or later. .PP You examine the documentation for \f(CW\*(C`write_getinfo_pm()\*(C'\fR using: .PP .Vb 1 \& perldoc DBI::DBD::Metadata .Ve .PP To use it, you need a Perl \fB\s-1DBI\s0\fR driver for your database which implements the \f(CW\*(C`get_info()\*(C'\fR method. In practice, this means you need to install \&\fB\s-1DBD::ODBC\s0\fR, an \s-1ODBC\s0 driver manager, and an \s-1ODBC\s0 driver for your database. .PP With the pre-requisites in place, you might type: .PP .Vb 2 \& perl \-MDBI::DBD::Metadata \-we \e \& "write_getinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" .Ve .PP The procedure writes to standard output the code that should be added to your \fIDriver.pm\fR file and the code that should be written to \&\fIlib/DBD/Driver/GetInfo.pm\fR. .PP You should review the output to ensure that it is sensible. .PP \fIGenerating the type_info method\fR .IX Subsection "Generating the type_info method" .PP Given the idea of the \f(CW\*(C`write_getinfo_pm()\*(C'\fR method, it was not hard to devise a parallel method, \f(CW\*(C`write_typeinfo_pm()\*(C'\fR, which does the analogous job for the \fB\s-1DBI\s0\fR \f(CW\*(C`type_info_all()\*(C'\fR metadata method. The \&\f(CW\*(C`write_typeinfo_pm()\*(C'\fR method was added to \fB\s-1DBI\s0\fR v1.33. .PP You examine the documentation for \f(CW\*(C`write_typeinfo_pm()\*(C'\fR using: .PP .Vb 1 \& perldoc DBI::DBD::Metadata .Ve .PP The setup is exactly analogous to the mechanism described in \&\*(L"Generating the get_info method\*(R". .PP With the pre-requisites in place, you might type: .PP .Vb 2 \& perl \-MDBI::DBD::Metadata \-we \e \& "write_typeinfo_pm (qw{ dbi:ODBC:foo_db username password Driver })" .Ve .PP The procedure writes to standard output the code that should be added to your \fIDriver.pm\fR file and the code that should be written to \&\fIlib/DBD/Driver/TypeInfo.pm\fR. .PP You should review the output to ensure that it is sensible. .SS "Writing DBD::Driver::db::get_info" .IX Subsection "Writing DBD::Driver::db::get_info" If you use the \fBDBI::DBD::Metadata\fR module, then the code you need is generated for you. .PP If you decide not to use the \fBDBI::DBD::Metadata\fR module, you should probably borrow the code from a driver that has done so (eg \&\fBDBD::Informix\fR from version 1.05 onwards) and crib the code from there, or look at the code that generates that module and follow that. The method in \fIDriver.pm\fR will be very simple; the method in \&\fIlib/DBD/Driver/GetInfo.pm\fR is not very much more complex unless your \&\s-1DBMS\s0 itself is much more complex. .PP Note that some of the \fB\s-1DBI\s0\fR utility methods rely on information from the \&\f(CW\*(C`get_info()\*(C'\fR method to perform their operations correctly. See, for example, the \f(CW\*(C`quote_identifier()\*(C'\fR and quote methods, discussed below. .SS "Writing DBD::Driver::db::type_info_all" .IX Subsection "Writing DBD::Driver::db::type_info_all" If you use the \f(CW\*(C`DBI::DBD::Metadata\*(C'\fR module, then the code you need is generated for you. .PP If you decide not to use the \f(CW\*(C`DBI::DBD::Metadata\*(C'\fR module, you should probably borrow the code from a driver that has done so (eg \&\f(CW\*(C`DBD::Informix\*(C'\fR from version 1.05 onwards) and crib the code from there, or look at the code that generates that module and follow that. The method in \fIDriver.pm\fR will be very simple; the method in \&\fIlib/DBD/Driver/TypeInfo.pm\fR is not very much more complex unless your \&\s-1DBMS\s0 itself is much more complex. .SS "Writing DBD::Driver::db::type_info" .IX Subsection "Writing DBD::Driver::db::type_info" The guidelines on writing this method are still not really clear. No sample implementation is available. .SS "Writing DBD::Driver::db::table_info" .IX Subsection "Writing DBD::Driver::db::table_info" .Vb 2 \& *FIX ME* The guidelines on writing this method have not been written yet. \& No sample implementation is available. .Ve .SS "Writing DBD::Driver::db::column_info" .IX Subsection "Writing DBD::Driver::db::column_info" .Vb 2 \& *FIX ME* The guidelines on writing this method have not been written yet. \& No sample implementation is available. .Ve .SS "Writing DBD::Driver::db::primary_key_info" .IX Subsection "Writing DBD::Driver::db::primary_key_info" .Vb 2 \& *FIX ME* The guidelines on writing this method have not been written yet. \& No sample implementation is available. .Ve .SS "Writing DBD::Driver::db::primary_key" .IX Subsection "Writing DBD::Driver::db::primary_key" .Vb 2 \& *FIX ME* The guidelines on writing this method have not been written yet. \& No sample implementation is available. .Ve .SS "Writing DBD::Driver::db::foreign_key_info" .IX Subsection "Writing DBD::Driver::db::foreign_key_info" .Vb 2 \& *FIX ME* The guidelines on writing this method have not been written yet. \& No sample implementation is available. .Ve .SS "Writing DBD::Driver::db::tables" .IX Subsection "Writing DBD::Driver::db::tables" This method generates an array of names in a format suitable for being embedded in \s-1SQL\s0 statements in places where a table name is expected. .PP If your database hews close enough to the \s-1SQL\s0 standard or if you have implemented an appropriate \f(CW\*(C`table_info()\*(C'\fR function and and the appropriate \&\f(CW\*(C`quote_identifier()\*(C'\fR function, then the \fB\s-1DBI\s0\fR default version of this method will work for your driver too. .PP Otherwise, you have to write a function yourself, such as: .PP .Vb 12 \& sub tables \& { \& my($dbh, $cat, $sch, $tab, $typ) = @_; \& my(@res); \& my($sth) = $dbh\->table_info($cat, $sch, $tab, $typ); \& my(@arr); \& while (@arr = $sth\->fetchrow_array) \& { \& push @res, $dbh\->quote_identifier($arr[0], $arr[1], $arr[2]); \& } \& return @res; \& } .Ve .PP See also the default implementation in \fI\s-1DBI\s0.pm\fR. .SS "Writing DBD::Driver::db::quote" .IX Subsection "Writing DBD::Driver::db::quote" This method takes a value and converts it into a string suitable for embedding in an \s-1SQL\s0 statement as a string literal. .PP If your \s-1DBMS\s0 accepts the \s-1SQL\s0 standard notation for strings (single quotes around the string as a whole with any embedded single quotes doubled up), then you do not need to write this method as \fB\s-1DBI\s0\fR provides a default method that does it for you. .PP If your \s-1DBMS\s0 uses an alternative notation or escape mechanism, then you need to provide an equivalent function. For example, suppose your \s-1DBMS\s0 used C notation with double quotes around the string and backslashes escaping both double quotes and backslashes themselves. Then you might write the function as: .PP .Vb 6 \& sub quote \& { \& my($dbh, $str) = @_; \& $str =~ s/["\e\e]/\e\e$&/gmo; \& return qq{"$str"}; \& } .Ve .PP Handling newlines and other control characters is left as an exercise for the reader. .PP This sample method ignores the \fI\f(CI$data_type\fI\fR indicator which is the optional second argument to the method. .SS "Writing DBD::Driver::db::quote_identifier" .IX Subsection "Writing DBD::Driver::db::quote_identifier" This method is called to ensure that the name of the given table (or other database object) can be embedded into an \s-1SQL\s0 statement without danger of misinterpretation. The result string should be usable in the text of an \s-1SQL\s0 statement as the identifier for a table. .PP If your \s-1DBMS\s0 accepts the \s-1SQL\s0 standard notation for quoted identifiers (which uses double quotes around the identifier as a whole, with any embedded double quotes doubled up) and accepts \fI\*(L"schema\*(R".\*(L"identifier\*(R"\fR (and \fI\*(L"catalog\*(R".\*(L"schema\*(R".\*(L"identifier\*(R"\fR when a catalog is specified), then you do not need to write this method as \fB\s-1DBI\s0\fR provides a default method that does it for you. .PP In fact, even if your \s-1DBMS\s0 does not handle exactly that notation but you have implemented the \f(CW\*(C`get_info()\*(C'\fR method and it gives the correct responses, then it will work for you. If your database is fussier, then you need to implement your own version of the function. .PP For example, \fBDBD::Informix\fR has to deal with an environment variable \&\fI\s-1DELIMIDENT\s0\fR. If it is not set, then the \s-1DBMS\s0 treats names enclosed in double quotes as strings rather than names, which is usually a syntax error. Additionally, the catalog portion of the name is separated from the schema and table by a different delimiter (colon instead of dot), and the catalog portion is never enclosed in quotes. (Fortunately, valid strings for the catalog will never contain weird characters that might need to be escaped, unless you count dots, dashes, slashes and at-signs as weird.) Finally, an Informix database can contain objects that cannot be accessed because they were created by a user with the \&\fI\s-1DELIMIDENT\s0\fR environment variable set, but the current user does not have it set. By design choice, the \f(CW\*(C`quote_identifier()\*(C'\fR method encloses those identifiers in double quotes anyway, which generally triggers a syntax error, and the metadata methods which generate lists of tables etc omit those identifiers from the result sets. .PP .Vb 10 \& sub quote_identifier \& { \& my($dbh, $cat, $sch, $obj) = @_; \& my($rv) = ""; \& my($qq) = (defined $ENV{DELIMIDENT}) ? \*(Aq"\*(Aq : \*(Aq\*(Aq; \& $rv .= qq{$cat:} if (defined $cat); \& if (defined $sch) \& { \& if ($sch !~ m/^\ew+$/o) \& { \& $qq = \*(Aq"\*(Aq; \& $sch =~ s/$qq/$qq$qq/gm; \& } \& $rv .= qq{$qq$sch$qq.}; \& } \& if (defined $obj) \& { \& if ($obj !~ m/^\ew+$/o) \& { \& $qq = \*(Aq"\*(Aq; \& $obj =~ s/$qq/$qq$qq/gm; \& } \& $rv .= qq{$qq$obj$qq}; \& } \& return $rv; \& } .Ve .PP Handling newlines and other control characters is left as an exercise for the reader. .PP Note that there is an optional fourth parameter to this function which is a reference to a hash of attributes; this sample implementation ignores that. .PP This sample implementation also ignores the single-argument variant of the method. .SH "TRACING" .IX Header "TRACING" Tracing in \s-1DBI\s0 is controlled with a combination of a trace level and a set of flags which together are known as the trace settings. The trace settings are stored in a single integer and divided into levels and flags by a set of masks (\f(CW\*(C`DBIc_TRACE_LEVEL_MASK\*(C'\fR and \&\f(CW\*(C`DBIc_TRACE_FLAGS_MASK\*(C'\fR). .PP Each handle has it's own trace settings and so does the \s-1DBI.\s0 When you call a method the \s-1DBI\s0 merges the handles settings into its own for the duration of the call: the trace flags of the handle are \s-1OR\s0'd into the trace flags of the \s-1DBI,\s0 and if the handle has a higher trace level then the \s-1DBI\s0 trace level is raised to match it. The previous \s-1DBI\s0 trace settings are restored when the called method returns. .SS "Trace Level" .IX Subsection "Trace Level" The trace level is the first 4 bits of the trace settings (masked by \&\f(CW\*(C`DBIc_TRACE_FLAGS_MASK\*(C'\fR) and represents trace levels of 1 to 15. Do not output anything at trace levels less than 3 as they are reserved for \s-1DBI.\s0 .PP For advice on what to output at each level see \*(L"Trace Levels\*(R" in \&\s-1DBI\s0. .PP To test for a trace level you can use the \f(CW\*(C`DBIc_TRACE_LEVEL\*(C'\fR macro like this: .PP .Vb 3 \& if (DBIc_TRACE_LEVEL(imp_xxh) >= 2) { \& PerlIO_printf(DBIc_LOGPIO(imp_xxh), "foobar"); \& } .Ve .PP Also \fBnote\fR the use of PerlIO_printf which you should always use for tracing and never the C \f(CW\*(C`stdio.h\*(C'\fR I/O functions. .SS "Trace Flags" .IX Subsection "Trace Flags" Trace flags are used to enable tracing of specific activities within the \s-1DBI\s0 and drivers. The \s-1DBI\s0 defines some trace flags and drivers can define others. \s-1DBI\s0 trace flag names begin with a capital letter and driver specific names begin with a lowercase letter. For a list of \s-1DBI\s0 defined trace flags see \*(L"Trace Flags\*(R" in \s-1DBI\s0. .PP If you want to use private trace flags you'll probably want to be able to set them by name. Drivers are expected to override the parse_trace_flag (note the singular) and check if \f(CW$trace_flag_name\fR is a driver specific trace flags and, if not, then call the DBIs default \&\fBparse_trace_flag()\fR. To do that you'll need to define a \&\fBparse_trace_flag()\fR method like this: .PP .Vb 9 \& sub parse_trace_flag { \& my ($h, $name) = @_; \& return 0x01000000 if $name eq \*(Aqfoo\*(Aq; \& return 0x02000000 if $name eq \*(Aqbar\*(Aq; \& return 0x04000000 if $name eq \*(Aqbaz\*(Aq; \& return 0x08000000 if $name eq \*(Aqboo\*(Aq; \& return 0x10000000 if $name eq \*(Aqbop\*(Aq; \& return $h\->SUPER::parse_trace_flag($name); \& } .Ve .PP All private flag names must be lowercase, and all private flags must be in the top 8 of the 32 bits of \f(CW\*(C`DBIc_TRACE_FLAGS(imp)\*(C'\fR i.e., 0xFF000000. .PP If you've defined a \fBparse_trace_flag()\fR method in ::db you'll also want it in ::st, so just alias it in: .PP .Vb 1 \& *parse_trace_flag = \e&DBD::foo:db::parse_trace_flag; .Ve .PP You may want to act on the current '\s-1SQL\s0' trace flag that \s-1DBI\s0 defines to output \s-1SQL\s0 prepared/executed as \s-1DBI\s0 currently does not do \s-1SQL\s0 tracing. .SS "Trace Macros" .IX Subsection "Trace Macros" Access to the trace level and trace flags is via a set of macros. .PP .Vb 4 \& DBIc_TRACE_SETTINGS(imp) returns the trace settings \& DBIc_TRACE_LEVEL(imp) returns the trace level \& DBIc_TRACE_FLAGS(imp) returns the trace flags \& DBIc_TRACE(imp, flags, flaglevel, level) \& \& e.g., \& \& DBIc_TRACE(imp, 0, 0, 4) \& if level >= 4 \& \& DBIc_TRACE(imp, DBDtf_FOO, 2, 4) \& if tracing DBDtf_FOO & level>=2 or level>=4 \& \& DBIc_TRACE(imp, DBDtf_FOO, 2, 0) \& as above but never trace just due to level .Ve .SH "WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE" .IX Header "WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE" Study \fIOraperl.pm\fR (supplied with \fBDBD::Oracle\fR) and \fIIngperl.pm\fR (supplied with \fBDBD::Ingres\fR) and the corresponding \fIdbdimp.c\fR files for ideas. .PP Note that the emulation code sets \f(CW\*(C`$dbh\->{CompatMode} = 1;\*(C'\fR for each connection so that the internals of the driver can implement behaviour compatible with the old interface when dealing with those handles. .SS "Setting emulation perl variables" .IX Subsection "Setting emulation perl variables" For example, ingperl has a \fI\f(CI$sql_rowcount\fI\fR variable. Rather than try to manually update this in \fIIngperl.pm\fR it can be done faster in C code. In \f(CW\*(C`dbd_init()\*(C'\fR: .PP .Vb 1 \& sql_rowcount = perl_get_sv("Ingperl::sql_rowcount", GV_ADDMULTI); .Ve .PP In the relevant places do: .PP .Vb 2 \& if (DBIc_COMPAT(imp_sth)) /* only do this for compatibility mode handles */ \& sv_setiv(sql_rowcount, the_row_count); .Ve .SH "OTHER MISCELLANEOUS INFORMATION" .IX Header "OTHER MISCELLANEOUS INFORMATION" .SS "The imp_xyz_t types" .IX Subsection "The imp_xyz_t types" Any handle has a corresponding C structure filled with private data. Some of this data is reserved for use by \fB\s-1DBI\s0\fR (except for using the DBIc macros below), some is for you. See the description of the \&\fIdbdimp.h\fR file above for examples. Most functions in \fIdbdimp.c\fR are passed both the handle \f(CW\*(C`xyz\*(C'\fR and a pointer to \f(CW\*(C`imp_xyz\*(C'\fR. In rare cases, however, you may use the following macros: .IP "D_imp_dbh(dbh)" 4 .IX Item "D_imp_dbh(dbh)" Given a function argument \fIdbh\fR, declare a variable \fIimp_dbh\fR and initialize it with a pointer to the handles private data. Note: This must be a part of the function header, because it declares a variable. .IP "D_imp_sth(sth)" 4 .IX Item "D_imp_sth(sth)" Likewise for statement handles. .IP "D_imp_xxx(h)" 4 .IX Item "D_imp_xxx(h)" Given any handle, declare a variable \fIimp_xxx\fR and initialize it with a pointer to the handles private data. It is safe, for example, to cast \fIimp_xxx\fR to \f(CW\*(C`imp_dbh_t*\*(C'\fR, if \f(CW\*(C`DBIc_TYPE(imp_xxx) == DBIt_DB\*(C'\fR. (You can also call \f(CW\*(C`sv_derived_from(h, "DBI::db")\*(C'\fR, but that's much slower.) .IP "D_imp_dbh_from_sth" 4 .IX Item "D_imp_dbh_from_sth" Given a \fIimp_sth\fR, declare a variable \fIimp_dbh\fR and initialize it with a pointer to the parent database handle's implementors structure. .SS "Using DBIc_IMPSET_on" .IX Subsection "Using DBIc_IMPSET_on" The driver code which initializes a handle should use \f(CW\*(C`DBIc_IMPSET_on()\*(C'\fR as soon as its state is such that the cleanup code must be called. When this happens is determined by your driver code. .PP \&\fBFailure to call this can lead to corruption of data structures.\fR .PP For example, \fBDBD::Informix\fR maintains a linked list of database handles in the driver, and within each handle, a linked list of statements. Once a statement is added to the linked list, it is crucial that it is cleaned up (removed from the list). When \fI\f(BIDBIc_IMPSET_on()\fI\fR was being called too late, it was able to cause all sorts of problems. .SS "Using \fBDBIc_is()\fP, \fBDBIc_has()\fP, \fBDBIc_on()\fP and \fBDBIc_off()\fP" .IX Subsection "Using DBIc_is(), DBIc_has(), DBIc_on() and DBIc_off()" Once upon a long time ago, the only way of handling the internal \fB\s-1DBI\s0\fR boolean flags/attributes was through macros such as: .PP .Vb 2 \& DBIc_WARN DBIc_WARN_on DBIc_WARN_off \& DBIc_COMPAT DBIc_COMPAT_on DBIc_COMPAT_off .Ve .PP Each of these took an \fIimp_xxh\fR pointer as an argument. .PP Since then, new attributes have been added such as \fIChopBlanks\fR, \&\fIRaiseError\fR and \fIPrintError\fR, and these do not have the full set of macros. The approved method for handling these is now the four macros: .PP .Vb 5 \& DBIc_is(imp, flag) \& DBIc_has(imp, flag) an alias for DBIc_is \& DBIc_on(imp, flag) \& DBIc_off(imp, flag) \& DBIc_set(imp, flag, on) set if on is true, else clear .Ve .PP Consequently, the \f(CW\*(C`DBIc_XXXXX\*(C'\fR family of macros is now mostly deprecated and new drivers should avoid using them, even though the older drivers will probably continue to do so for quite a while yet. However... .PP There is an \fIimportant exception\fR to that. The \fI\s-1ACTIVE\s0\fR and \fI\s-1IMPSET\s0\fR flags should be set via the \f(CW\*(C`DBIc_ACTIVE_on()\*(C'\fR and \f(CW\*(C`DBIc_IMPSET_on()\*(C'\fR macros, and unset via the \f(CW\*(C`DBIc_ACTIVE_off()\*(C'\fR and \f(CW\*(C`DBIc_IMPSET_off()\*(C'\fR macros. .SS "Using the \fBget_fbav()\fP method" .IX Subsection "Using the get_fbav() method" \&\fB\s-1THIS IS CRITICAL\s0 for C/XS drivers\fR. .PP The \f(CW\*(C`$sth\->bind_col()\*(C'\fR and \f(CW\*(C`$sth\->bind_columns()\*(C'\fR documented in the \fB\s-1DBI\s0\fR specification do not have to be implemented by the driver writer because \fB\s-1DBI\s0\fR takes care of the details for you. .PP However, the key to ensuring that bound columns work is to call the function \f(CW\*(C`DBIc_DBISTATE(imp_xxh)\->get_fbav()\*(C'\fR in the code which fetches a row of data. .PP This returns an \f(CW\*(C`AV\*(C'\fR, and each element of the \f(CW\*(C`AV\*(C'\fR contains the \f(CW\*(C`SV\*(C'\fR which should be set to contain the returned data. .PP The pure Perl equivalent is the \f(CW\*(C`$sth\->_set_fbav($data)\*(C'\fR method, as described in the part on pure Perl drivers. .SS "Casting strings to Perl types based on a \s-1SQL\s0 type" .IX Subsection "Casting strings to Perl types based on a SQL type" \&\s-1DBI\s0 from 1.611 (and \s-1DBIXS_REVISION 13606\s0) defines the sql_type_cast_svpv method which may be used to cast a string representation of a value to a more specific Perl type based on a \s-1SQL\s0 type. You should consider using this method when processing bound column data as it provides some support for the \s-1TYPE\s0 bind_col attribute which is rarely used in drivers. .PP .Vb 1 \& int sql_type_cast_svpv(pTHX_ SV *sv, int sql_type, U32 flags, void *v) .Ve .PP \&\f(CW\*(C`sv\*(C'\fR is what you would like cast, \f(CW\*(C`sql_type\*(C'\fR is one of the \s-1DBI\s0 defined \&\s-1SQL\s0 types (e.g., \f(CW\*(C`SQL_INTEGER\*(C'\fR) and \f(CW\*(C`flags\*(C'\fR is a bitmask as follows: .IP "DBIstcf_STRICT" 4 .IX Item "DBIstcf_STRICT" If set this indicates you want an error state returned if the cast cannot be performed. .IP "DBIstcf_DISCARD_STRING" 4 .IX Item "DBIstcf_DISCARD_STRING" If set and the pv portion of the \f(CW\*(C`sv\*(C'\fR is cast then this will cause sv's pv to be freed up. .PP sql_type_cast_svpv returns the following states: .PP .Vb 5 \& \-2 sql_type is not handled \- sv not changed \& \-1 sv is undef, sv not changed \& 0 sv could not be cast cleanly and DBIstcf_STRICT was specified \& 1 sv could not be case cleanly and DBIstcf_STRICT was not specified \& 2 sv was cast ok .Ve .PP The current implementation of sql_type_cast_svpv supports \&\f(CW\*(C`SQL_INTEGER\*(C'\fR, \f(CW\*(C`SQL_DOUBLE\*(C'\fR and \f(CW\*(C`SQL_NUMERIC\*(C'\fR. \f(CW\*(C`SQL_INTEGER\*(C'\fR uses sv_2iv and hence may set \s-1IV, UV\s0 or \s-1NV\s0 depending on the number. \f(CW\*(C`SQL_DOUBLE\*(C'\fR uses sv_2nv so may set \s-1NV\s0 and \f(CW\*(C`SQL_NUMERIC\*(C'\fR will set \s-1IV\s0 or \s-1UV\s0 or \s-1NV.\s0 .PP DBIstcf_STRICT should be implemented as the StrictlyTyped attribute and DBIstcf_DISCARD_STRING implemented as the DiscardString attribute to the bind_col method and both default to off. .PP See DBD::Oracle for an example of how this is used. .SH "SUBCLASSING DBI DRIVERS" .IX Header "SUBCLASSING DBI DRIVERS" This is definitely an open subject. It can be done, as demonstrated by the \fBDBD::File\fR driver, but it is not as simple as one might think. .PP (Note that this topic is different from subclassing the \fB\s-1DBI\s0\fR. For an example of that, see the \fIt/subclass.t\fR file supplied with the \fB\s-1DBI\s0\fR.) .PP The main problem is that the \fIdbh\fR's and \fIsth\fR's that your \f(CW\*(C`connect()\*(C'\fR and \&\f(CW\*(C`prepare()\*(C'\fR methods return are not instances of your \fBDBD::Driver::db\fR or \fBDBD::Driver::st\fR packages, they are not even derived from it. Instead they are instances of the \fBDBI::db\fR or \fBDBI::st\fR classes or a derived subclass. Thus, if you write a method \f(CW\*(C`mymethod()\*(C'\fR and do a .PP .Vb 1 \& $dbh\->mymethod() .Ve .PP then the autoloader will search for that method in the package \fBDBI::db\fR. Of course you can instead to a .PP .Vb 1 \& $dbh\->func(\*(Aqmymethod\*(Aq) .Ve .PP and that will indeed work, even if \f(CW\*(C`mymethod()\*(C'\fR is inherited, but not without additional work. Setting \fI\f(CI@ISA\fI\fR is not sufficient. .SS "Overwriting methods" .IX Subsection "Overwriting methods" The first problem is, that the \f(CW\*(C`connect()\*(C'\fR method has no idea of subclasses. For example, you cannot implement base class and subclass in the same file: The \f(CW\*(C`install_driver()\*(C'\fR method wants to do a .PP .Vb 1 \& require DBD::Driver; .Ve .PP In particular, your subclass \fBhas\fR to be a separate driver, from the view of \fB\s-1DBI\s0\fR, and you cannot share driver handles. .PP Of course that's not much of a problem. You should even be able to inherit the base classes \f(CW\*(C`connect()\*(C'\fR method. But you cannot simply overwrite the method, unless you do something like this, quoted from \fB\s-1DBD::CSV\s0\fR: .PP .Vb 2 \& sub connect ($$;$$$) { \& my ($drh, $dbname, $user, $auth, $attr) = @_; \& \& my $this = $drh\->DBD::File::dr::connect($dbname, $user, $auth, $attr); \& if (!exists($this\->{csv_tables})) { \& $this\->{csv_tables} = {}; \& } \& \& $this; \& } .Ve .PP Note that we cannot do a .PP .Vb 1 \& $drh\->SUPER::connect($dbname, $user, $auth, $attr); .Ve .PP as we would usually do in a an \s-1OO\s0 environment, because \fI\f(CI$drh\fI\fR is an instance of \fBDBI::dr\fR. And note, that the \f(CW\*(C`connect()\*(C'\fR method of \fBDBD::File\fR is able to handle subclass attributes. See the description of Pure Perl drivers above. .PP It is essential that you always call superclass method in the above manner. However, that should do. .SS "Attribute handling" .IX Subsection "Attribute handling" Fortunately the \fB\s-1DBI\s0\fR specifications allow a simple, but still performant way of handling attributes. The idea is based on the convention that any driver uses a prefix \fIdriver_\fR for its private methods. Thus it's always clear whether to pass attributes to the super class or not. For example, consider this \f(CW\*(C`STORE()\*(C'\fR method from the \&\fB\s-1DBD::CSV\s0\fR class: .PP .Vb 8 \& sub STORE { \& my ($dbh, $attr, $val) = @_; \& if ($attr !~ /^driver_/) { \& return $dbh\->DBD::File::db::STORE($attr, $val); \& } \& if ($attr eq \*(Aqdriver_foo\*(Aq) { \& ... \& } .Ve .SH "AUTHORS" .IX Header "AUTHORS" Jonathan Leffler (previously ), Jochen Wiedmann , Steffen Goeldner , and Tim Bunce . man/man3/JSON.3pm000044400000175366152462503210007367 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON 3" .TH JSON 3 "2021-01-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON \- JSON (JavaScript Object Notation) encoder/decoder .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use JSON; # imports encode_json, decode_json, to_json and from_json. \& \& # simple and fast interfaces (expect/generate UTF\-8) \& \& $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; \& $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; \& \& # OO\-interface \& \& $json = JSON\->new\->allow_nonref; \& \& $json_text = $json\->encode( $perl_scalar ); \& $perl_scalar = $json\->decode( $json_text ); \& \& $pretty_printed = $json\->pretty\->encode( $perl_scalar ); # pretty\-printing .Ve .SH "VERSION" .IX Header "VERSION" .Vb 1 \& 4.02 .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module is a thin wrapper for \s-1JSON::XS\s0\-compatible modules with a few additional features. All the backend modules convert a Perl data structure to a \s-1JSON\s0 text and vice versa. This module uses \s-1JSON::XS\s0 by default, and when \s-1JSON::XS\s0 is not available, falls back on \s-1JSON::PP\s0, which is in the Perl core since 5.14. If \s-1JSON::PP\s0 is not available either, this module then falls back on JSON::backportPP (which is actually \s-1JSON::PP\s0 in a different .pm file) bundled in the same distribution as this module. You can also explicitly specify to use Cpanel::JSON::XS, a fork of \&\s-1JSON::XS\s0 by Reini Urban. .PP All these backend modules have slight incompatibilities between them, including extra features that other modules don't support, but as long as you use only common features (most important ones are described below), migration from backend to backend should be reasonably easy. For details, see each backend module you use. .SH "CHOOSING BACKEND" .IX Header "CHOOSING BACKEND" This module respects an environmental variable called \f(CW\*(C`PERL_JSON_BACKEND\*(C'\fR when it decides a backend module to use. If this environmental variable is not set, it tries to load \s-1JSON::XS,\s0 and if \s-1JSON::XS\s0 is not available, it falls back on \s-1JSON::PP,\s0 and then JSON::backportPP if \s-1JSON::PP\s0 is not available either. .PP If you always don't want it to fall back on pure perl modules, set the variable like this (\f(CW\*(C`export\*(C'\fR may be \f(CW\*(C`setenv\*(C'\fR, \f(CW\*(C`set\*(C'\fR and the likes, depending on your environment): .PP .Vb 1 \& > export PERL_JSON_BACKEND=JSON::XS .Ve .PP If you prefer Cpanel::JSON::XS to \s-1JSON::XS,\s0 then: .PP .Vb 1 \& > export PERL_JSON_BACKEND=Cpanel::JSON::XS,JSON::XS,JSON::PP .Ve .PP You may also want to set this variable at the top of your test files, in order not to be bothered with incompatibilities between backends (you need to wrap this in \f(CW\*(C`BEGIN\*(C'\fR, and set before actually \f(CW\*(C`use\*(C'\fR\-ing \s-1JSON\s0 module, as it decides its backend as soon as it's loaded): .PP .Vb 2 \& BEGIN { $ENV{PERL_JSON_BACKEND}=\*(AqJSON::backportPP\*(Aq; } \& use JSON; .Ve .SH "USING OPTIONAL FEATURES" .IX Header "USING OPTIONAL FEATURES" There are a few options you can set when you \f(CW\*(C`use\*(C'\fR this module. These historical options are only kept for backward compatibility, and should not be used in a new application. .IP "\-support_by_pp" 4 .IX Item "-support_by_pp" .Vb 1 \& BEGIN { $ENV{PERL_JSON_BACKEND} = \*(AqJSON::XS\*(Aq } \& \& use JSON \-support_by_pp; \& \& my $json = JSON\->new; \& # escape_slash is for JSON::PP only. \& $json\->allow_nonref\->escape_slash\->encode("/"); .Ve .Sp With this option, this module loads its pure perl backend along with its \s-1XS\s0 backend (if available), and lets the \s-1XS\s0 backend to watch if you set a flag only \s-1JSON::PP\s0 supports. When you do, the internal \s-1JSON::XS\s0 object is replaced with a newly created \s-1JSON::PP\s0 object with the setting copied from the \s-1XS\s0 object, so that you can use \s-1JSON::PP\s0 flags (and its slower \&\f(CW\*(C`decode\*(C'\fR/\f(CW\*(C`encode\*(C'\fR methods) from then on. In other words, this is not something that allows you to hook \s-1JSON::XS\s0 to change its behavior while keeping its speed. \s-1JSON::XS\s0 and \s-1JSON::PP\s0 objects are quite different (\s-1JSON::XS\s0 object is a blessed scalar reference, while \s-1JSON::PP\s0 object is a blessed hash reference), and can't share their internals. .Sp To avoid needless overhead (by copying settings), you are advised not to use this option and just to use \s-1JSON::PP\s0 explicitly when you need \&\s-1JSON::PP\s0 features. .IP "\-convert_blessed_universally" 4 .IX Item "-convert_blessed_universally" .Vb 1 \& use JSON \-convert_blessed_universally; \& \& my $json = JSON\->new\->allow_nonref\->convert_blessed; \& my $object = bless {foo => \*(Aqbar\*(Aq}, \*(AqFoo\*(Aq; \& $json\->encode($object); # => {"foo":"bar"} .Ve .Sp JSON::XS\-compatible backend modules don't encode blessed objects by default (except for their boolean values, which are typically blessed JSON::PP::Boolean objects). If you need to encode a data structure that may contain objects, you usually need to look into the structure and replace objects with alternative non-blessed values, or enable \&\f(CW\*(C`convert_blessed\*(C'\fR and provide a \f(CW\*(C`TO_JSON\*(C'\fR method for each object's (base) class that may be found in the structure, in order to let the methods replace the objects with whatever scalar values the methods return. .Sp If you need to serialise data structures that may contain arbitrary objects, it's probably better to use other serialisers (such as Sereal or Storable for example), but if you do want to use this module for that purpose, \f(CW\*(C`\-convert_blessed_universally\*(C'\fR option may help, which tweaks \f(CW\*(C`encode\*(C'\fR method of the backend to install \&\f(CW\*(C`UNIVERSAL::TO_JSON\*(C'\fR method (locally) before encoding, so that all the objects that don't have their own \f(CW\*(C`TO_JSON\*(C'\fR method can fall back on the method in the \f(CW\*(C`UNIVERSAL\*(C'\fR namespace. Note that you still need to enable \f(CW\*(C`convert_blessed\*(C'\fR flag to actually encode objects in a data structure, and \f(CW\*(C`UNIVERSAL::TO_JSON\*(C'\fR method installed by this option only converts blessed hash/array references into their unblessed clone (including private keys/values that are not supposed to be exposed). Other blessed references will be converted into null. .Sp This feature is experimental and may be removed in the future. .IP "\-no_export" 4 .IX Item "-no_export" When you don't want to import functional interfaces from a module, you usually supply \f(CW\*(C`()\*(C'\fR to its \f(CW\*(C`use\*(C'\fR statement. .Sp .Vb 1 \& use JSON (); # no functional interfaces .Ve .Sp If you don't want to import functional interfaces, but you also want to use any of the above options, add \f(CW\*(C`\-no_export\*(C'\fR to the option list. .Sp .Vb 2 \& # no functional interfaces, while JSON::PP support is enabled. \& use JSON \-support_by_pp, \-no_export; .Ve .SH "FUNCTIONAL INTERFACE" .IX Header "FUNCTIONAL INTERFACE" This section is taken from \s-1JSON::XS.\s0 \f(CW\*(C`encode_json\*(C'\fR and \f(CW\*(C`decode_json\*(C'\fR are exported by default. .PP This module also exports \f(CW\*(C`to_json\*(C'\fR and \f(CW\*(C`from_json\*(C'\fR for backward compatibility. These are slower, and may expect/generate different stuff from what \f(CW\*(C`encode_json\*(C'\fR and \f(CW\*(C`decode_json\*(C'\fR do, depending on their options. It's better just to use Object-Oriented interfaces than using these two functions. .SS "encode_json" .IX Subsection "encode_json" .Vb 1 \& $json_text = encode_json $perl_scalar .Ve .PP Converts the given Perl data structure to a \s-1UTF\-8\s0 encoded, binary string (that is, the string contains octets only). Croaks on error. .PP This function call is functionally identical to: .PP .Vb 1 \& $json_text = JSON\->new\->utf8\->encode($perl_scalar) .Ve .PP Except being faster. .SS "decode_json" .IX Subsection "decode_json" .Vb 1 \& $perl_scalar = decode_json $json_text .Ve .PP The opposite of \f(CW\*(C`encode_json\*(C'\fR: expects an \s-1UTF\-8\s0 (binary) string and tries to parse that as an \s-1UTF\-8\s0 encoded \s-1JSON\s0 text, returning the resulting reference. Croaks on error. .PP This function call is functionally identical to: .PP .Vb 1 \& $perl_scalar = JSON\->new\->utf8\->decode($json_text) .Ve .PP Except being faster. .SS "to_json" .IX Subsection "to_json" .Vb 1 \& $json_text = to_json($perl_scalar[, $optional_hashref]) .Ve .PP Converts the given Perl data structure to a Unicode string by default. Croaks on error. .PP Basically, this function call is functionally identical to: .PP .Vb 1 \& $json_text = JSON\->new\->encode($perl_scalar) .Ve .PP Except being slower. .PP You can pass an optional hash reference to modify its behavior, but that may change what \f(CW\*(C`to_json\*(C'\fR expects/generates (see \&\f(CW\*(C`ENCODING/CODESET FLAG NOTES\*(C'\fR for details). .PP .Vb 2 \& $json_text = to_json($perl_scalar, {utf8 => 1, pretty => 1}) \& # => JSON\->new\->utf8(1)\->pretty(1)\->encode($perl_scalar) .Ve .SS "from_json" .IX Subsection "from_json" .Vb 1 \& $perl_scalar = from_json($json_text[, $optional_hashref]) .Ve .PP The opposite of \f(CW\*(C`to_json\*(C'\fR: expects a Unicode string and tries to parse it, returning the resulting reference. Croaks on error. .PP Basically, this function call is functionally identical to: .PP .Vb 1 \& $perl_scalar = JSON\->new\->decode($json_text) .Ve .PP You can pass an optional hash reference to modify its behavior, but that may change what \f(CW\*(C`from_json\*(C'\fR expects/generates (see \&\f(CW\*(C`ENCODING/CODESET FLAG NOTES\*(C'\fR for details). .PP .Vb 2 \& $perl_scalar = from_json($json_text, {utf8 => 1}) \& # => JSON\->new\->utf8(1)\->decode($json_text) .Ve .SS "JSON::is_bool" .IX Subsection "JSON::is_bool" .Vb 1 \& $is_boolean = JSON::is_bool($scalar) .Ve .PP Returns true if the passed scalar represents either JSON::true or JSON::false, two constants that act like \f(CW1\fR and \f(CW0\fR respectively and are also used to represent \s-1JSON\s0 \f(CW\*(C`true\*(C'\fR and \f(CW\*(C`false\*(C'\fR in Perl strings. .PP See \s-1MAPPING\s0, below, for more information on how \s-1JSON\s0 values are mapped to Perl. .SH "COMMON OBJECT-ORIENTED INTERFACE" .IX Header "COMMON OBJECT-ORIENTED INTERFACE" This section is also taken from \s-1JSON::XS.\s0 .PP The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. .SS "new" .IX Subsection "new" .Vb 1 \& $json = JSON\->new .Ve .PP Creates a new JSON::XS\-compatible backend object that can be used to de/encode \s-1JSON\s0 strings. All boolean flags described below are by default \fIdisabled\fR (with the exception of \f(CW\*(C`allow_nonref\*(C'\fR, which defaults to \fIenabled\fR since version \f(CW4.0\fR). .PP The mutators for flags all return the backend object again and thus calls can be chained: .PP .Vb 2 \& my $json = JSON\->new\->utf8\->space_after\->encode({a => [1,2]}) \& => {"a": [1, 2]} .Ve .SS "ascii" .IX Subsection "ascii" .Vb 1 \& $json = $json\->ascii([$enable]) \& \& $enabled = $json\->get_ascii .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not generate characters outside the code range \f(CW0..127\fR (which is \s-1ASCII\s0). Any Unicode characters outside that range will be escaped using either a single \euXXXX (\s-1BMP\s0 characters) or a double \euHHHH\euLLLLL escape sequence, as per \s-1RFC4627.\s0 The resulting encoded \s-1JSON\s0 text can be treated as a native Unicode string, an ascii-encoded, latin1\-encoded or \s-1UTF\-8\s0 encoded string, or any other superset of \s-1ASCII.\s0 .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. This results in a faster and more compact format. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP The main use for this flag is to produce \s-1JSON\s0 texts that can be transmitted over a 7\-bit channel, as the encoded \s-1JSON\s0 texts will not contain any 8 bit characters. .PP .Vb 2 \& JSON\->new\->ascii(1)\->encode([chr 0x10401]) \& => ["\eud801\eudc01"] .Ve .SS "latin1" .IX Subsection "latin1" .Vb 1 \& $json = $json\->latin1([$enable]) \& \& $enabled = $json\->get_latin1 .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the resulting \s-1JSON\s0 text as latin1 (or iso\-8859\-1), escaping any characters outside the code range \f(CW0..255\fR. The resulting string can be treated as a latin1\-encoded \s-1JSON\s0 text or a native Unicode string. The \f(CW\*(C`decode\*(C'\fR method will not be affected in any way by this flag, as \f(CW\*(C`decode\*(C'\fR by default expects Unicode, which is a strict superset of latin1. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP The main use for this flag is efficiently encoding binary data as \s-1JSON\s0 text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting \s-1JSON\s0 text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for \s-1JSON.\s0 It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other \s-1JSON\s0 encoders/decoders. .PP .Vb 2 \& JSON\->new\->latin1\->encode (["\ex{89}\ex{abc}"] \& => ["\ex{89}\e\eu0abc"] # (perl syntax, U+abc escaped, U+89 not) .Ve .SS "utf8" .IX Subsection "utf8" .Vb 1 \& $json = $json\->utf8([$enable]) \& \& $enabled = $json\->get_utf8 .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the \s-1JSON\s0 result into \s-1UTF\-8,\s0 as required by many protocols, while the \&\f(CW\*(C`decode\*(C'\fR method expects to be handled an UTF\-8\-encoded string. Please note that UTF\-8\-encoded strings do not contain any characters outside the range \f(CW0..255\fR, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the \s-1UTF\-16\s0 and \s-1UTF\-32\s0 encoding families, as described in \s-1RFC4627.\s0 .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will return the \s-1JSON\s0 string as a (non-encoded) Unicode string, while \f(CW\*(C`decode\*(C'\fR expects thus a Unicode string. Any decoding or encoding (e.g. to \s-1UTF\-8\s0 or \s-1UTF\-16\s0) needs to be done yourself, e.g. using the Encode module. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP Example, output UTF\-16BE\-encoded \s-1JSON:\s0 .PP .Vb 2 \& use Encode; \& $jsontext = encode "UTF\-16BE", JSON\->new\->encode ($object); .Ve .PP Example, decode UTF\-32LE\-encoded \s-1JSON:\s0 .PP .Vb 2 \& use Encode; \& $object = JSON\->new\->decode (decode "UTF\-32LE", $jsontext); .Ve .SS "pretty" .IX Subsection "pretty" .Vb 1 \& $json = $json\->pretty([$enable]) .Ve .PP This enables (or disables) all of the \f(CW\*(C`indent\*(C'\fR, \f(CW\*(C`space_before\*(C'\fR and \&\f(CW\*(C`space_after\*(C'\fR (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. .SS "indent" .IX Subsection "indent" .Vb 1 \& $json = $json\->indent([$enable]) \& \& $enabled = $json\->get_indent .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. .PP If \f(CW$enable\fR is false, no newlines or indenting will be produced, and the resulting \s-1JSON\s0 text is guaranteed not to contain any \f(CW\*(C`newlines\*(C'\fR. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .SS "space_before" .IX Subsection "space_before" .Vb 1 \& $json = $json\->space_before([$enable]) \& \& $enabled = $json\->get_space_before .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space before the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .PP This setting has no effect when decoding \s-1JSON\s0 texts. You will also most likely combine this setting with \f(CW\*(C`space_after\*(C'\fR. .PP Example, space_before enabled, space_after and indent disabled: .PP .Vb 1 \& {"key" :"value"} .Ve .SS "space_after" .IX Subsection "space_after" .Vb 1 \& $json = $json\->space_after([$enable]) \& \& $enabled = $json\->get_space_after .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space after the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects and extra whitespace after the \f(CW\*(C`,\*(C'\fR separating key-value pairs and array members. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP Example, space_before and indent disabled, space_after enabled: .PP .Vb 1 \& {"key": "value"} .Ve .SS "relaxed" .IX Subsection "relaxed" .Vb 1 \& $json = $json\->relaxed([$enable]) \& \& $enabled = $json\->get_relaxed .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept some extensions to normal \s-1JSON\s0 syntax (see below). \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \fIBe aware that this option makes you accept invalid \&\s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP Currently accepted extensions are: .IP "\(bu" 4 list items can have an end-comma .Sp \&\s-1JSON\s0 \fIseparates\fR array elements and key-value pairs with commas. This can be annoying if you write \s-1JSON\s0 texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: .Sp .Vb 8 \& [ \& 1, \& 2, <\- this comma not normally allowed \& ] \& { \& "k1": "v1", \& "k2": "v2", <\- this comma not normally allowed \& } .Ve .IP "\(bu" 4 shell-style '#'\-comments .Sp Whenever \s-1JSON\s0 allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, # this comment not allowed in JSON \& # neither this one... \& ] .Ve .SS "canonical" .IX Subsection "canonical" .Vb 1 \& $json = $json\->canonical([$enable]) \& \& $enabled = $json\->get_canonical .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will output \s-1JSON\s0 objects by sorting their keys. This is adding a comparatively high overhead. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). .PP This option is useful if you want the same data structure to be encoded as the same \s-1JSON\s0 text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP This setting has currently no effect on tied hashes. .SS "allow_nonref" .IX Subsection "allow_nonref" .Vb 1 \& $json = $json\->allow_nonref([$enable]) \& \& $enabled = $json\->get_allow_nonref .Ve .PP Unlike other boolean options, this option is enabled by default beginning with version \f(CW4.0\fR. .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method can convert a non-reference into its corresponding string, number or null \s-1JSON\s0 value, which is an extension to \s-1RFC4627.\s0 Likewise, \f(CW\*(C`decode\*(C'\fR will accept those \s-1JSON\s0 values instead of croaking. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will croak if it isn't passed an arrayref or hashref, as \s-1JSON\s0 texts must either be an object or array. Likewise, \f(CW\*(C`decode\*(C'\fR will croak if given something that is not a \&\s-1JSON\s0 object or array. .PP Example, encode a Perl scalar as \s-1JSON\s0 value with enabled \f(CW\*(C`allow_nonref\*(C'\fR, resulting in an invalid \s-1JSON\s0 text: .PP .Vb 2 \& JSON\->new\->allow_nonref\->encode ("Hello, World!") \& => "Hello, World!" .Ve .SS "allow_unknown" .IX Subsection "allow_unknown" .Vb 1 \& $json = $json\->allow_unknown ([$enable]) \& \& $enabled = $json\->get_allow_unknown .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR will \fInot\fR throw an exception when it encounters values it cannot represent in \s-1JSON\s0 (for example, filehandles) but instead will encode a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value. Note that blessed objects are not included here and are handled separately by c. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters anything it cannot encode as \s-1JSON.\s0 .PP This option does not affect \f(CW\*(C`decode\*(C'\fR in any way, and it is recommended to leave it off unless you know your communications partner. .SS "allow_blessed" .IX Subsection "allow_blessed" .Vb 1 \& $json = $json\->allow_blessed([$enable]) \& \& $enabled = $json\->get_allow_blessed .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value is encoded instead of the object. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters a blessed object that it cannot convert otherwise. .PP This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .SS "convert_blessed" .IX Subsection "convert_blessed" .Vb 1 \& $json = $json\->convert_blessed([$enable]) \& \& $enabled = $json\->get_convert_blessed .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`TO_JSON\*(C'\fR method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. .PP The \f(CW\*(C`TO_JSON\*(C'\fR method may safely call die if it wants. If \f(CW\*(C`TO_JSON\*(C'\fR returns other blessed objects, those will be handled in the same way. \f(CW\*(C`TO_JSON\*(C'\fR must take care of not causing an endless recursion cycle (== crash) in this case. The name of \f(CW\*(C`TO_JSON\*(C'\fR was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any \f(CW\*(C`to_json\*(C'\fR function or method. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion. .PP This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .SS "allow_tags (since version 3.0)" .IX Subsection "allow_tags (since version 3.0)" .Vb 1 \& $json = $json\->allow_tags([$enable]) \& \& $enabled = $json\->get_allow_tags .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`FREEZE\*(C'\fR method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged \s-1JSON\s0 value (that \s-1JSON\s0 decoders cannot decode). .PP It also causes \f(CW\*(C`decode\*(C'\fR to parse such tagged \s-1JSON\s0 values and deserialise them via a call to the \f(CW\*(C`THAW\*(C'\fR method. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion, and tagged \s-1JSON\s0 values will cause a parse error in \f(CW\*(C`decode\*(C'\fR, as if tags were not part of the grammar. .SS "boolean_values (since version 4.0)" .IX Subsection "boolean_values (since version 4.0)" .Vb 1 \& $json\->boolean_values([$false, $true]) \& \& ($false, $true) = $json\->get_boolean_values .Ve .PP By default, \s-1JSON\s0 booleans will be decoded as overloaded \&\f(CW$JSON::false\fR and \f(CW$JSON::true\fR objects. .PP With this method you can specify your own boolean values for decoding \- on decode, \s-1JSON\s0 \f(CW\*(C`false\*(C'\fR will be decoded as a copy of \f(CW$false\fR, and \s-1JSON\s0 \&\f(CW\*(C`true\*(C'\fR will be decoded as \f(CW$true\fR (\*(L"copy\*(R" here is the same thing as assigning a value to another variable, i.e. \f(CW\*(C`$copy = $false\*(C'\fR). .PP This is useful when you want to pass a decoded data structure directly to other serialisers like \s-1YAML,\s0 Data::MessagePack and so on. .PP Note that this works only when you \f(CW\*(C`decode\*(C'\fR. You can set incompatible boolean objects (like boolean), but when you \f(CW\*(C`encode\*(C'\fR a data structure with such boolean objects, you still need to enable \f(CW\*(C`convert_blessed\*(C'\fR (and add a \f(CW\*(C`TO_JSON\*(C'\fR method if necessary). .PP Calling this method without any arguments will reset the booleans to their default values. .PP \&\f(CW\*(C`get_boolean_values\*(C'\fR will return both \f(CW$false\fR and \f(CW$true\fR values, or the empty list when they are set to the default. .SS "filter_json_object" .IX Subsection "filter_json_object" .Vb 1 \& $json = $json\->filter_json_object([$coderef]) .Ve .PP When \f(CW$coderef\fR is specified, it will be called from \f(CW\*(C`decode\*(C'\fR each time it decodes a \s-1JSON\s0 object. The only argument is a reference to the newly-created hash. If the code references returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (\s-1NOTE:\s0 \fInot\fR \f(CW\*(C`undef\*(C'\fR, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. .PP When \f(CW$coderef\fR is omitted or undefined, any existing callback will be removed and \f(CW\*(C`decode\*(C'\fR will not change the deserialised hash in any way. .PP Example, convert all \s-1JSON\s0 objects into the integer 5: .PP .Vb 5 \& my $js = JSON\->new\->filter_json_object(sub { 5 }); \& # returns [5] \& $js\->decode(\*(Aq[{}]\*(Aq); \& # returns 5 \& $js\->decode(\*(Aq{"a":1, "b":2}\*(Aq); .Ve .SS "filter_json_single_key_object" .IX Subsection "filter_json_single_key_object" .Vb 1 \& $json = $json\->filter_json_single_key_object($key [=> $coderef]) .Ve .PP Works remotely similar to \f(CW\*(C`filter_json_object\*(C'\fR, but is only called for \&\s-1JSON\s0 objects having a single key named \f(CW$key\fR. .PP This \f(CW$coderef\fR is called before the one specified via \&\f(CW\*(C`filter_json_object\*(C'\fR, if any. It gets passed the single value in the \s-1JSON\s0 object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even \f(CW\*(C`undef\*(C'\fR but the empty list), the callback from \f(CW\*(C`filter_json_object\*(C'\fR will be called next, as if no single-key callback were specified. .PP If \f(CW$coderef\fR is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. .PP As this callback gets called less often then the \f(CW\*(C`filter_json_object\*(C'\fR one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key \s-1JSON\s0 objects are as close to the type-tagged value concept as \s-1JSON\s0 gets (it's basically an \s-1ID/VALUE\s0 tuple). Of course, \s-1JSON\s0 does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. .PP Typical names for the single object key are \f(CW\*(C`_\|_class_whatever_\|_\*(C'\fR, or \&\f(CW\*(C`$_\|_dollars_are_rarely_used_\|_$\*(C'\fR or \f(CW\*(C`}ugly_brace_placement\*(C'\fR, or even things like \f(CW\*(C`_\|_class_md5sum(classname)_\|_\*(C'\fR, to reduce the risk of clashing with real hashes. .PP Example, decode \s-1JSON\s0 objects of the form \f(CW\*(C`{ "_\|_widget_\|_" => }\*(C'\fR into the corresponding \f(CW$WIDGET{}\fR object: .PP .Vb 7 \& # return whatever is in $WIDGET{5}: \& JSON \& \->new \& \->filter_json_single_key_object (_\|_widget_\|_ => sub { \& $WIDGET{ $_[0] } \& }) \& \->decode (\*(Aq{"_\|_widget_\|_": 5\*(Aq) \& \& # this can be used with a TO_JSON method in some "widget" class \& # for serialisation to json: \& sub WidgetBase::TO_JSON { \& my ($self) = @_; \& \& unless ($self\->{id}) { \& $self\->{id} = ..get..some..id..; \& $WIDGET{$self\->{id}} = $self; \& } \& \& { _\|_widget_\|_ => $self\->{id} } \& } .Ve .SS "max_depth" .IX Subsection "max_depth" .Vb 1 \& $json = $json\->max_depth([$maximum_nesting_depth]) \& \& $max_depth = $json\->get_max_depth .Ve .PP Sets the maximum nesting level (default \f(CW512\fR) accepted while encoding or decoding. If a higher nesting level is detected in \s-1JSON\s0 text or a Perl data structure, then the encoder and decoder will stop and croak at that point. .PP Nesting level is defined by number of hash\- or arrayrefs that the encoder needs to traverse to reach a given point or the number of \f(CW\*(C`{\*(C'\fR or \f(CW\*(C`[\*(C'\fR characters without their matching closing parenthesis crossed to reach a given character in a string. .PP Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. .PP If no argument is given, the highest possible setting will be used, which is rarely useful. .PP See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 in \s-1JSON::XS\s0 for more info on why this is useful. .SS "max_size" .IX Subsection "max_size" .Vb 1 \& $json = $json\->max_size([$maximum_string_size]) \& \& $max_size = $json\->get_max_size .Ve .PP Set the maximum length a \s-1JSON\s0 text may have (in bytes) where decoding is being attempted. The default is \f(CW0\fR, meaning no limit. When \f(CW\*(C`decode\*(C'\fR is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on \f(CW\*(C`encode\*(C'\fR (yet). .PP If no argument is given, the limit check will be deactivated (same as when \&\f(CW0\fR is specified). .PP See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 in \s-1JSON::XS\s0 for more info on why this is useful. .SS "encode" .IX Subsection "encode" .Vb 1 \& $json_text = $json\->encode($perl_scalar) .Ve .PP Converts the given Perl value or data structure to its \s-1JSON\s0 representation. Croaks on error. .SS "decode" .IX Subsection "decode" .Vb 1 \& $perl_scalar = $json\->decode($json_text) .Ve .PP The opposite of \f(CW\*(C`encode\*(C'\fR: expects a \s-1JSON\s0 text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. .SS "decode_prefix" .IX Subsection "decode_prefix" .Vb 1 \& ($perl_scalar, $characters) = $json\->decode_prefix($json_text) .Ve .PP This works like the \f(CW\*(C`decode\*(C'\fR method, but instead of raising an exception when there is trailing garbage after the first \s-1JSON\s0 object, it will silently stop parsing there and return the number of characters consumed so far. .PP This is useful if your \s-1JSON\s0 texts are not delimited by an outer protocol and you need to know where the \s-1JSON\s0 text ends. .PP .Vb 2 \& JSON\->new\->decode_prefix ("[1] the tail") \& => ([1], 3) .Ve .SH "ADDITIONAL METHODS" .IX Header "ADDITIONAL METHODS" The following methods are for this module only. .SS "backend" .IX Subsection "backend" .Vb 1 \& $backend = $json\->backend .Ve .PP Since 2.92, \f(CW\*(C`backend\*(C'\fR method returns an abstract backend module used currently, which should be JSON::Backend::XS (which inherits \s-1JSON::XS\s0 or Cpanel::JSON::XS), or JSON::Backend::PP (which inherits \s-1JSON::PP\s0), not to monkey-patch the actual backend module globally. .PP If you need to know what is used actually, use \f(CW\*(C`isa\*(C'\fR, instead of string comparison. .SS "is_xs" .IX Subsection "is_xs" .Vb 1 \& $boolean = $json\->is_xs .Ve .PP Returns true if the backend inherits \s-1JSON::XS\s0 or Cpanel::JSON::XS. .SS "is_pp" .IX Subsection "is_pp" .Vb 1 \& $boolean = $json\->is_pp .Ve .PP Returns true if the backend inherits \s-1JSON::PP.\s0 .SS "property" .IX Subsection "property" .Vb 1 \& $settings = $json\->property() .Ve .PP Returns a reference to a hash that holds all the common flag settings. .PP .Vb 2 \& $json = $json\->property(\*(Aqutf8\*(Aq => 1) \& $value = $json\->property(\*(Aqutf8\*(Aq) # 1 .Ve .PP You can use this to get/set a value of a particular flag. .SS "boolean" .IX Subsection "boolean" .Vb 1 \& $boolean_object = JSON\->boolean($scalar) .Ve .PP Returns \f(CW$JSON::true\fR if \f(CW$scalar\fR contains a true value, \f(CW$JSON::false\fR otherwise. You can use this as a full-qualified function (\f(CW\*(C`JSON::boolean($scalar)\*(C'\fR). .SH "INCREMENTAL PARSING" .IX Header "INCREMENTAL PARSING" This section is also taken from \s-1JSON::XS.\s0 .PP In some cases, there is the need for incremental parsing of \s-1JSON\s0 texts. While this module always has to keep both \s-1JSON\s0 text and resulting Perl data structure in memory at one time, it does allow you to parse a \&\s-1JSON\s0 stream incrementally. It does so by accumulating text until it has a full \s-1JSON\s0 object, which it then can decode. This process is similar to using \f(CW\*(C`decode_prefix\*(C'\fR to see if a full \s-1JSON\s0 object is available, but is much more efficient (and can be implemented with a minimum of method calls). .PP This module will only attempt to parse the \s-1JSON\s0 text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid \s-1JSON\s0 text has been seen. This means you need to set resource limits (e.g. \f(CW\*(C`max_size\*(C'\fR) to ensure the parser will stop parsing in the presence if syntax errors. .PP The following methods implement this incremental parser. .SS "incr_parse" .IX Subsection "incr_parse" .Vb 1 \& $json\->incr_parse( [$string] ) # void context \& \& $obj_or_undef = $json\->incr_parse( [$string] ) # scalar context \& \& @obj_or_empty = $json\->incr_parse( [$string] ) # list context .Ve .PP This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). .PP If \f(CW$string\fR is given, then this string is appended to the already existing \s-1JSON\s0 fragment stored in the \f(CW$json\fR object. .PP After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. .PP If the method is called in scalar context, then it will try to extract exactly \fIone\fR \s-1JSON\s0 object. If that is successful, it will return this object, otherwise it will return \f(CW\*(C`undef\*(C'\fR. If there is a parse error, this method will croak just as \f(CW\*(C`decode\*(C'\fR would do (one can then use \&\f(CW\*(C`incr_skip\*(C'\fR to skip the erroneous part). This is the most common way of using the method. .PP And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the \s-1JSON\s0 objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed \s-1JSON\s0 texts will be lost. .PP Example: Parse some \s-1JSON\s0 arrays/objects in a given string and return them. .PP .Vb 1 \& my @objs = JSON\->new\->incr_parse ("[5][7][1,2]"); .Ve .SS "incr_text" .IX Subsection "incr_text" .Vb 1 \& $lvalue_string = $json\->incr_text .Ve .PP This method returns the currently stored \s-1JSON\s0 fragment as an lvalue, that is, you can manipulate it. This \fIonly\fR works when a preceding call to \&\f(CW\*(C`incr_parse\*(C'\fR in \fIscalar context\fR successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it \fIwill\fR fail under real world conditions). As a special exception, you can also call this method before having parsed anything. .PP That means you can only use this function to look at or manipulate text before or after complete \s-1JSON\s0 objects, not while the parser is in the middle of parsing a \s-1JSON\s0 object. .PP This function is useful in two cases: a) finding the trailing text after a \&\s-1JSON\s0 object or b) parsing multiple \s-1JSON\s0 objects separated by non-JSON text (such as commas). .SS "incr_skip" .IX Subsection "incr_skip" .Vb 1 \& $json\->incr_skip .Ve .PP This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after \&\f(CW\*(C`incr_parse\*(C'\fR died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. .PP The difference to \f(CW\*(C`incr_reset\*(C'\fR is that only text until the parse error occurred is removed. .SS "incr_reset" .IX Subsection "incr_reset" .Vb 1 \& $json\->incr_reset .Ve .PP This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. .PP This is useful if you want to repeatedly parse \s-1JSON\s0 objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. .SH "MAPPING" .IX Header "MAPPING" Most of this section is also taken from \s-1JSON::XS.\s0 .PP This section describes how the backend modules map Perl values to \s-1JSON\s0 values and vice versa. These mappings are designed to \*(L"do the right thing\*(R" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). .PP For the more enlightened: note that in the following descriptions, lowercase \fIperl\fR refers to the Perl interpreter, while uppercase \fIPerl\fR refers to the abstract Perl language itself. .SS "\s-1JSON\s0 \-> \s-1PERL\s0" .IX Subsection "JSON -> PERL" .IP "object" 4 .IX Item "object" A \s-1JSON\s0 object becomes a reference to a hash in Perl. No ordering of object keys is preserved (\s-1JSON\s0 does not preserver object key ordering itself). .IP "array" 4 .IX Item "array" A \s-1JSON\s0 array becomes a reference to an array in Perl. .IP "string" 4 .IX Item "string" A \s-1JSON\s0 string becomes a string scalar in Perl \- Unicode codepoints in \s-1JSON\s0 are represented by the same codepoints in the Perl string, so no manual decoding is necessary. .IP "number" 4 .IX Item "number" A \s-1JSON\s0 number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. .Sp If the number consists of digits only, this module will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the \s-1JSON\s0 number will be re-encoded to a \s-1JSON\s0 string). .Sp Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the \s-1JSON\s0 number will still be re-encoded as a \s-1JSON\s0 number). .Sp Note that precision is not accuracy \- binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, this module only guarantees precision up to but not including the least significant bit. .IP "true, false" 4 .IX Item "true, false" These \s-1JSON\s0 atoms become \f(CW\*(C`JSON::true\*(C'\fR and \f(CW\*(C`JSON::false\*(C'\fR, respectively. They are overloaded to act almost exactly like the numbers \&\f(CW1\fR and \f(CW0\fR. You can check whether a scalar is a \s-1JSON\s0 boolean by using the \f(CW\*(C`JSON::is_bool\*(C'\fR function. .IP "null" 4 .IX Item "null" A \s-1JSON\s0 null atom becomes \f(CW\*(C`undef\*(C'\fR in Perl. .ie n .IP "shell-style comments (""# \fItext\fP"")" 4 .el .IP "shell-style comments (\f(CW# \f(CItext\f(CW\fR)" 4 .IX Item "shell-style comments (# text)" As a nonstandard extension to the \s-1JSON\s0 syntax that is enabled by the \&\f(CW\*(C`relaxed\*(C'\fR setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. .ie n .IP "tagged values (""(\fItag\fP)\fIvalue\fP"")." 4 .el .IP "tagged values (\f(CW(\f(CItag\f(CW)\f(CIvalue\f(CW\fR)." 4 .IX Item "tagged values ((tag)value)." Another nonstandard extension to the \s-1JSON\s0 syntax, enabled with the \&\f(CW\*(C`allow_tags\*(C'\fR setting, are tagged values. In this implementation, the \&\fItag\fR must be a perl package/class name encoded as a \s-1JSON\s0 string, and the \&\fIvalue\fR must be a \s-1JSON\s0 array encoding optional constructor arguments. .Sp See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .SS "\s-1PERL\s0 \-> \s-1JSON\s0" .IX Subsection "PERL -> JSON" The mapping from Perl to \s-1JSON\s0 is slightly more difficult, as Perl is a truly typeless language, so we can only guess which \s-1JSON\s0 type is meant by a Perl value. .IP "hash references" 4 .IX Item "hash references" Perl hash references become \s-1JSON\s0 objects. As there is no inherent ordering in hash keys (or \s-1JSON\s0 objects), they will usually be encoded in a pseudo-random order. This module can optionally sort the hash keys (determined by the \fIcanonical\fR flag), so the same data structure will serialise to the same \s-1JSON\s0 text (given same settings and version of the same backend), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some \s-1JSON\s0 text against another for equality. .IP "array references" 4 .IX Item "array references" Perl array references become \s-1JSON\s0 arrays. .IP "other references" 4 .IX Item "other references" Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers \f(CW0\fR and \&\f(CW1\fR, which get turned into \f(CW\*(C`false\*(C'\fR and \f(CW\*(C`true\*(C'\fR atoms in \s-1JSON.\s0 You can also use \f(CW\*(C`JSON::false\*(C'\fR and \f(CW\*(C`JSON::true\*(C'\fR to improve readability. .Sp .Vb 1 \& encode_json [\e0,JSON::true] # yields [false,true] .Ve .IP "JSON::true, JSON::false, JSON::null" 4 .IX Item "JSON::true, JSON::false, JSON::null" These special values become \s-1JSON\s0 true and \s-1JSON\s0 false values, respectively. You can also use \f(CW\*(C`\e1\*(C'\fR and \f(CW\*(C`\e0\*(C'\fR directly if you want. .IP "blessed objects" 4 .IX Item "blessed objects" Blessed objects are not directly representable in \s-1JSON,\s0 but \f(CW\*(C`JSON::XS\*(C'\fR allows various ways of handling objects. See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .IP "simple scalars" 4 .IX Item "simple scalars" Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: this module will encode undefined scalars as \&\s-1JSON\s0 \f(CW\*(C`null\*(C'\fR values, scalars that have last been used in a string context before encoding as \s-1JSON\s0 strings, and anything else as number value: .Sp .Vb 4 \& # dump as number \& encode_json [2] # yields [2] \& encode_json [\-3.0e17] # yields [\-3e+17] \& my $value = 5; encode_json [$value] # yields [5] \& \& # used as string, so dump as string \& print $value; \& encode_json [$value] # yields ["5"] \& \& # undef becomes null \& encode_json [undef] # yields [null] .Ve .Sp You can force the type to be a string by stringifying it: .Sp .Vb 4 \& my $x = 3.1; # some variable containing a number \& "$x"; # stringified \& $x .= ""; # another, more awkward way to stringify \& print $x; # perl does it for you, too, quite often .Ve .Sp You can force the type to be a number by numifying it: .Sp .Vb 3 \& my $x = "3"; # some variable containing a string \& $x += 0; # numify it, ensuring it will be dumped as a number \& $x *= 1; # same thing, the choice is yours. .Ve .Sp You can not currently force the type in other, less obscure, ways. Tell me if you need this capability (but don't forget to explain why it's needed :). .Sp Since version 2.91_01, \s-1JSON::PP\s0 uses a different number detection logic that converts a scalar that is possible to turn into a number safely. The new logic is slightly faster, and tends to help people who use older perl or who want to encode complicated data structure. However, this may results in a different \s-1JSON\s0 text from the one \s-1JSON::XS\s0 encodes (and thus may break tests that compare entire \s-1JSON\s0 texts). If you do need the previous behavior for better compatibility or for finer control, set \s-1PERL_JSON_PP_USE_B\s0 environmental variable to true before you \&\f(CW\*(C`use\*(C'\fR \s-1JSON.\s0 .Sp Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's \- these cannot be represented in \s-1JSON,\s0 and it is an error to pass those in. .Sp \&\s-1JSON\s0.pm backend modules trust what you pass to \f(CW\*(C`encode\*(C'\fR method (or \f(CW\*(C`encode_json\*(C'\fR function) is a clean, validated data structure with values that can be represented as valid \s-1JSON\s0 values only, because it's not from an external data source (as opposed to \s-1JSON\s0 texts you pass to \&\f(CW\*(C`decode\*(C'\fR or \f(CW\*(C`decode_json\*(C'\fR, which \s-1JSON\s0 backends consider tainted and don't trust). As \s-1JSON\s0 backends don't know exactly what you and consumers of your \s-1JSON\s0 texts want the unexpected values to be (you may want to convert them into null, or to stringify them with or without normalisation (string representation of infinities/NaN may vary depending on platforms), or to croak without conversion), you're advised to do what you and your consumers need before you encode, and also not to numify values that may start with values that look like a number (including infinities/NaN), without validating. .SS "\s-1OBJECT SERIALISATION\s0" .IX Subsection "OBJECT SERIALISATION" As \s-1JSON\s0 cannot directly represent Perl objects, you have to choose between a pure \s-1JSON\s0 representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the \s-1JSON\s0 syntax, tagged values. .PP \fI\s-1SERIALISATION\s0\fR .IX Subsection "SERIALISATION" .PP What happens when this module encounters a Perl object depends on the \&\f(CW\*(C`allow_blessed\*(C'\fR, \f(CW\*(C`convert_blessed\*(C'\fR and \f(CW\*(C`allow_tags\*(C'\fR settings, which are used in this order: .ie n .IP "1. ""allow_tags"" is enabled and the object has a ""FREEZE"" method." 4 .el .IP "1. \f(CWallow_tags\fR is enabled and the object has a \f(CWFREEZE\fR method." 4 .IX Item "1. allow_tags is enabled and the object has a FREEZE method." In this case, \f(CW\*(C`JSON\*(C'\fR creates a tagged \s-1JSON\s0 value, using a nonstandard extension to the \s-1JSON\s0 syntax. .Sp This works by invoking the \f(CW\*(C`FREEZE\*(C'\fR method on the object, with the first argument being the object to serialise, and the second argument being the constant string \f(CW\*(C`JSON\*(C'\fR to distinguish it from other serialisers. .Sp The \f(CW\*(C`FREEZE\*(C'\fR method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged \s-1JSON\s0 value in the following format: .Sp .Vb 1 \& ("classname")[FREEZE return values...] .Ve .Sp e.g.: .Sp .Vb 3 \& ("URI")["http://www.google.com/"] \& ("MyDate")[2013,10,29] \& ("ImageData::JPEG")["Z3...VlCg=="] .Ve .Sp For example, the hypothetical \f(CW\*(C`My::Object\*(C'\fR \f(CW\*(C`FREEZE\*(C'\fR method might use the objects \f(CW\*(C`type\*(C'\fR and \f(CW\*(C`id\*(C'\fR members to encode the object: .Sp .Vb 2 \& sub My::Object::FREEZE { \& my ($self, $serialiser) = @_; \& \& ($self\->{type}, $self\->{id}) \& } .Ve .ie n .IP "2. ""convert_blessed"" is enabled and the object has a ""TO_JSON"" method." 4 .el .IP "2. \f(CWconvert_blessed\fR is enabled and the object has a \f(CWTO_JSON\fR method." 4 .IX Item "2. convert_blessed is enabled and the object has a TO_JSON method." In this case, the \f(CW\*(C`TO_JSON\*(C'\fR method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into \&\s-1JSON.\s0 This scalar replaces the object in the \s-1JSON\s0 text. .Sp For example, the following \f(CW\*(C`TO_JSON\*(C'\fR method will convert all \s-1URI\s0 objects to \s-1JSON\s0 strings when serialised. The fact that these values originally were \s-1URI\s0 objects is lost. .Sp .Vb 4 \& sub URI::TO_JSON { \& my ($uri) = @_; \& $uri\->as_string \& } .Ve .ie n .IP "3. ""allow_blessed"" is enabled." 4 .el .IP "3. \f(CWallow_blessed\fR is enabled." 4 .IX Item "3. allow_blessed is enabled." The object will be serialised as a \s-1JSON\s0 null value. .IP "4. none of the above" 4 .IX Item "4. none of the above" If none of the settings are enabled or the respective methods are missing, this module throws an exception. .PP \fI\s-1DESERIALISATION\s0\fR .IX Subsection "DESERIALISATION" .PP For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case \f(CW\*(C`allow_tags\*(C'\fR decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the \f(CW\*(C`filter_json_object\*(C'\fR or \&\f(CW\*(C`filter_json_single_key_object\*(C'\fR callbacks to get some real objects our of your \s-1JSON.\s0 .PP This section only considers the tagged value case: a tagged \s-1JSON\s0 object is encountered during decoding and \f(CW\*(C`allow_tags\*(C'\fR is disabled, a parse error will result (as if tagged values were not part of the grammar). .PP If \f(CW\*(C`allow_tags\*(C'\fR is enabled, this module will look up the \f(CW\*(C`THAW\*(C'\fR method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. .PP Otherwise, the \f(CW\*(C`THAW\*(C'\fR method is invoked with the classname as first argument, the constant string \f(CW\*(C`JSON\*(C'\fR as second argument, and all the values from the \s-1JSON\s0 array (the values originally returned by the \&\f(CW\*(C`FREEZE\*(C'\fR method) as remaining arguments. .PP The method must then return the object. While technically you can return any Perl scalar, you might have to enable the \f(CW\*(C`allow_nonref\*(C'\fR setting to make that work in all cases, so better return an actual blessed reference. .PP As an example, let's implement a \f(CW\*(C`THAW\*(C'\fR function that regenerates the \&\f(CW\*(C`My::Object\*(C'\fR from the \f(CW\*(C`FREEZE\*(C'\fR example earlier: .PP .Vb 2 \& sub My::Object::THAW { \& my ($class, $serialiser, $type, $id) = @_; \& \& $class\->new (type => $type, id => $id) \& } .Ve .SH "ENCODING/CODESET FLAG NOTES" .IX Header "ENCODING/CODESET FLAG NOTES" This section is taken from \s-1JSON::XS.\s0 .PP The interested reader might have seen a number of flags that signify encodings or codesets \- \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR. There seems to be some confusion on what these do, so here is a short comparison: .PP \&\f(CW\*(C`utf8\*(C'\fR controls whether the \s-1JSON\s0 text created by \f(CW\*(C`encode\*(C'\fR (and expected by \f(CW\*(C`decode\*(C'\fR) is \s-1UTF\-8\s0 encoded or not, while \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR only control whether \f(CW\*(C`encode\*(C'\fR escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. .PP Care has been taken to make all flags symmetrical with respect to \&\f(CW\*(C`encode\*(C'\fR and \f(CW\*(C`decode\*(C'\fR, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used \&\- in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. .PP Below comes a verbose discussion of these flags. Note that a \*(L"codeset\*(R" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and \fIencodes\fR them, in our case into octets. Unicode is (among other things) a codeset, \s-1UTF\-8\s0 is an encoding, and \s-1ISO\-8859\-1\s0 (= latin 1) and \s-1ASCII\s0 are both codesets \fIand\fR encodings at the same time, which can be confusing. .ie n .IP """utf8"" flag disabled" 4 .el .IP "\f(CWutf8\fR flag disabled" 4 .IX Item "utf8 flag disabled" When \f(CW\*(C`utf8\*(C'\fR is disabled (the default), then \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except \&\*(L"(re\-)interpreting\*(R" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). .Sp This is useful when you want to do the encoding yourself (e.g. when you want to have \s-1UTF\-16\s0 encoded \s-1JSON\s0 texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to \s-1UTF\-8\s0 you certainly do \s-1NOT\s0 want to \s-1UTF\-8\s0 encode your data first and have Perl encode it another time). .ie n .IP """utf8"" flag enabled" 4 .el .IP "\f(CWutf8\fR flag enabled" 4 .IX Item "utf8 flag enabled" If the \f(CW\*(C`utf8\*(C'\fR\-flag is enabled, \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR will encode all characters using the corresponding \s-1UTF\-8\s0 multi-byte sequence, and will expect your input strings to be encoded as \s-1UTF\-8,\s0 that is, no \*(L"character\*(R" of the input string must have any value > 255, as \s-1UTF\-8\s0 does not allow that. .Sp The \f(CW\*(C`utf8\*(C'\fR flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get an \s-1UTF\-8\s0 encoded octet/binary string in Perl. .ie n .IP """latin1"" or ""ascii"" flags enabled" 4 .el .IP "\f(CWlatin1\fR or \f(CWascii\fR flags enabled" 4 .IX Item "latin1 or ascii flags enabled" With \f(CW\*(C`latin1\*(C'\fR (or \f(CW\*(C`ascii\*(C'\fR) enabled, \f(CW\*(C`encode\*(C'\fR will escape characters with ordinal values > 255 (> 127 with \f(CW\*(C`ascii\*(C'\fR) and encode the remaining characters as specified by the \f(CW\*(C`utf8\*(C'\fR flag. .Sp If \f(CW\*(C`utf8\*(C'\fR is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a \&\s-1ISO\-8859\-1\s0 string, and a Unicode string with all character values < 128 is the same thing as an \s-1ASCII\s0 string in Perl). .Sp If \f(CW\*(C`utf8\*(C'\fR is enabled, you still get a correct UTF\-8\-encoded string, regardless of these flags, just some more characters will be escaped using \&\f(CW\*(C`\euXXXX\*(C'\fR then before. .Sp Note that \s-1ISO\-8859\-1\-\s0\fIencoded\fR strings are not compatible with \s-1UTF\-8\s0 encoding, while ASCII-encoded strings are. That is because the \s-1ISO\-8859\-1\s0 encoding is \s-1NOT\s0 a subset of \s-1UTF\-8\s0 (despite the \s-1ISO\-8859\-1\s0 \fIcodeset\fR being a subset of Unicode), while \s-1ASCII\s0 is. .Sp Surprisingly, \f(CW\*(C`decode\*(C'\fR will ignore these flags and so treat all input values as governed by the \f(CW\*(C`utf8\*(C'\fR flag. If it is disabled, this allows you to decode \s-1ISO\-8859\-1\-\s0 and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode \s-1UTF\-8\s0 encoded strings. .Sp So neither \f(CW\*(C`latin1\*(C'\fR nor \f(CW\*(C`ascii\*(C'\fR are incompatible with the \f(CW\*(C`utf8\*(C'\fR flag \- they only govern when the \s-1JSON\s0 output engine escapes a character or not. .Sp The main use for \f(CW\*(C`latin1\*(C'\fR is to relatively efficiently store binary data as \s-1JSON,\s0 at the expense of breaking compatibility with most \s-1JSON\s0 decoders. .Sp The main use for \f(CW\*(C`ascii\*(C'\fR is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as \s-1UTF\-8, ISO\-8859\-1, ASCII, KOI8\-R\s0 or most about any character set and 8\-bit\-encoding, and still get the same data structure back. This is useful when your channel for \s-1JSON\s0 transfer is not 8\-bit clean or the encoding might be mangled in between (e.g. in mail), and works because \s-1ASCII\s0 is a proper subset of most 8\-bit and multibyte encodings in use in the world. .SH "BACKWARD INCOMPATIBILITY" .IX Header "BACKWARD INCOMPATIBILITY" Since version 2.90, stringification (and string comparison) for \&\f(CW\*(C`JSON::true\*(C'\fR and \f(CW\*(C`JSON::false\*(C'\fR has not been overloaded. It shouldn't matter as long as you treat them as boolean values, but a code that expects they are stringified as \*(L"true\*(R" or \*(L"false\*(R" doesn't work as you have expected any more. .PP .Vb 1 \& if (JSON::true eq \*(Aqtrue\*(Aq) { # now fails \& \& print "The result is $JSON::true now."; # => The result is 1 now. .Ve .PP And now these boolean values don't inherit JSON::Boolean, either. When you need to test a value is a \s-1JSON\s0 boolean value or not, use \&\f(CW\*(C`JSON::is_bool\*(C'\fR function, instead of testing the value inherits a particular boolean class or not. .SH "BUGS" .IX Header "BUGS" Please report bugs on backend selection and additional features this module provides to \s-1RT\s0 or GitHub issues for this module: .PP .PP .PP As for bugs on a specific behavior, please report to the author of the backend module you are using. .PP As for new features and requests to change common behaviors, please ask the author of \s-1JSON::XS\s0 (Marc Lehmann, ) first, by email (important!), to keep compatibility among \s-1JSON\s0.pm backends. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1JSON::XS\s0, Cpanel::JSON::XS, \s-1JSON::PP\s0 for backends. .PP JSON::MaybeXS, an alternative that prefers Cpanel::JSON::XS. .PP \&\f(CW\*(C`RFC4627\*(C'\fR() .PP \&\s-1RFC7159\s0 () .PP \&\s-1RFC8259\s0 () .SH "AUTHOR" .IX Header "AUTHOR" Makamaka Hannyaharamitu, .PP \&\s-1JSON::XS\s0 was written by Marc Lehmann .PP The release of this new version owes to the courtesy of Marc Lehmann. .SH "CURRENT MAINTAINER" .IX Header "CURRENT MAINTAINER" Kenichi Ishigaki, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2005\-2013 by Makamaka Hannyaharamitu .PP Most of the documentation is taken from \s-1JSON::XS\s0 by Marc Lehmann .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/LWP::MemberMixin.3pm000044400000005663152462503210011571 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::MemberMixin 3" .TH LWP::MemberMixin 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::MemberMixin \- Member access mixin class .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& package Foo; \& use parent qw(LWP::MemberMixin); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" A mixin class to get methods that provide easy access to member variables in the \f(CW%$self\fR. Ideally there should be better Perl language support for this. .SH "METHODS" .IX Header "METHODS" There is only one method provided: .SS "_elem" .IX Subsection "_elem" .Vb 1 \& _elem($elem [, $val]) .Ve .PP Internal method to get/set the value of member variable \&\f(CW$elem\fR. If \f(CW$val\fR is present it is used as the new value for the member variable. If it is not present the current value is not touched. In both cases the previous value of the member variable is returned. man/man3/DBI::Gofer::Execute.3pm000044400000022766152462503210012065 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Execute 3" .TH DBI::Gofer::Execute 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Execute \- Executes Gofer requests and returns Gofer responses .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $executor = DBI::Gofer::Execute\->new( { ...config... }); \& \& $response = $executor\->execute_request( $request ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Accepts a DBI::Gofer::Request object, executes the requested \s-1DBI\s0 method calls, and returns a DBI::Gofer::Response object. .PP Any error, including any internal 'fatal' errors are caught and converted into a DBI::Gofer::Response object. .PP This module is usually invoked by a 'server\-side' Gofer transport module. They usually have names in the "\f(CW\*(C`DBI::Gofer::Transport::*\*(C'\fR" namespace. Examples include: DBI::Gofer::Transport::stream and DBI::Gofer::Transport::mod_perl. .SH "CONFIGURATION" .IX Header "CONFIGURATION" .SS "check_request_sub" .IX Subsection "check_request_sub" If defined, it must be a reference to a subroutine that will 'check' the request. It is passed the request object and the executor as its only arguments. .PP The subroutine can either return the original request object or die with a suitable error message (which will be turned into a Gofer response). .PP It can also construct and return a new request that should be executed instead of the original request. .SS "check_response_sub" .IX Subsection "check_response_sub" If defined, it must be a reference to a subroutine that will 'check' the response. It is passed the response object, the executor, and the request object. The sub may alter the response object and return undef, or return a new response object. .PP This mechanism can be used to, for example, terminate the service if specific database errors are seen. .SS "forced_connect_dsn" .IX Subsection "forced_connect_dsn" If set, this \s-1DSN\s0 is always used instead of the one in the request. .SS "default_connect_dsn" .IX Subsection "default_connect_dsn" If set, this \s-1DSN\s0 is used if \f(CW\*(C`forced_connect_dsn\*(C'\fR is not set and the request does not contain a \s-1DSN\s0 itself. .SS "forced_connect_attributes" .IX Subsection "forced_connect_attributes" A reference to a hash of \fBconnect()\fR attributes. Individual attributes in \&\f(CW\*(C`forced_connect_attributes\*(C'\fR will take precedence over corresponding attributes in the request. .SS "default_connect_attributes" .IX Subsection "default_connect_attributes" A reference to a hash of \fBconnect()\fR attributes. Individual attributes in the request take precedence over corresponding attributes in \f(CW\*(C`default_connect_attributes\*(C'\fR. .SS "max_cached_dbh_per_drh" .IX Subsection "max_cached_dbh_per_drh" If set, the loaded drivers will be checked to ensure they don't have more than this number of cached connections. There is no default value. This limit is not enforced for every request. .SS "max_cached_sth_per_dbh" .IX Subsection "max_cached_sth_per_dbh" If set, all the cached statement handles will be cleared once the number of cached statement handles rises above this limit. The default is 1000. .SS "forced_single_resultset" .IX Subsection "forced_single_resultset" If true, then only the first result set will be fetched and returned in the response. .SS "forced_response_attributes" .IX Subsection "forced_response_attributes" A reference to a data structure that can specify extra attributes to be returned in responses. .PP .Vb 6 \& forced_response_attributes => { \& DriverName => { \& dbh => [ qw(dbh_attrib_name) ], \& sth => [ qw(sth_attrib_name) ], \& }, \& }, .Ve .PP This can be useful in cases where the driver has not implemented the \&\fBprivate_attribute_info()\fR method and DBI::Gofer::Execute's own fallback list of private attributes doesn't include the driver or attributes you need. .SS "track_recent" .IX Subsection "track_recent" If set, specifies the number of recent requests and responses that should be kept by the \fBupdate_stats()\fR method for diagnostics. See DBI::Gofer::Transport::mod_perl. .PP Note that this setting can significantly increase memory use. Use with caution. .SS "forced_gofer_random" .IX Subsection "forced_gofer_random" Enable forced random failures and/or delays for testing. See \*(L"\s-1DBI_GOFER_RANDOM\*(R"\s0 below. .SH "DRIVER-SPECIFIC ISSUES" .IX Header "DRIVER-SPECIFIC ISSUES" Gofer needs to know about any driver-private attributes that should have their values sent back to the client. .PP If the driver doesn't support \fBprivate_attribute_info()\fR method, and very few do, then the module fallsback to using some hard-coded details, if available, for the driver being used. Currently hard-coded details are available for the mysql, Pg, Sybase, and SQLite drivers. .SH "TESTING" .IX Header "TESTING" DBD::Gofer, DBD::Execute and related packages are well tested by executing the \&\s-1DBI\s0 test suite with \s-1DBI_AUTOPROXY\s0 configured to route all \s-1DBI\s0 calls via DBD::Gofer. .PP Because Gofer includes timeout and 'retry on error' mechanisms there is a need for some way to trigger delays and/or errors. This can be done via the \&\f(CW\*(C`forced_gofer_random\*(C'\fR configuration item, or else the \s-1DBI_GOFER_RANDOM\s0 environment variable. .SS "\s-1DBI_GOFER_RANDOM\s0" .IX Subsection "DBI_GOFER_RANDOM" The value of the \f(CW\*(C`forced_gofer_random\*(C'\fR configuration item (or else the \&\s-1DBI_GOFER_RANDOM\s0 environment variable) is treated as a series of tokens separated by commas. .PP The tokens can be one of three types: .IP "fail=R%" 4 .IX Item "fail=R%" Set the current failure rate to R where R is a percentage. The value R can be floating point, e.g., \f(CW\*(C`fail=0.05%\*(C'\fR. Negative values for R have special meaning, see below. .IP "err=N" 4 .IX Item "err=N" Sets the current failure err value to N (instead of the \s-1DBI\s0's default 'standard err value' of 2000000000). This is useful when you want to simulate a specific error. .IP "delayN=R%" 4 .IX Item "delayN=R%" Set the current random delay rate to R where R is a percentage, and set the current delay duration to N seconds. The values of R and N can be floating point, e.g., \f(CW\*(C`delay0.5=0.2%\*(C'\fR. Negative values for R have special meaning, see below. .Sp If R is an odd number (R % 2 == 1) then a message is logged via \fBwarn()\fR which will be returned to, and echoed at, the client. .IP "methodname" 4 .IX Item "methodname" Applies the current fail, err, and delay values to the named method. If neither a fail nor delay have been set yet then a warning is generated. .PP For example: .PP .Vb 3 \& $executor = DBI::Gofer::Execute\->new( { \& forced_gofer_random => "fail=0.01%,do,delay60=1%,execute", \& }); .Ve .PP will cause the \fBdo()\fR method to fail for 0.01% of calls, and the \fBexecute()\fR method to fail 0.01% of calls and be delayed by 60 seconds on 1% of calls. .PP If the percentage value (\f(CW\*(C`R\*(C'\fR) is negative then instead of the failures being triggered randomly (via the \fBrand()\fR function) they are triggered via a sequence number. In other words "\f(CW\*(C`fail=\-20%\*(C'\fR" will mean every fifth call will fail. Each method has a distinct sequence number. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/DBD::Gofer::Transport::null.3pm000044400000007355152462503210013526 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Transport::null 3" .TH DBD::Gofer::Transport::null 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Transport::null \- DBD::Gofer client transport for testing .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& my $original_dsn = "..." \& DBI\->connect("dbi:Gofer:transport=null;dsn=$original_dsn",...) .Ve .PP or, enable by setting the \s-1DBI_AUTOPROXY\s0 environment variable: .PP .Vb 1 \& export DBI_AUTOPROXY="dbi:Gofer:transport=null" .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Connect via DBD::Gofer but execute the requests within the same process. .PP This is a quick and simple way to test applications for compatibility with the (few) restrictions that DBD::Gofer imposes. .PP It also provides a simple, portable way for the \s-1DBI\s0 test suite to be used to test DBD::Gofer on all platforms with no setup. .PP Also, by measuring the difference in performance between normal connections and connections via \f(CW\*(C`dbi:Gofer:transport=null\*(C'\fR the basic cost of using DBD::Gofer can be measured. Furthermore, the additional cost of more advanced transports can be isolated by comparing their performance with the null transport. .PP The \f(CW\*(C`t/85gofer.t\*(C'\fR script in the \s-1DBI\s0 distribution includes a comparative benchmark. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. .SH "SEE ALSO" .IX Header "SEE ALSO" DBD::Gofer::Transport::Base .PP DBD::Gofer man/man3/Net::HTTP::Methods.3pm000044400000010570152462503210011721 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Net::HTTP::Methods 3pm" .TH Net::HTTP::Methods 3pm "2021-03-18" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::HTTP::Methods \- Methods shared by Net::HTTP and Net::HTTPS .SH "VERSION" .IX Header "VERSION" version 6.21 .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2001\-2017 by Gisle Aas. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. man/man3/Devel::CheckLib.3pm000044400000023272152462503210011412 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Devel::CheckLib 3" .TH Devel::CheckLib 3 "2019-11-12" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Devel::CheckLib \- check that a library is available .SH "DESCRIPTION" .IX Header "DESCRIPTION" Devel::CheckLib is a perl module that checks whether a particular C library and its headers are available. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Devel::CheckLib; \& \& check_lib_or_exit( lib => \*(Aqjpeg\*(Aq, header => \*(Aqjpeglib.h\*(Aq ); \& check_lib_or_exit( lib => [ \*(Aqiconv\*(Aq, \*(Aqjpeg\*(Aq ] ); \& \& # or prompt for path to library and then do this: \& check_lib_or_exit( lib => \*(Aqjpeg\*(Aq, libpath => $additional_path ); .Ve .SH "USING IT IN Makefile.PL or Build.PL" .IX Header "USING IT IN Makefile.PL or Build.PL" If you want to use this from Makefile.PL or Build.PL, do not simply copy the module into your distribution as this may cause problems when \s-1PAUSE\s0 and search.cpan.org index the distro. Instead, use the use-devel-checklib script. .SH "HOW IT WORKS" .IX Header "HOW IT WORKS" You pass named parameters to a function, describing to it how to build and link to the libraries. .PP It works by trying to compile some code \- which defaults to this: .PP .Vb 1 \& int main(int argc, char *argv[]) { return 0; } .Ve .PP and linking it to the specified libraries. If something pops out the end which looks executable, it gets executed, and if \fBmain()\fR returns 0 we know that it worked. That tiny program is built once for each library that you specify, and (without linking) once for each header file. .PP If you want to check for the presence of particular functions in a library, or even that those functions return particular results, then you can pass your own function body for \fBmain()\fR thus: .PP .Vb 7 \& check_lib_or_exit( \& function => \*(Aqfoo();if(libversion() > 5) return 0; else return 1;\*(Aq \& incpath => ... \& libpath => ... \& lib => ... \& header => ... \& ); .Ve .PP In that case, it will fail to build if either \fBfoo()\fR or \fBlibversion()\fR don't exist, and \fBmain()\fR will return the wrong value if \fBlibversion()\fR's return value isn't what you want. .SH "FUNCTIONS" .IX Header "FUNCTIONS" All of these take the same named parameters and are exported by default. To avoid exporting them, \f(CW\*(C`use Devel::CheckLib ()\*(C'\fR. .SS "assert_lib" .IX Subsection "assert_lib" This takes several named parameters, all of which are optional, and dies with an error message if any of the libraries listed can not be found. \fBNote\fR: dying in a Makefile.PL or Build.PL may provoke a '\s-1FAIL\s0' report from \s-1CPAN\s0 Testers' automated smoke testers. Use \&\f(CW\*(C`check_lib_or_exit\*(C'\fR instead. .PP The named parameters are: .IP "lib" 4 .IX Item "lib" Must be either a string with the name of a single library or a reference to an array of strings of library names. Depending on the compiler found, library names will be fed to the compiler either as \&\f(CW\*(C`\-l\*(C'\fR arguments or as \f(CW\*(C`.lib\*(C'\fR file names. (E.g. \f(CW\*(C`\-ljpeg\*(C'\fR or \f(CW\*(C`jpeg.lib\*(C'\fR) .IP "libpath" 4 .IX Item "libpath" a string or an array of strings representing additional paths to search for libraries. .IP "\s-1LIBS\s0" 4 .IX Item "LIBS" a \f(CW\*(C`ExtUtils::MakeMaker\*(C'\fR\-style space-separated list of libraries (each preceded by '\-l') and directories (preceded by '\-L'). .Sp This can also be supplied on the command-line. .IP "debug" 4 .IX Item "debug" If true \- emit information during processing that can be used for debugging. .PP And libraries are no use without header files, so ... .IP "header" 4 .IX Item "header" Must be either a string with the name of a single header file or a reference to an array of strings of header file names. .IP "incpath" 4 .IX Item "incpath" a string or an array of strings representing additional paths to search for headers. .IP "\s-1INC\s0" 4 .IX Item "INC" a \f(CW\*(C`ExtUtils::MakeMaker\*(C'\fR\-style space-separated list of incpaths, each preceded by '\-I'. .Sp This can also be supplied on the command-line. .IP "ccflags" 4 .IX Item "ccflags" Extra flags to pass to the compiler. .IP "ldflags" 4 .IX Item "ldflags" Extra flags to pass to the linker. .IP "analyze_binary" 4 .IX Item "analyze_binary" a callback function that will be invoked in order to perform custom analysis of the generated binary. The callback arguments are the library name and the path to the binary just compiled. .Sp It is possible to use this callback, for instance, to inspect the binary for further dependencies. .IP "not_execute" 4 .IX Item "not_execute" Do not try to execute generated binary. Only check that compilation has not failed. .SS "check_lib_or_exit" .IX Subsection "check_lib_or_exit" This behaves exactly the same as \f(CW\*(C`assert_lib()\*(C'\fR except that instead of dieing, it warns (with exactly the same error message) and exits. This is intended for use in Makefile.PL / Build.PL when you might want to prompt the user for various paths and things before checking that what they've told you is sane. .PP If any library or header is missing, it exits with an exit value of 0 to avoid causing a \s-1CPAN\s0 Testers '\s-1FAIL\s0' report. \s-1CPAN\s0 Testers should ignore this result \*(-- which is what you want if an external library dependency is not available. .SS "check_lib" .IX Subsection "check_lib" This behaves exactly the same as \f(CW\*(C`assert_lib()\*(C'\fR except that it is silent, returning false instead of dieing, or true otherwise. .SH "PLATFORMS SUPPORTED" .IX Header "PLATFORMS SUPPORTED" You must have a C compiler installed. We check for \f(CW$Config{cc}\fR, both literally as it is in Config.pm and also in the \f(CW$PATH\fR. .PP It has been tested with varying degrees of rigorousness on: .IP "gcc (on Linux, *BSD, Mac \s-1OS X,\s0 Solaris, Cygwin)" 4 .IX Item "gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)" .PD 0 .IP "Sun's compiler tools on Solaris" 4 .IX Item "Sun's compiler tools on Solaris" .IP "\s-1IBM\s0's tools on \s-1AIX\s0" 4 .IX Item "IBM's tools on AIX" .IP "\s-1SGI\s0's tools on Irix 6.5" 4 .IX Item "SGI's tools on Irix 6.5" .IP "Microsoft's tools on Windows" 4 .IX Item "Microsoft's tools on Windows" .IP "MinGW on Windows (with Strawberry Perl)" 4 .IX Item "MinGW on Windows (with Strawberry Perl)" .IP "Borland's tools on Windows" 4 .IX Item "Borland's tools on Windows" .IP "\s-1QNX\s0" 4 .IX Item "QNX" .PD .SH "WARNINGS, BUGS and FEEDBACK" .IX Header "WARNINGS, BUGS and FEEDBACK" This is a very early release intended primarily for feedback from people who have discussed it. The interface may change and it has not been adequately tested. .PP Feedback is most welcome, including constructive criticism. Bug reports should be made using or by email. .PP When submitting a bug report, please include the output from running: .PP .Vb 2 \& perl \-V \& perl \-MDevel::CheckLib \-e0 .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" Devel::CheckOS .PP Probe::Perl .SH "AUTHORS" .IX Header "AUTHORS" David Cantrell .PP David Golden .PP Yasuhiro Matsumoto .PP Thanks to the cpan-testers-discuss mailing list for prompting us to write it in the first place; .PP to Chris Williams for help with Borland support; .PP to Tony Cook for help with Microsoft compiler command-line options .SH "COPYRIGHT and LICENCE" .IX Header "COPYRIGHT and LICENCE" Copyright 2007 David Cantrell. Portions copyright 2007 David Golden. .PP This module is free-as-in-speech software, and may be used, distributed, and modified under the same conditions as perl itself. .SH "CONSPIRACY" .IX Header "CONSPIRACY" This module is also free-as-in-mason software. man/man3/LWP::Protocol.3pm000044400000014207152462503210011150 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP::Protocol 3" .TH LWP::Protocol 3 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" LWP::Protocol \- Base class for LWP protocols .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& package LWP::Protocol::foo; \& use parent qw(LWP::Protocol); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This class is used as the base class for all protocol implementations supported by the \s-1LWP\s0 library. .PP When creating an instance of this class using \&\f(CW\*(C`LWP::Protocol::create($url)\*(C'\fR, and you get an initialized subclass appropriate for that access method. In other words, the \&\*(L"create\*(R" in LWP::Protocol function calls the constructor for one of its subclasses. .PP All derived \f(CW\*(C`LWP::Protocol\*(C'\fR classes need to override the \f(CW\*(C`request()\*(C'\fR method which is used to service a request. The overridden method can make use of the \f(CW\*(C`collect()\*(C'\fR method to collect together chunks of data as it is received. .SH "METHODS" .IX Header "METHODS" The following methods and functions are provided: .SS "new" .IX Subsection "new" .Vb 1 \& my $prot = LWP::Protocol\->new(); .Ve .PP The LWP::Protocol constructor is inherited by subclasses. As this is a virtual base class this method should \fBnot\fR be called directly. .SS "create" .IX Subsection "create" .Vb 1 \& my $prot = LWP::Protocol::create($scheme) .Ve .PP Create an object of the class implementing the protocol to handle the given scheme. This is a function, not a method. It is more an object factory than a constructor. This is the function user agents should use to access protocols. .SS "implementor" .IX Subsection "implementor" .Vb 1 \& my $class = LWP::Protocol::implementor($scheme, [$class]) .Ve .PP Get and/or set implementor class for a scheme. Returns \f(CW\*(Aq\*(Aq\fR if the specified scheme is not supported. .SS "request" .IX Subsection "request" .Vb 3 \& $response = $protocol\->request($request, $proxy, undef); \& $response = $protocol\->request($request, $proxy, \*(Aq/tmp/sss\*(Aq); \& $response = $protocol\->request($request, $proxy, \e&callback, 1024); .Ve .PP Dispatches a request over the protocol, and returns a response object. This method needs to be overridden in subclasses. Refer to LWP::UserAgent for description of the arguments. .SS "collect" .IX Subsection "collect" .Vb 3 \& my $res = $prot\->collect(undef, $response, $collector); # stored in $response \& my $res = $prot\->collect($filename, $response, $collector); \& my $res = $prot\->collect(sub { ... }, $response, $collector); .Ve .PP Collect the content of a request, and process it appropriately into a scalar, file, or by calling a callback. If the first parameter is undefined, then the content is stored within the \f(CW$response\fR. If it's a simple scalar, then it's interpreted as a file name and the content is written to this file. If it's a code reference, then content is passed to this routine. .PP The collector is a routine that will be called and which is responsible for returning pieces (as ref to scalar) of the content to process. The \f(CW$collector\fR signals \f(CW\*(C`EOF\*(C'\fR by returning a reference to an empty string. .PP The return value is the HTTP::Response object reference. .PP \&\fBNote:\fR We will only use the callback or file argument if \&\f(CW\*(C`$response\->is_success()\*(C'\fR. This avoids sending content data for redirects and authentication responses to the callback which would be confusing. .SS "collect_once" .IX Subsection "collect_once" .Vb 1 \& $prot\->collect_once($arg, $response, $content) .Ve .PP Can be called when the whole response content is available as content. This will invoke \*(L"collect\*(R" in LWP::Protocol with a collector callback that returns a reference to \f(CW$content\fR the first time and an empty string the next. .SH "SEE ALSO" .IX Header "SEE ALSO" Inspect the \fILWP/Protocol/file.pm\fR and \fILWP/Protocol/http.pm\fR files for examples of usage. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 1995\-2001 Gisle Aas. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/Bundle::DBI.3pm000044400000006573152462503210010523 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Bundle::DBI 3" .TH Bundle::DBI 3 "2015-05-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Bundle::DBI \- A bundle to install DBI and required modules. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& perl \-MCPAN \-e \*(Aqinstall Bundle::DBI\*(Aq .Ve .SH "CONTENTS" .IX Header "CONTENTS" \&\s-1DBI\s0 \- for to get to know thyself .PP DBI::Shell 11.91 \- the \s-1DBI\s0 command line shell .PP Storable 2.06 \- for DBD::Proxy, DBI::ProxyServer, DBD::Forward .PP Net::Daemon 0.37 \- for DBD::Proxy and DBI::ProxyServer .PP RPC::PlServer 0.2016 \- for DBD::Proxy and DBI::ProxyServer .PP DBD::Multiplex 1.19 \- treat multiple db handles as one .SH "DESCRIPTION" .IX Header "DESCRIPTION" This bundle includes all the modules used by the Perl Database Interface (\s-1DBI\s0) module, created by Tim Bunce. .PP A \fIBundle\fR is a module that simply defines a collection of other modules. It is used by the \s-1CPAN\s0 module to automate the fetching, building and installing of modules from the \s-1CPAN\s0 ftp archive sites. .PP This bundle does not deal with the various database drivers (e.g. DBD::Informix, DBD::Oracle etc), most of which require software from sources other than \s-1CPAN.\s0 You'll need to fetch and build those drivers yourself. .SH "AUTHORS" .IX Header "AUTHORS" Jonathan Leffler, Jochen Wiedmann and Tim Bunce. man/man3/DBI::Gofer::Transport::stream.3pm000044400000005244152462503210014047 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Transport::stream 3" .TH DBI::Gofer::Transport::stream 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Transport::stream \- DBD::Gofer server\-side transport for stream .SH "SYNOPSIS" .IX Header "SYNOPSIS" See DBD::Gofer::Transport::stream. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/JSON::backportPP.3pm000044400000176572152462503210011541 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::backportPP 3" .TH JSON::backportPP 3 "2021-01-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::PP \- JSON::XS compatible pure\-Perl module. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use JSON::PP; \& \& # exported functions, they croak on error \& # and expect/generate UTF\-8 \& \& $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; \& $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; \& \& # OO\-interface \& \& $json = JSON::PP\->new\->ascii\->pretty\->allow_nonref; \& \& $pretty_printed_json_text = $json\->encode( $perl_scalar ); \& $perl_scalar = $json\->decode( $json_text ); \& \& # Note that JSON version 2.0 and above will automatically use \& # JSON::XS or JSON::PP, so you should be able to just: \& \& use JSON; .Ve .SH "VERSION" .IX Header "VERSION" .Vb 1 \& 4.05 .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1JSON::PP\s0 is a pure perl \s-1JSON\s0 decoder/encoder, and (almost) compatible to much faster \s-1JSON::XS\s0 written by Marc Lehmann in C. \s-1JSON::PP\s0 works as a fallback module when you use \s-1JSON\s0 module without having installed \s-1JSON::XS.\s0 .PP Because of this fallback feature of \s-1JSON\s0.pm, \s-1JSON::PP\s0 tries not to be more JavaScript-friendly than \s-1JSON::XS\s0 (i.e. not to escape extra characters such as U+2028 and U+2029, etc), in order for you not to lose such JavaScript-friendliness silently when you use \s-1JSON\s0.pm and install \s-1JSON::XS\s0 for speed or by accident. If you need JavaScript-friendly RFC7159\-compliant pure perl module, try JSON::Tiny, which is derived from Mojolicious web framework and is also smaller and faster than \s-1JSON::PP.\s0 .PP \&\s-1JSON::PP\s0 has been in the Perl core since Perl 5.14, mainly for \&\s-1CPAN\s0 toolchain modules to parse \s-1META\s0.json. .SH "FUNCTIONAL INTERFACE" .IX Header "FUNCTIONAL INTERFACE" This section is taken from \s-1JSON::XS\s0 almost verbatim. \f(CW\*(C`encode_json\*(C'\fR and \f(CW\*(C`decode_json\*(C'\fR are exported by default. .SS "encode_json" .IX Subsection "encode_json" .Vb 1 \& $json_text = encode_json $perl_scalar .Ve .PP Converts the given Perl data structure to a \s-1UTF\-8\s0 encoded, binary string (that is, the string contains octets only). Croaks on error. .PP This function call is functionally identical to: .PP .Vb 1 \& $json_text = JSON::PP\->new\->utf8\->encode($perl_scalar) .Ve .PP Except being faster. .SS "decode_json" .IX Subsection "decode_json" .Vb 1 \& $perl_scalar = decode_json $json_text .Ve .PP The opposite of \f(CW\*(C`encode_json\*(C'\fR: expects an \s-1UTF\-8\s0 (binary) string and tries to parse that as an \s-1UTF\-8\s0 encoded \s-1JSON\s0 text, returning the resulting reference. Croaks on error. .PP This function call is functionally identical to: .PP .Vb 1 \& $perl_scalar = JSON::PP\->new\->utf8\->decode($json_text) .Ve .PP Except being faster. .SS "JSON::PP::is_bool" .IX Subsection "JSON::PP::is_bool" .Vb 1 \& $is_boolean = JSON::PP::is_bool($scalar) .Ve .PP Returns true if the passed scalar represents either JSON::PP::true or JSON::PP::false, two constants that act like \f(CW1\fR and \f(CW0\fR respectively and are also used to represent \s-1JSON\s0 \f(CW\*(C`true\*(C'\fR and \f(CW\*(C`false\*(C'\fR in Perl strings. .PP See \s-1MAPPING\s0, below, for more information on how \s-1JSON\s0 values are mapped to Perl. .SH "OBJECT-ORIENTED INTERFACE" .IX Header "OBJECT-ORIENTED INTERFACE" This section is also taken from \s-1JSON::XS.\s0 .PP The object oriented interface lets you configure your own encoding or decoding style, within the limits of supported formats. .SS "new" .IX Subsection "new" .Vb 1 \& $json = JSON::PP\->new .Ve .PP Creates a new \s-1JSON::PP\s0 object that can be used to de/encode \s-1JSON\s0 strings. All boolean flags described below are by default \fIdisabled\fR (with the exception of \f(CW\*(C`allow_nonref\*(C'\fR, which defaults to \fIenabled\fR since version \f(CW4.0\fR). .PP The mutators for flags all return the \s-1JSON::PP\s0 object again and thus calls can be chained: .PP .Vb 2 \& my $json = JSON::PP\->new\->utf8\->space_after\->encode({a => [1,2]}) \& => {"a": [1, 2]} .Ve .SS "ascii" .IX Subsection "ascii" .Vb 1 \& $json = $json\->ascii([$enable]) \& \& $enabled = $json\->get_ascii .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not generate characters outside the code range \f(CW0..127\fR (which is \s-1ASCII\s0). Any Unicode characters outside that range will be escaped using either a single \euXXXX (\s-1BMP\s0 characters) or a double \euHHHH\euLLLLL escape sequence, as per \s-1RFC4627.\s0 The resulting encoded \s-1JSON\s0 text can be treated as a native Unicode string, an ascii-encoded, latin1\-encoded or \s-1UTF\-8\s0 encoded string, or any other superset of \s-1ASCII.\s0 .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. This results in a faster and more compact format. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP The main use for this flag is to produce \s-1JSON\s0 texts that can be transmitted over a 7\-bit channel, as the encoded \s-1JSON\s0 texts will not contain any 8 bit characters. .PP .Vb 2 \& JSON::PP\->new\->ascii(1)\->encode([chr 0x10401]) \& => ["\eud801\eudc01"] .Ve .SS "latin1" .IX Subsection "latin1" .Vb 1 \& $json = $json\->latin1([$enable]) \& \& $enabled = $json\->get_latin1 .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the resulting \s-1JSON\s0 text as latin1 (or iso\-8859\-1), escaping any characters outside the code range \f(CW0..255\fR. The resulting string can be treated as a latin1\-encoded \s-1JSON\s0 text or a native Unicode string. The \f(CW\*(C`decode\*(C'\fR method will not be affected in any way by this flag, as \f(CW\*(C`decode\*(C'\fR by default expects Unicode, which is a strict superset of latin1. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not escape Unicode characters unless required by the \s-1JSON\s0 syntax or other flags. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP The main use for this flag is efficiently encoding binary data as \s-1JSON\s0 text, as most octets will not be escaped, resulting in a smaller encoded size. The disadvantage is that the resulting \s-1JSON\s0 text is encoded in latin1 (and must correctly be treated as such when storing and transferring), a rare encoding for \s-1JSON.\s0 It is therefore most useful when you want to store data structures known to contain binary data efficiently in files or databases, not when talking to other \s-1JSON\s0 encoders/decoders. .PP .Vb 2 \& JSON::PP\->new\->latin1\->encode (["\ex{89}\ex{abc}"] \& => ["\ex{89}\e\eu0abc"] # (perl syntax, U+abc escaped, U+89 not) .Ve .SS "utf8" .IX Subsection "utf8" .Vb 1 \& $json = $json\->utf8([$enable]) \& \& $enabled = $json\->get_utf8 .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will encode the \s-1JSON\s0 result into \s-1UTF\-8,\s0 as required by many protocols, while the \&\f(CW\*(C`decode\*(C'\fR method expects to be handled an UTF\-8\-encoded string. Please note that UTF\-8\-encoded strings do not contain any characters outside the range \f(CW0..255\fR, they are thus useful for bytewise/binary I/O. In future versions, enabling this option might enable autodetection of the \s-1UTF\-16\s0 and \s-1UTF\-32\s0 encoding families, as described in \s-1RFC4627.\s0 .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will return the \s-1JSON\s0 string as a (non-encoded) Unicode string, while \f(CW\*(C`decode\*(C'\fR expects thus a Unicode string. Any decoding or encoding (e.g. to \s-1UTF\-8\s0 or \s-1UTF\-16\s0) needs to be done yourself, e.g. using the Encode module. .PP See also the section \fI\s-1ENCODING/CODESET FLAG NOTES\s0\fR later in this document. .PP Example, output UTF\-16BE\-encoded \s-1JSON:\s0 .PP .Vb 2 \& use Encode; \& $jsontext = encode "UTF\-16BE", JSON::PP\->new\->encode ($object); .Ve .PP Example, decode UTF\-32LE\-encoded \s-1JSON:\s0 .PP .Vb 2 \& use Encode; \& $object = JSON::PP\->new\->decode (decode "UTF\-32LE", $jsontext); .Ve .SS "pretty" .IX Subsection "pretty" .Vb 1 \& $json = $json\->pretty([$enable]) .Ve .PP This enables (or disables) all of the \f(CW\*(C`indent\*(C'\fR, \f(CW\*(C`space_before\*(C'\fR and \&\f(CW\*(C`space_after\*(C'\fR (and in the future possibly more) flags in one call to generate the most readable (or most compact) form possible. .SS "indent" .IX Subsection "indent" .Vb 1 \& $json = $json\->indent([$enable]) \& \& $enabled = $json\->get_indent .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will use a multiline format as output, putting every array member or object/hash key-value pair into its own line, indenting them properly. .PP If \f(CW$enable\fR is false, no newlines or indenting will be produced, and the resulting \s-1JSON\s0 text is guaranteed not to contain any \f(CW\*(C`newlines\*(C'\fR. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP The default indent space length is three. You can use \f(CW\*(C`indent_length\*(C'\fR to change the length. .SS "space_before" .IX Subsection "space_before" .Vb 1 \& $json = $json\->space_before([$enable]) \& \& $enabled = $json\->get_space_before .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space before the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .PP This setting has no effect when decoding \s-1JSON\s0 texts. You will also most likely combine this setting with \f(CW\*(C`space_after\*(C'\fR. .PP Example, space_before enabled, space_after and indent disabled: .PP .Vb 1 \& {"key" :"value"} .Ve .SS "space_after" .IX Subsection "space_after" .Vb 1 \& $json = $json\->space_after([$enable]) \& \& $enabled = $json\->get_space_after .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will add an extra optional space after the \f(CW\*(C`:\*(C'\fR separating keys from values in \s-1JSON\s0 objects and extra whitespace after the \f(CW\*(C`,\*(C'\fR separating key-value pairs and array members. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will not add any extra space at those places. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP Example, space_before and indent disabled, space_after enabled: .PP .Vb 1 \& {"key": "value"} .Ve .SS "relaxed" .IX Subsection "relaxed" .Vb 1 \& $json = $json\->relaxed([$enable]) \& \& $enabled = $json\->get_relaxed .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept some extensions to normal \s-1JSON\s0 syntax (see below). \f(CW\*(C`encode\*(C'\fR will not be affected in anyway. \fIBe aware that this option makes you accept invalid \&\s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP Currently accepted extensions are: .IP "\(bu" 4 list items can have an end-comma .Sp \&\s-1JSON\s0 \fIseparates\fR array elements and key-value pairs with commas. This can be annoying if you write \s-1JSON\s0 texts manually and want to be able to quickly append elements, so this extension accepts comma at the end of such items not just between them: .Sp .Vb 8 \& [ \& 1, \& 2, <\- this comma not normally allowed \& ] \& { \& "k1": "v1", \& "k2": "v2", <\- this comma not normally allowed \& } .Ve .IP "\(bu" 4 shell-style '#'\-comments .Sp Whenever \s-1JSON\s0 allows whitespace, shell-style comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, # this comment not allowed in JSON \& # neither this one... \& ] .Ve .IP "\(bu" 4 C\-style multiple-line '/* */'\-comments (\s-1JSON::PP\s0 only) .Sp Whenever \s-1JSON\s0 allows whitespace, C\-style multiple-line comments are additionally allowed. Everything between \f(CW\*(C`/*\*(C'\fR and \f(CW\*(C`*/\*(C'\fR is a comment, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, /* this comment not allowed in JSON */ \& /* neither this one... */ \& ] .Ve .IP "\(bu" 4 \&\*(C+\-style one-line '//'\-comments (\s-1JSON::PP\s0 only) .Sp Whenever \s-1JSON\s0 allows whitespace, \*(C+\-style one-line comments are additionally allowed. They are terminated by the first carriage-return or line-feed character, after which more white-space and comments are allowed. .Sp .Vb 4 \& [ \& 1, // this comment not allowed in JSON \& // neither this one... \& ] .Ve .IP "\(bu" 4 literal \s-1ASCII TAB\s0 characters in strings .Sp Literal \s-1ASCII TAB\s0 characters are now allowed in strings (and treated as \&\f(CW\*(C`\et\*(C'\fR). .Sp .Vb 4 \& [ \& "Hello\etWorld", \& "HelloWorld", # literal would not normally be allowed \& ] .Ve .SS "canonical" .IX Subsection "canonical" .Vb 1 \& $json = $json\->canonical([$enable]) \& \& $enabled = $json\->get_canonical .Ve .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will output \s-1JSON\s0 objects by sorting their keys. This is adding a comparatively high overhead. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will output key-value pairs in the order Perl stores them (which will likely change between runs of the same script, and can change even within the same run from 5.18 onwards). .PP This option is useful if you want the same data structure to be encoded as the same \s-1JSON\s0 text (given the same overall settings). If it is disabled, the same hash might be encoded differently even if contains the same data, as key-value pairs have no inherent ordering in Perl. .PP This setting has no effect when decoding \s-1JSON\s0 texts. .PP This setting has currently no effect on tied hashes. .SS "allow_nonref" .IX Subsection "allow_nonref" .Vb 1 \& $json = $json\->allow_nonref([$enable]) \& \& $enabled = $json\->get_allow_nonref .Ve .PP Unlike other boolean options, this opotion is enabled by default beginning with version \f(CW4.0\fR. .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method can convert a non-reference into its corresponding string, number or null \s-1JSON\s0 value, which is an extension to \s-1RFC4627.\s0 Likewise, \f(CW\*(C`decode\*(C'\fR will accept those \s-1JSON\s0 values instead of croaking. .PP If \f(CW$enable\fR is false, then the \f(CW\*(C`encode\*(C'\fR method will croak if it isn't passed an arrayref or hashref, as \s-1JSON\s0 texts must either be an object or array. Likewise, \f(CW\*(C`decode\*(C'\fR will croak if given something that is not a \&\s-1JSON\s0 object or array. .PP Example, encode a Perl scalar as \s-1JSON\s0 value without enabled \f(CW\*(C`allow_nonref\*(C'\fR, resulting in an error: .PP .Vb 2 \& JSON::PP\->new\->allow_nonref(0)\->encode ("Hello, World!") \& => hash\- or arrayref expected... .Ve .SS "allow_unknown" .IX Subsection "allow_unknown" .Vb 1 \& $json = $json\->allow_unknown([$enable]) \& \& $enabled = $json\->get_allow_unknown .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR will \fInot\fR throw an exception when it encounters values it cannot represent in \s-1JSON\s0 (for example, filehandles) but instead will encode a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value. Note that blessed objects are not included here and are handled separately by c. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters anything it cannot encode as \s-1JSON.\s0 .PP This option does not affect \f(CW\*(C`decode\*(C'\fR in any way, and it is recommended to leave it off unless you know your communications partner. .SS "allow_blessed" .IX Subsection "allow_blessed" .Vb 1 \& $json = $json\->allow_blessed([$enable]) \& \& $enabled = $json\->get_allow_blessed .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then the \f(CW\*(C`encode\*(C'\fR method will not barf when it encounters a blessed reference that it cannot convert otherwise. Instead, a \s-1JSON\s0 \f(CW\*(C`null\*(C'\fR value is encoded instead of the object. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will throw an exception when it encounters a blessed object that it cannot convert otherwise. .PP This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .SS "convert_blessed" .IX Subsection "convert_blessed" .Vb 1 \& $json = $json\->convert_blessed([$enable]) \& \& $enabled = $json\->get_convert_blessed .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`TO_JSON\*(C'\fR method on the object's class. If found, it will be called in scalar context and the resulting scalar will be encoded instead of the object. .PP The \f(CW\*(C`TO_JSON\*(C'\fR method may safely call die if it wants. If \f(CW\*(C`TO_JSON\*(C'\fR returns other blessed objects, those will be handled in the same way. \f(CW\*(C`TO_JSON\*(C'\fR must take care of not causing an endless recursion cycle (== crash) in this case. The name of \f(CW\*(C`TO_JSON\*(C'\fR was chosen because other methods called by the Perl core (== not by the user of the object) are usually in upper case letters and to avoid collisions with any \f(CW\*(C`to_json\*(C'\fR function or method. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion. .PP This setting has no effect on \f(CW\*(C`decode\*(C'\fR. .SS "allow_tags" .IX Subsection "allow_tags" .Vb 1 \& $json = $json\->allow_tags([$enable]) \& \& $enabled = $json\->get_allow_tags .Ve .PP See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0 for details. .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR, upon encountering a blessed object, will check for the availability of the \f(CW\*(C`FREEZE\*(C'\fR method on the object's class. If found, it will be used to serialise the object into a nonstandard tagged \s-1JSON\s0 value (that \s-1JSON\s0 decoders cannot decode). .PP It also causes \f(CW\*(C`decode\*(C'\fR to parse such tagged \s-1JSON\s0 values and deserialise them via a call to the \f(CW\*(C`THAW\*(C'\fR method. .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`encode\*(C'\fR will not consider this type of conversion, and tagged \s-1JSON\s0 values will cause a parse error in \f(CW\*(C`decode\*(C'\fR, as if tags were not part of the grammar. .SS "boolean_values" .IX Subsection "boolean_values" .Vb 1 \& $json\->boolean_values([$false, $true]) \& \& ($false, $true) = $json\->get_boolean_values .Ve .PP By default, \s-1JSON\s0 booleans will be decoded as overloaded \&\f(CW$JSON::PP::false\fR and \f(CW$JSON::PP::true\fR objects. .PP With this method you can specify your own boolean values for decoding \- on decode, \s-1JSON\s0 \f(CW\*(C`false\*(C'\fR will be decoded as a copy of \f(CW$false\fR, and \s-1JSON\s0 \&\f(CW\*(C`true\*(C'\fR will be decoded as \f(CW$true\fR (\*(L"copy\*(R" here is the same thing as assigning a value to another variable, i.e. \f(CW\*(C`$copy = $false\*(C'\fR). .PP This is useful when you want to pass a decoded data structure directly to other serialisers like \s-1YAML,\s0 Data::MessagePack and so on. .PP Note that this works only when you \f(CW\*(C`decode\*(C'\fR. You can set incompatible boolean objects (like boolean), but when you \f(CW\*(C`encode\*(C'\fR a data structure with such boolean objects, you still need to enable \f(CW\*(C`convert_blessed\*(C'\fR (and add a \f(CW\*(C`TO_JSON\*(C'\fR method if necessary). .PP Calling this method without any arguments will reset the booleans to their default values. .PP \&\f(CW\*(C`get_boolean_values\*(C'\fR will return both \f(CW$false\fR and \f(CW$true\fR values, or the empty list when they are set to the default. .SS "filter_json_object" .IX Subsection "filter_json_object" .Vb 1 \& $json = $json\->filter_json_object([$coderef]) .Ve .PP When \f(CW$coderef\fR is specified, it will be called from \f(CW\*(C`decode\*(C'\fR each time it decodes a \s-1JSON\s0 object. The only argument is a reference to the newly-created hash. If the code references returns a single scalar (which need not be a reference), this value (or rather a copy of it) is inserted into the deserialised data structure. If it returns an empty list (\s-1NOTE:\s0 \fInot\fR \f(CW\*(C`undef\*(C'\fR, which is a valid scalar), the original deserialised hash will be inserted. This setting can slow down decoding considerably. .PP When \f(CW$coderef\fR is omitted or undefined, any existing callback will be removed and \f(CW\*(C`decode\*(C'\fR will not change the deserialised hash in any way. .PP Example, convert all \s-1JSON\s0 objects into the integer 5: .PP .Vb 5 \& my $js = JSON::PP\->new\->filter_json_object(sub { 5 }); \& # returns [5] \& $js\->decode(\*(Aq[{}]\*(Aq); \& # returns 5 \& $js\->decode(\*(Aq{"a":1, "b":2}\*(Aq); .Ve .SS "filter_json_single_key_object" .IX Subsection "filter_json_single_key_object" .Vb 1 \& $json = $json\->filter_json_single_key_object($key [=> $coderef]) .Ve .PP Works remotely similar to \f(CW\*(C`filter_json_object\*(C'\fR, but is only called for \&\s-1JSON\s0 objects having a single key named \f(CW$key\fR. .PP This \f(CW$coderef\fR is called before the one specified via \&\f(CW\*(C`filter_json_object\*(C'\fR, if any. It gets passed the single value in the \s-1JSON\s0 object. If it returns a single value, it will be inserted into the data structure. If it returns nothing (not even \f(CW\*(C`undef\*(C'\fR but the empty list), the callback from \f(CW\*(C`filter_json_object\*(C'\fR will be called next, as if no single-key callback were specified. .PP If \f(CW$coderef\fR is omitted or undefined, the corresponding callback will be disabled. There can only ever be one callback for a given key. .PP As this callback gets called less often then the \f(CW\*(C`filter_json_object\*(C'\fR one, decoding speed will not usually suffer as much. Therefore, single-key objects make excellent targets to serialise Perl objects into, especially as single-key \s-1JSON\s0 objects are as close to the type-tagged value concept as \s-1JSON\s0 gets (it's basically an \s-1ID/VALUE\s0 tuple). Of course, \s-1JSON\s0 does not support this in any way, so you need to make sure your data never looks like a serialised Perl hash. .PP Typical names for the single object key are \f(CW\*(C`_\|_class_whatever_\|_\*(C'\fR, or \&\f(CW\*(C`$_\|_dollars_are_rarely_used_\|_$\*(C'\fR or \f(CW\*(C`}ugly_brace_placement\*(C'\fR, or even things like \f(CW\*(C`_\|_class_md5sum(classname)_\|_\*(C'\fR, to reduce the risk of clashing with real hashes. .PP Example, decode \s-1JSON\s0 objects of the form \f(CW\*(C`{ "_\|_widget_\|_" => }\*(C'\fR into the corresponding \f(CW$WIDGET{}\fR object: .PP .Vb 7 \& # return whatever is in $WIDGET{5}: \& JSON::PP \& \->new \& \->filter_json_single_key_object (_\|_widget_\|_ => sub { \& $WIDGET{ $_[0] } \& }) \& \->decode (\*(Aq{"_\|_widget_\|_": 5\*(Aq) \& \& # this can be used with a TO_JSON method in some "widget" class \& # for serialisation to json: \& sub WidgetBase::TO_JSON { \& my ($self) = @_; \& \& unless ($self\->{id}) { \& $self\->{id} = ..get..some..id..; \& $WIDGET{$self\->{id}} = $self; \& } \& \& { _\|_widget_\|_ => $self\->{id} } \& } .Ve .SS "shrink" .IX Subsection "shrink" .Vb 1 \& $json = $json\->shrink([$enable]) \& \& $enabled = $json\->get_shrink .Ve .PP If \f(CW$enable\fR is true (or missing), the string returned by \f(CW\*(C`encode\*(C'\fR will be shrunk (i.e. downgraded if possible). .PP The actual definition of what shrink does might change in future versions, but it will always try to save space at the expense of time. .PP If \f(CW$enable\fR is false, then \s-1JSON::PP\s0 does nothing. .SS "max_depth" .IX Subsection "max_depth" .Vb 1 \& $json = $json\->max_depth([$maximum_nesting_depth]) \& \& $max_depth = $json\->get_max_depth .Ve .PP Sets the maximum nesting level (default \f(CW512\fR) accepted while encoding or decoding. If a higher nesting level is detected in \s-1JSON\s0 text or a Perl data structure, then the encoder and decoder will stop and croak at that point. .PP Nesting level is defined by number of hash\- or arrayrefs that the encoder needs to traverse to reach a given point or the number of \f(CW\*(C`{\*(C'\fR or \f(CW\*(C`[\*(C'\fR characters without their matching closing parenthesis crossed to reach a given character in a string. .PP Setting the maximum depth to one disallows any nesting, so that ensures that the object is only a single hash/object or array. .PP If no argument is given, the highest possible setting will be used, which is rarely useful. .PP See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 in \s-1JSON::XS\s0 for more info on why this is useful. .SS "max_size" .IX Subsection "max_size" .Vb 1 \& $json = $json\->max_size([$maximum_string_size]) \& \& $max_size = $json\->get_max_size .Ve .PP Set the maximum length a \s-1JSON\s0 text may have (in bytes) where decoding is being attempted. The default is \f(CW0\fR, meaning no limit. When \f(CW\*(C`decode\*(C'\fR is called on a string that is longer then this many bytes, it will not attempt to decode the string but throw an exception. This setting has no effect on \f(CW\*(C`encode\*(C'\fR (yet). .PP If no argument is given, the limit check will be deactivated (same as when \&\f(CW0\fR is specified). .PP See \*(L"\s-1SECURITY CONSIDERATIONS\*(R"\s0 in \s-1JSON::XS\s0 for more info on why this is useful. .SS "encode" .IX Subsection "encode" .Vb 1 \& $json_text = $json\->encode($perl_scalar) .Ve .PP Converts the given Perl value or data structure to its \s-1JSON\s0 representation. Croaks on error. .SS "decode" .IX Subsection "decode" .Vb 1 \& $perl_scalar = $json\->decode($json_text) .Ve .PP The opposite of \f(CW\*(C`encode\*(C'\fR: expects a \s-1JSON\s0 text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. .SS "decode_prefix" .IX Subsection "decode_prefix" .Vb 1 \& ($perl_scalar, $characters) = $json\->decode_prefix($json_text) .Ve .PP This works like the \f(CW\*(C`decode\*(C'\fR method, but instead of raising an exception when there is trailing garbage after the first \s-1JSON\s0 object, it will silently stop parsing there and return the number of characters consumed so far. .PP This is useful if your \s-1JSON\s0 texts are not delimited by an outer protocol and you need to know where the \s-1JSON\s0 text ends. .PP .Vb 2 \& JSON::PP\->new\->decode_prefix ("[1] the tail") \& => ([1], 3) .Ve .SH "FLAGS FOR JSON::PP ONLY" .IX Header "FLAGS FOR JSON::PP ONLY" The following flags and properties are for \s-1JSON::PP\s0 only. If you use any of these, you can't make your application run faster by replacing \&\s-1JSON::PP\s0 with \s-1JSON::XS.\s0 If you need these and also speed boost, you might want to try Cpanel::JSON::XS, a fork of \s-1JSON::XS\s0 by Reini Urban, which supports some of these (with a different set of incompatibilities). Most of these historical flags are only kept for backward compatibility, and should not be used in a new application. .SS "allow_singlequote" .IX Subsection "allow_singlequote" .Vb 2 \& $json = $json\->allow_singlequote([$enable]) \& $enabled = $json\->get_allow_singlequote .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept invalid \s-1JSON\s0 texts that contain strings that begin and end with single quotation marks. \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \&\fIBe aware that this option makes you accept invalid \s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP .Vb 3 \& $json\->allow_singlequote\->decode(qq|{"foo":\*(Aqbar\*(Aq}|); \& $json\->allow_singlequote\->decode(qq|{\*(Aqfoo\*(Aq:"bar"}|); \& $json\->allow_singlequote\->decode(qq|{\*(Aqfoo\*(Aq:\*(Aqbar\*(Aq}|); .Ve .SS "allow_barekey" .IX Subsection "allow_barekey" .Vb 2 \& $json = $json\->allow_barekey([$enable]) \& $enabled = $json\->get_allow_barekey .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept invalid \s-1JSON\s0 texts that contain \s-1JSON\s0 objects whose names don't begin and end with quotation marks. \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \fIBe aware that this option makes you accept invalid \s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP .Vb 1 \& $json\->allow_barekey\->decode(qq|{foo:"bar"}|); .Ve .SS "allow_bignum" .IX Subsection "allow_bignum" .Vb 2 \& $json = $json\->allow_bignum([$enable]) \& $enabled = $json\->get_allow_bignum .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will convert big integers Perl cannot handle as integer into Math::BigInt objects and convert floating numbers into Math::BigFloat objects. \f(CW\*(C`encode\*(C'\fR will convert \f(CW\*(C`Math::BigInt\*(C'\fR and \f(CW\*(C`Math::BigFloat\*(C'\fR objects into \s-1JSON\s0 numbers. .PP .Vb 4 \& $json\->allow_nonref\->allow_bignum; \& $bigfloat = $json\->decode(\*(Aq2.000000000000000000000000001\*(Aq); \& print $json\->encode($bigfloat); \& # => 2.000000000000000000000000001 .Ve .PP See also \s-1MAPPING\s0. .SS "loose" .IX Subsection "loose" .Vb 2 \& $json = $json\->loose([$enable]) \& $enabled = $json\->get_loose .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`decode\*(C'\fR will accept invalid \s-1JSON\s0 texts that contain unescaped [\ex00\-\ex1f\ex22\ex5c] characters. \f(CW\*(C`encode\*(C'\fR will not be affected in any way. \&\fIBe aware that this option makes you accept invalid \s-1JSON\s0 texts as if they were valid!\fR. I suggest only to use this option to parse application-specific files written by humans (configuration files, resource files etc.) .PP If \f(CW$enable\fR is false (the default), then \f(CW\*(C`decode\*(C'\fR will only accept valid \s-1JSON\s0 texts. .PP .Vb 2 \& $json\->loose\->decode(qq|["abc \& def"]|); .Ve .SS "escape_slash" .IX Subsection "escape_slash" .Vb 2 \& $json = $json\->escape_slash([$enable]) \& $enabled = $json\->get_escape_slash .Ve .PP If \f(CW$enable\fR is true (or missing), then \f(CW\*(C`encode\*(C'\fR will explicitly escape \fIslash\fR (solidus; \f(CW\*(C`U+002F\*(C'\fR) characters to reduce the risk of \&\s-1XSS\s0 (cross site scripting) that may be caused by \f(CW\*(C`\*(C'\fR in a \s-1JSON\s0 text, with the cost of bloating the size of \s-1JSON\s0 texts. .PP This option may be useful when you embed \s-1JSON\s0 in \s-1HTML,\s0 but embedding arbitrary \s-1JSON\s0 in \s-1HTML\s0 (by some \s-1HTML\s0 template toolkit or by string interpolation) is risky in general. You must escape necessary characters in correct order, depending on the context. .PP \&\f(CW\*(C`decode\*(C'\fR will not be affected in any way. .SS "indent_length" .IX Subsection "indent_length" .Vb 2 \& $json = $json\->indent_length($number_of_spaces) \& $length = $json\->get_indent_length .Ve .PP This option is only useful when you also enable \f(CW\*(C`indent\*(C'\fR or \f(CW\*(C`pretty\*(C'\fR. .PP \&\s-1JSON::XS\s0 indents with three spaces when you \f(CW\*(C`encode\*(C'\fR (if requested by \f(CW\*(C`indent\*(C'\fR or \f(CW\*(C`pretty\*(C'\fR), and the number cannot be changed. \&\s-1JSON::PP\s0 allows you to change/get the number of indent spaces with these mutator/accessor. The default number of spaces is three (the same as \&\s-1JSON::XS\s0), and the acceptable range is from \f(CW0\fR (no indentation; it'd be better to disable indentation by \f(CWindent(0)\fR) to \f(CW15\fR. .SS "sort_by" .IX Subsection "sort_by" .Vb 2 \& $json = $json\->sort_by($code_ref) \& $json = $json\->sort_by($subroutine_name) .Ve .PP If you just want to sort keys (names) in \s-1JSON\s0 objects when you \&\f(CW\*(C`encode\*(C'\fR, enable \f(CW\*(C`canonical\*(C'\fR option (see above) that allows you to sort object keys alphabetically. .PP If you do need to sort non-alphabetically for whatever reasons, you can give a code reference (or a subroutine name) to \f(CW\*(C`sort_by\*(C'\fR, then the argument will be passed to Perl's \f(CW\*(C`sort\*(C'\fR built-in function. .PP As the sorting is done in the \s-1JSON::PP\s0 scope, you usually need to prepend \f(CW\*(C`JSON::PP::\*(C'\fR to the subroutine name, and the special variables \&\f(CW$a\fR and \f(CW$b\fR used in the subrontine used by \f(CW\*(C`sort\*(C'\fR function. .PP Example: .PP .Vb 9 \& my %ORDER = (id => 1, class => 2, name => 3); \& $json\->sort_by(sub { \& ($ORDER{$JSON::PP::a} // 999) <=> ($ORDER{$JSON::PP::b} // 999) \& or $JSON::PP::a cmp $JSON::PP::b \& }); \& print $json\->encode([ \& {name => \*(AqCPAN\*(Aq, id => 1, href => \*(Aqhttp://cpan.org\*(Aq} \& ]); \& # [{"id":1,"name":"CPAN","href":"http://cpan.org"}] .Ve .PP Note that \f(CW\*(C`sort_by\*(C'\fR affects all the plain hashes in the data structure. If you need finer control, \f(CW\*(C`tie\*(C'\fR necessary hashes with a module that implements ordered hash (such as Hash::Ordered and Tie::IxHash). \&\f(CW\*(C`canonical\*(C'\fR and \f(CW\*(C`sort_by\*(C'\fR don't affect the key order in \f(CW\*(C`tie\*(C'\fRd hashes. .PP .Vb 5 \& use Hash::Ordered; \& tie my %hash, \*(AqHash::Ordered\*(Aq, \& (name => \*(AqCPAN\*(Aq, id => 1, href => \*(Aqhttp://cpan.org\*(Aq); \& print $json\->encode([\e%hash]); \& # [{"name":"CPAN","id":1,"href":"http://cpan.org"}] # order is kept .Ve .SH "INCREMENTAL PARSING" .IX Header "INCREMENTAL PARSING" This section is also taken from \s-1JSON::XS.\s0 .PP In some cases, there is the need for incremental parsing of \s-1JSON\s0 texts. While this module always has to keep both \s-1JSON\s0 text and resulting Perl data structure in memory at one time, it does allow you to parse a \&\s-1JSON\s0 stream incrementally. It does so by accumulating text until it has a full \s-1JSON\s0 object, which it then can decode. This process is similar to using \f(CW\*(C`decode_prefix\*(C'\fR to see if a full \s-1JSON\s0 object is available, but is much more efficient (and can be implemented with a minimum of method calls). .PP \&\s-1JSON::PP\s0 will only attempt to parse the \s-1JSON\s0 text once it is sure it has enough text to get a decisive result, using a very simple but truly incremental parser. This means that it sometimes won't stop as early as the full parser, for example, it doesn't detect mismatched parentheses. The only thing it guarantees is that it starts decoding as soon as a syntactically valid \s-1JSON\s0 text has been seen. This means you need to set resource limits (e.g. \f(CW\*(C`max_size\*(C'\fR) to ensure the parser will stop parsing in the presence if syntax errors. .PP The following methods implement this incremental parser. .SS "incr_parse" .IX Subsection "incr_parse" .Vb 1 \& $json\->incr_parse( [$string] ) # void context \& \& $obj_or_undef = $json\->incr_parse( [$string] ) # scalar context \& \& @obj_or_empty = $json\->incr_parse( [$string] ) # list context .Ve .PP This is the central parsing function. It can both append new text and extract objects from the stream accumulated so far (both of these functions are optional). .PP If \f(CW$string\fR is given, then this string is appended to the already existing \s-1JSON\s0 fragment stored in the \f(CW$json\fR object. .PP After that, if the function is called in void context, it will simply return without doing anything further. This can be used to add more text in as many chunks as you want. .PP If the method is called in scalar context, then it will try to extract exactly \fIone\fR \s-1JSON\s0 object. If that is successful, it will return this object, otherwise it will return \f(CW\*(C`undef\*(C'\fR. If there is a parse error, this method will croak just as \f(CW\*(C`decode\*(C'\fR would do (one can then use \&\f(CW\*(C`incr_skip\*(C'\fR to skip the erroneous part). This is the most common way of using the method. .PP And finally, in list context, it will try to extract as many objects from the stream as it can find and return them, or the empty list otherwise. For this to work, there must be no separators (other than whitespace) between the \s-1JSON\s0 objects or arrays, instead they must be concatenated back-to-back. If an error occurs, an exception will be raised as in the scalar context case. Note that in this case, any previously-parsed \s-1JSON\s0 texts will be lost. .PP Example: Parse some \s-1JSON\s0 arrays/objects in a given string and return them. .PP .Vb 1 \& my @objs = JSON::PP\->new\->incr_parse ("[5][7][1,2]"); .Ve .SS "incr_text" .IX Subsection "incr_text" .Vb 1 \& $lvalue_string = $json\->incr_text .Ve .PP This method returns the currently stored \s-1JSON\s0 fragment as an lvalue, that is, you can manipulate it. This \fIonly\fR works when a preceding call to \&\f(CW\*(C`incr_parse\*(C'\fR in \fIscalar context\fR successfully returned an object. Under all other circumstances you must not call this function (I mean it. although in simple tests it might actually work, it \fIwill\fR fail under real world conditions). As a special exception, you can also call this method before having parsed anything. .PP That means you can only use this function to look at or manipulate text before or after complete \s-1JSON\s0 objects, not while the parser is in the middle of parsing a \s-1JSON\s0 object. .PP This function is useful in two cases: a) finding the trailing text after a \&\s-1JSON\s0 object or b) parsing multiple \s-1JSON\s0 objects separated by non-JSON text (such as commas). .SS "incr_skip" .IX Subsection "incr_skip" .Vb 1 \& $json\->incr_skip .Ve .PP This will reset the state of the incremental parser and will remove the parsed text from the input buffer so far. This is useful after \&\f(CW\*(C`incr_parse\*(C'\fR died, in which case the input buffer and incremental parser state is left unchanged, to skip the text parsed so far and to reset the parse state. .PP The difference to \f(CW\*(C`incr_reset\*(C'\fR is that only text until the parse error occurred is removed. .SS "incr_reset" .IX Subsection "incr_reset" .Vb 1 \& $json\->incr_reset .Ve .PP This completely resets the incremental parser, that is, after this call, it will be as if the parser had never parsed anything. .PP This is useful if you want to repeatedly parse \s-1JSON\s0 objects and want to ignore any trailing data, which means you have to reset the parser after each successful decode. .SH "MAPPING" .IX Header "MAPPING" Most of this section is also taken from \s-1JSON::XS.\s0 .PP This section describes how \s-1JSON::PP\s0 maps Perl values to \s-1JSON\s0 values and vice versa. These mappings are designed to \*(L"do the right thing\*(R" in most circumstances automatically, preserving round-tripping characteristics (what you put in comes out as something equivalent). .PP For the more enlightened: note that in the following descriptions, lowercase \fIperl\fR refers to the Perl interpreter, while uppercase \fIPerl\fR refers to the abstract Perl language itself. .SS "\s-1JSON\s0 \-> \s-1PERL\s0" .IX Subsection "JSON -> PERL" .IP "object" 4 .IX Item "object" A \s-1JSON\s0 object becomes a reference to a hash in Perl. No ordering of object keys is preserved (\s-1JSON\s0 does not preserve object key ordering itself). .IP "array" 4 .IX Item "array" A \s-1JSON\s0 array becomes a reference to an array in Perl. .IP "string" 4 .IX Item "string" A \s-1JSON\s0 string becomes a string scalar in Perl \- Unicode codepoints in \s-1JSON\s0 are represented by the same codepoints in the Perl string, so no manual decoding is necessary. .IP "number" 4 .IX Item "number" A \s-1JSON\s0 number becomes either an integer, numeric (floating point) or string scalar in perl, depending on its range and any fractional parts. On the Perl level, there is no difference between those as Perl handles all the conversion details, but an integer may take slightly less memory and might represent more values exactly than floating point numbers. .Sp If the number consists of digits only, \s-1JSON::PP\s0 will try to represent it as an integer value. If that fails, it will try to represent it as a numeric (floating point) value if that is possible without loss of precision. Otherwise it will preserve the number as a string value (in which case you lose roundtripping ability, as the \s-1JSON\s0 number will be re-encoded to a \s-1JSON\s0 string). .Sp Numbers containing a fractional or exponential part will always be represented as numeric (floating point) values, possibly at a loss of precision (in which case you might lose perfect roundtripping ability, but the \s-1JSON\s0 number will still be re-encoded as a \s-1JSON\s0 number). .Sp Note that precision is not accuracy \- binary floating point values cannot represent most decimal fractions exactly, and when converting from and to floating point, \s-1JSON::PP\s0 only guarantees precision up to but not including the least significant bit. .Sp When \f(CW\*(C`allow_bignum\*(C'\fR is enabled, big integer values and any numeric values will be converted into Math::BigInt and Math::BigFloat objects respectively, without becoming string scalars or losing precision. .IP "true, false" 4 .IX Item "true, false" These \s-1JSON\s0 atoms become \f(CW\*(C`JSON::PP::true\*(C'\fR and \f(CW\*(C`JSON::PP::false\*(C'\fR, respectively. They are overloaded to act almost exactly like the numbers \&\f(CW1\fR and \f(CW0\fR. You can check whether a scalar is a \s-1JSON\s0 boolean by using the \f(CW\*(C`JSON::PP::is_bool\*(C'\fR function. .IP "null" 4 .IX Item "null" A \s-1JSON\s0 null atom becomes \f(CW\*(C`undef\*(C'\fR in Perl. .ie n .IP "shell-style comments (""# \fItext\fP"")" 4 .el .IP "shell-style comments (\f(CW# \f(CItext\f(CW\fR)" 4 .IX Item "shell-style comments (# text)" As a nonstandard extension to the \s-1JSON\s0 syntax that is enabled by the \&\f(CW\*(C`relaxed\*(C'\fR setting, shell-style comments are allowed. They can start anywhere outside strings and go till the end of the line. .ie n .IP "tagged values (""(\fItag\fP)\fIvalue\fP"")." 4 .el .IP "tagged values (\f(CW(\f(CItag\f(CW)\f(CIvalue\f(CW\fR)." 4 .IX Item "tagged values ((tag)value)." Another nonstandard extension to the \s-1JSON\s0 syntax, enabled with the \&\f(CW\*(C`allow_tags\*(C'\fR setting, are tagged values. In this implementation, the \&\fItag\fR must be a perl package/class name encoded as a \s-1JSON\s0 string, and the \&\fIvalue\fR must be a \s-1JSON\s0 array encoding optional constructor arguments. .Sp See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .SS "\s-1PERL\s0 \-> \s-1JSON\s0" .IX Subsection "PERL -> JSON" The mapping from Perl to \s-1JSON\s0 is slightly more difficult, as Perl is a truly typeless language, so we can only guess which \s-1JSON\s0 type is meant by a Perl value. .IP "hash references" 4 .IX Item "hash references" Perl hash references become \s-1JSON\s0 objects. As there is no inherent ordering in hash keys (or \s-1JSON\s0 objects), they will usually be encoded in a pseudo-random order. \s-1JSON::PP\s0 can optionally sort the hash keys (determined by the \fIcanonical\fR flag and/or \fIsort_by\fR property), so the same data structure will serialise to the same \s-1JSON\s0 text (given same settings and version of \s-1JSON::PP\s0), but this incurs a runtime overhead and is only rarely useful, e.g. when you want to compare some \&\s-1JSON\s0 text against another for equality. .IP "array references" 4 .IX Item "array references" Perl array references become \s-1JSON\s0 arrays. .IP "other references" 4 .IX Item "other references" Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers \f(CW0\fR and \&\f(CW1\fR, which get turned into \f(CW\*(C`false\*(C'\fR and \f(CW\*(C`true\*(C'\fR atoms in \s-1JSON.\s0 You can also use \f(CW\*(C`JSON::PP::false\*(C'\fR and \f(CW\*(C`JSON::PP::true\*(C'\fR to improve readability. .Sp .Vb 1 \& to_json [\e0, JSON::PP::true] # yields [false,true] .Ve .IP "JSON::PP::true, JSON::PP::false" 4 .IX Item "JSON::PP::true, JSON::PP::false" These special values become \s-1JSON\s0 true and \s-1JSON\s0 false values, respectively. You can also use \f(CW\*(C`\e1\*(C'\fR and \f(CW\*(C`\e0\*(C'\fR directly if you want. .IP "JSON::PP::null" 4 .IX Item "JSON::PP::null" This special value becomes \s-1JSON\s0 null. .IP "blessed objects" 4 .IX Item "blessed objects" Blessed objects are not directly representable in \s-1JSON,\s0 but \f(CW\*(C`JSON::PP\*(C'\fR allows various ways of handling objects. See \*(L"\s-1OBJECT SERIALISATION\*(R"\s0, below, for details. .IP "simple scalars" 4 .IX Item "simple scalars" Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: \s-1JSON::PP\s0 will encode undefined scalars as \&\s-1JSON\s0 \f(CW\*(C`null\*(C'\fR values, scalars that have last been used in a string context before encoding as \s-1JSON\s0 strings, and anything else as number value: .Sp .Vb 4 \& # dump as number \& encode_json [2] # yields [2] \& encode_json [\-3.0e17] # yields [\-3e+17] \& my $value = 5; encode_json [$value] # yields [5] \& \& # used as string, so dump as string \& print $value; \& encode_json [$value] # yields ["5"] \& \& # undef becomes null \& encode_json [undef] # yields [null] .Ve .Sp You can force the type to be a \s-1JSON\s0 string by stringifying it: .Sp .Vb 5 \& my $x = 3.1; # some variable containing a number \& "$x"; # stringified \& $x .= ""; # another, more awkward way to stringify \& print $x; # perl does it for you, too, quite often \& # (but for older perls) .Ve .Sp You can force the type to be a \s-1JSON\s0 number by numifying it: .Sp .Vb 3 \& my $x = "3"; # some variable containing a string \& $x += 0; # numify it, ensuring it will be dumped as a number \& $x *= 1; # same thing, the choice is yours. .Ve .Sp You can not currently force the type in other, less obscure, ways. .Sp Since version 2.91_01, \s-1JSON::PP\s0 uses a different number detection logic that converts a scalar that is possible to turn into a number safely. The new logic is slightly faster, and tends to help people who use older perl or who want to encode complicated data structure. However, this may results in a different \s-1JSON\s0 text from the one \s-1JSON::XS\s0 encodes (and thus may break tests that compare entire \s-1JSON\s0 texts). If you do need the previous behavior for compatibility or for finer control, set \s-1PERL_JSON_PP_USE_B\s0 environmental variable to true before you \&\f(CW\*(C`use\*(C'\fR \s-1JSON::PP\s0 (or \s-1JSON\s0.pm). .Sp Note that numerical precision has the same meaning as under Perl (so binary to decimal conversion follows the same rules as in Perl, which can differ to other languages). Also, your perl interpreter might expose extensions to the floating point numbers of your platform, such as infinities or NaN's \- these cannot be represented in \s-1JSON,\s0 and it is an error to pass those in. .Sp \&\s-1JSON::PP\s0 (and \s-1JSON::XS\s0) trusts what you pass to \f(CW\*(C`encode\*(C'\fR method (or \f(CW\*(C`encode_json\*(C'\fR function) is a clean, validated data structure with values that can be represented as valid \s-1JSON\s0 values only, because it's not from an external data source (as opposed to \s-1JSON\s0 texts you pass to \&\f(CW\*(C`decode\*(C'\fR or \f(CW\*(C`decode_json\*(C'\fR, which \s-1JSON::PP\s0 considers tainted and doesn't trust). As \s-1JSON::PP\s0 doesn't know exactly what you and consumers of your \s-1JSON\s0 texts want the unexpected values to be (you may want to convert them into null, or to stringify them with or without normalisation (string representation of infinities/NaN may vary depending on platforms), or to croak without conversion), you're advised to do what you and your consumers need before you encode, and also not to numify values that may start with values that look like a number (including infinities/NaN), without validating. .SS "\s-1OBJECT SERIALISATION\s0" .IX Subsection "OBJECT SERIALISATION" As \s-1JSON\s0 cannot directly represent Perl objects, you have to choose between a pure \s-1JSON\s0 representation (without the ability to deserialise the object automatically again), and a nonstandard extension to the \s-1JSON\s0 syntax, tagged values. .PP \fI\s-1SERIALISATION\s0\fR .IX Subsection "SERIALISATION" .PP What happens when \f(CW\*(C`JSON::PP\*(C'\fR encounters a Perl object depends on the \&\f(CW\*(C`allow_blessed\*(C'\fR, \f(CW\*(C`convert_blessed\*(C'\fR, \f(CW\*(C`allow_tags\*(C'\fR and \f(CW\*(C`allow_bignum\*(C'\fR settings, which are used in this order: .ie n .IP "1. ""allow_tags"" is enabled and the object has a ""FREEZE"" method." 4 .el .IP "1. \f(CWallow_tags\fR is enabled and the object has a \f(CWFREEZE\fR method." 4 .IX Item "1. allow_tags is enabled and the object has a FREEZE method." In this case, \f(CW\*(C`JSON::PP\*(C'\fR creates a tagged \s-1JSON\s0 value, using a nonstandard extension to the \s-1JSON\s0 syntax. .Sp This works by invoking the \f(CW\*(C`FREEZE\*(C'\fR method on the object, with the first argument being the object to serialise, and the second argument being the constant string \f(CW\*(C`JSON\*(C'\fR to distinguish it from other serialisers. .Sp The \f(CW\*(C`FREEZE\*(C'\fR method can return any number of values (i.e. zero or more). These values and the paclkage/classname of the object will then be encoded as a tagged \s-1JSON\s0 value in the following format: .Sp .Vb 1 \& ("classname")[FREEZE return values...] .Ve .Sp e.g.: .Sp .Vb 3 \& ("URI")["http://www.google.com/"] \& ("MyDate")[2013,10,29] \& ("ImageData::JPEG")["Z3...VlCg=="] .Ve .Sp For example, the hypothetical \f(CW\*(C`My::Object\*(C'\fR \f(CW\*(C`FREEZE\*(C'\fR method might use the objects \f(CW\*(C`type\*(C'\fR and \f(CW\*(C`id\*(C'\fR members to encode the object: .Sp .Vb 2 \& sub My::Object::FREEZE { \& my ($self, $serialiser) = @_; \& \& ($self\->{type}, $self\->{id}) \& } .Ve .ie n .IP "2. ""convert_blessed"" is enabled and the object has a ""TO_JSON"" method." 4 .el .IP "2. \f(CWconvert_blessed\fR is enabled and the object has a \f(CWTO_JSON\fR method." 4 .IX Item "2. convert_blessed is enabled and the object has a TO_JSON method." In this case, the \f(CW\*(C`TO_JSON\*(C'\fR method of the object is invoked in scalar context. It must return a single scalar that can be directly encoded into \&\s-1JSON.\s0 This scalar replaces the object in the \s-1JSON\s0 text. .Sp For example, the following \f(CW\*(C`TO_JSON\*(C'\fR method will convert all \s-1URI\s0 objects to \s-1JSON\s0 strings when serialised. The fact that these values originally were \s-1URI\s0 objects is lost. .Sp .Vb 4 \& sub URI::TO_JSON { \& my ($uri) = @_; \& $uri\->as_string \& } .Ve .ie n .IP "3. ""allow_bignum"" is enabled and the object is a ""Math::BigInt"" or ""Math::BigFloat""." 4 .el .IP "3. \f(CWallow_bignum\fR is enabled and the object is a \f(CWMath::BigInt\fR or \f(CWMath::BigFloat\fR." 4 .IX Item "3. allow_bignum is enabled and the object is a Math::BigInt or Math::BigFloat." The object will be serialised as a \s-1JSON\s0 number value. .ie n .IP "4. ""allow_blessed"" is enabled." 4 .el .IP "4. \f(CWallow_blessed\fR is enabled." 4 .IX Item "4. allow_blessed is enabled." The object will be serialised as a \s-1JSON\s0 null value. .IP "5. none of the above" 4 .IX Item "5. none of the above" If none of the settings are enabled or the respective methods are missing, \&\f(CW\*(C`JSON::PP\*(C'\fR throws an exception. .PP \fI\s-1DESERIALISATION\s0\fR .IX Subsection "DESERIALISATION" .PP For deserialisation there are only two cases to consider: either nonstandard tagging was used, in which case \f(CW\*(C`allow_tags\*(C'\fR decides, or objects cannot be automatically be deserialised, in which case you can use postprocessing or the \f(CW\*(C`filter_json_object\*(C'\fR or \&\f(CW\*(C`filter_json_single_key_object\*(C'\fR callbacks to get some real objects our of your \s-1JSON.\s0 .PP This section only considers the tagged value case: a tagged \s-1JSON\s0 object is encountered during decoding and \f(CW\*(C`allow_tags\*(C'\fR is disabled, a parse error will result (as if tagged values were not part of the grammar). .PP If \f(CW\*(C`allow_tags\*(C'\fR is enabled, \f(CW\*(C`JSON::PP\*(C'\fR will look up the \f(CW\*(C`THAW\*(C'\fR method of the package/classname used during serialisation (it will not attempt to load the package as a Perl module). If there is no such method, the decoding will fail with an error. .PP Otherwise, the \f(CW\*(C`THAW\*(C'\fR method is invoked with the classname as first argument, the constant string \f(CW\*(C`JSON\*(C'\fR as second argument, and all the values from the \s-1JSON\s0 array (the values originally returned by the \&\f(CW\*(C`FREEZE\*(C'\fR method) as remaining arguments. .PP The method must then return the object. While technically you can return any Perl scalar, you might have to enable the \f(CW\*(C`allow_nonref\*(C'\fR setting to make that work in all cases, so better return an actual blessed reference. .PP As an example, let's implement a \f(CW\*(C`THAW\*(C'\fR function that regenerates the \&\f(CW\*(C`My::Object\*(C'\fR from the \f(CW\*(C`FREEZE\*(C'\fR example earlier: .PP .Vb 2 \& sub My::Object::THAW { \& my ($class, $serialiser, $type, $id) = @_; \& \& $class\->new (type => $type, id => $id) \& } .Ve .SH "ENCODING/CODESET FLAG NOTES" .IX Header "ENCODING/CODESET FLAG NOTES" This section is taken from \s-1JSON::XS.\s0 .PP The interested reader might have seen a number of flags that signify encodings or codesets \- \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR. There seems to be some confusion on what these do, so here is a short comparison: .PP \&\f(CW\*(C`utf8\*(C'\fR controls whether the \s-1JSON\s0 text created by \f(CW\*(C`encode\*(C'\fR (and expected by \f(CW\*(C`decode\*(C'\fR) is \s-1UTF\-8\s0 encoded or not, while \f(CW\*(C`latin1\*(C'\fR and \f(CW\*(C`ascii\*(C'\fR only control whether \f(CW\*(C`encode\*(C'\fR escapes character values outside their respective codeset range. Neither of these flags conflict with each other, although some combinations make less sense than others. .PP Care has been taken to make all flags symmetrical with respect to \&\f(CW\*(C`encode\*(C'\fR and \f(CW\*(C`decode\*(C'\fR, that is, texts encoded with any combination of these flag values will be correctly decoded when the same flags are used \&\- in general, if you use different flag settings while encoding vs. when decoding you likely have a bug somewhere. .PP Below comes a verbose discussion of these flags. Note that a \*(L"codeset\*(R" is simply an abstract set of character-codepoint pairs, while an encoding takes those codepoint numbers and \fIencodes\fR them, in our case into octets. Unicode is (among other things) a codeset, \s-1UTF\-8\s0 is an encoding, and \s-1ISO\-8859\-1\s0 (= latin 1) and \s-1ASCII\s0 are both codesets \fIand\fR encodings at the same time, which can be confusing. .ie n .IP """utf8"" flag disabled" 4 .el .IP "\f(CWutf8\fR flag disabled" 4 .IX Item "utf8 flag disabled" When \f(CW\*(C`utf8\*(C'\fR is disabled (the default), then \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR generate and expect Unicode strings, that is, characters with high ordinal Unicode values (> 255) will be encoded as such characters, and likewise such characters are decoded as-is, no changes to them will be done, except \&\*(L"(re\-)interpreting\*(R" them as Unicode codepoints or Unicode characters, respectively (to Perl, these are the same thing in strings unless you do funny/weird/dumb stuff). .Sp This is useful when you want to do the encoding yourself (e.g. when you want to have \s-1UTF\-16\s0 encoded \s-1JSON\s0 texts) or when some other layer does the encoding for you (for example, when printing to a terminal using a filehandle that transparently encodes to \s-1UTF\-8\s0 you certainly do \s-1NOT\s0 want to \s-1UTF\-8\s0 encode your data first and have Perl encode it another time). .ie n .IP """utf8"" flag enabled" 4 .el .IP "\f(CWutf8\fR flag enabled" 4 .IX Item "utf8 flag enabled" If the \f(CW\*(C`utf8\*(C'\fR\-flag is enabled, \f(CW\*(C`encode\*(C'\fR/\f(CW\*(C`decode\*(C'\fR will encode all characters using the corresponding \s-1UTF\-8\s0 multi-byte sequence, and will expect your input strings to be encoded as \s-1UTF\-8,\s0 that is, no \*(L"character\*(R" of the input string must have any value > 255, as \s-1UTF\-8\s0 does not allow that. .Sp The \f(CW\*(C`utf8\*(C'\fR flag therefore switches between two modes: disabled means you will get a Unicode string in Perl, enabled means you get an \s-1UTF\-8\s0 encoded octet/binary string in Perl. .ie n .IP """latin1"" or ""ascii"" flags enabled" 4 .el .IP "\f(CWlatin1\fR or \f(CWascii\fR flags enabled" 4 .IX Item "latin1 or ascii flags enabled" With \f(CW\*(C`latin1\*(C'\fR (or \f(CW\*(C`ascii\*(C'\fR) enabled, \f(CW\*(C`encode\*(C'\fR will escape characters with ordinal values > 255 (> 127 with \f(CW\*(C`ascii\*(C'\fR) and encode the remaining characters as specified by the \f(CW\*(C`utf8\*(C'\fR flag. .Sp If \f(CW\*(C`utf8\*(C'\fR is disabled, then the result is also correctly encoded in those character sets (as both are proper subsets of Unicode, meaning that a Unicode string with all character values < 256 is the same thing as a \&\s-1ISO\-8859\-1\s0 string, and a Unicode string with all character values < 128 is the same thing as an \s-1ASCII\s0 string in Perl). .Sp If \f(CW\*(C`utf8\*(C'\fR is enabled, you still get a correct UTF\-8\-encoded string, regardless of these flags, just some more characters will be escaped using \&\f(CW\*(C`\euXXXX\*(C'\fR then before. .Sp Note that \s-1ISO\-8859\-1\-\s0\fIencoded\fR strings are not compatible with \s-1UTF\-8\s0 encoding, while ASCII-encoded strings are. That is because the \s-1ISO\-8859\-1\s0 encoding is \s-1NOT\s0 a subset of \s-1UTF\-8\s0 (despite the \s-1ISO\-8859\-1\s0 \fIcodeset\fR being a subset of Unicode), while \s-1ASCII\s0 is. .Sp Surprisingly, \f(CW\*(C`decode\*(C'\fR will ignore these flags and so treat all input values as governed by the \f(CW\*(C`utf8\*(C'\fR flag. If it is disabled, this allows you to decode \s-1ISO\-8859\-1\-\s0 and ASCII-encoded strings, as both strict subsets of Unicode. If it is enabled, you can correctly decode \s-1UTF\-8\s0 encoded strings. .Sp So neither \f(CW\*(C`latin1\*(C'\fR nor \f(CW\*(C`ascii\*(C'\fR are incompatible with the \f(CW\*(C`utf8\*(C'\fR flag \- they only govern when the \s-1JSON\s0 output engine escapes a character or not. .Sp The main use for \f(CW\*(C`latin1\*(C'\fR is to relatively efficiently store binary data as \s-1JSON,\s0 at the expense of breaking compatibility with most \s-1JSON\s0 decoders. .Sp The main use for \f(CW\*(C`ascii\*(C'\fR is to force the output to not contain characters with values > 127, which means you can interpret the resulting string as \s-1UTF\-8, ISO\-8859\-1, ASCII, KOI8\-R\s0 or most about any character set and 8\-bit\-encoding, and still get the same data structure back. This is useful when your channel for \s-1JSON\s0 transfer is not 8\-bit clean or the encoding might be mangled in between (e.g. in mail), and works because \s-1ASCII\s0 is a proper subset of most 8\-bit and multibyte encodings in use in the world. .SH "BUGS" .IX Header "BUGS" Please report bugs on a specific behavior of this module to \s-1RT\s0 or GitHub issues (preferred): .PP .PP .PP As for new features and requests to change common behaviors, please ask the author of \s-1JSON::XS\s0 (Marc Lehmann, ) first, by email (important!), to keep compatibility among \s-1JSON\s0.pm backends. .PP Generally speaking, if you need something special for you, you are advised to create a new module, maybe based on JSON::Tiny, which is smaller and written in a much cleaner way than this module. .SH "SEE ALSO" .IX Header "SEE ALSO" The \fIjson_pp\fR command line utility for quick experiments. .PP \&\s-1JSON::XS\s0, Cpanel::JSON::XS, and JSON::Tiny for faster alternatives. \&\s-1JSON\s0 and JSON::MaybeXS for easy migration. .PP JSON::backportPP::Compat5005 and JSON::backportPP::Compat5006 for older perl users. .PP \&\s-1RFC4627\s0 () .PP \&\s-1RFC7159\s0 () .PP \&\s-1RFC8259\s0 () .SH "AUTHOR" .IX Header "AUTHOR" Makamaka Hannyaharamitu, .SH "CURRENT MAINTAINER" .IX Header "CURRENT MAINTAINER" Kenichi Ishigaki, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2007\-2016 by Makamaka Hannyaharamitu .PP Most of the documentation is taken from \s-1JSON::XS\s0 by Marc Lehmann .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/HTTP::Tiny.3pm000044400000067046152462503210010420 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "HTTP::Tiny 3" .TH HTTP::Tiny 3 "2021-08-02" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" HTTP::Tiny \- A small, simple, correct HTTP/1.1 client .SH "VERSION" .IX Header "VERSION" version 0.078 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use HTTP::Tiny; \& \& my $response = HTTP::Tiny\->new\->get(\*(Aqhttp://example.com/\*(Aq); \& \& die "Failed!\en" unless $response\->{success}; \& \& print "$response\->{status} $response\->{reason}\en"; \& \& while (my ($k, $v) = each %{$response\->{headers}}) { \& for (ref $v eq \*(AqARRAY\*(Aq ? @$v : $v) { \& print "$k: $_\en"; \& } \& } \& \& print $response\->{content} if length $response\->{content}; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is a very simple \s-1HTTP/1.1\s0 client, designed for doing simple requests without the overhead of a large framework like LWP::UserAgent. .PP It is more correct and more complete than HTTP::Lite. It supports proxies and redirection. It also correctly resumes after \s-1EINTR.\s0 .PP If IO::Socket::IP 0.25 or later is installed, HTTP::Tiny will use it instead of IO::Socket::INET for transparent support for both IPv4 and IPv6. .PP Cookie support requires HTTP::CookieJar or an equivalent class. .SH "METHODS" .IX Header "METHODS" .SS "new" .IX Subsection "new" .Vb 1 \& $http = HTTP::Tiny\->new( %attributes ); .Ve .PP This constructor returns a new HTTP::Tiny object. Valid attributes include: .IP "\(bu" 4 \&\f(CW\*(C`agent\*(C'\fR — A user-agent string (defaults to 'HTTP\-Tiny/$VERSION'). If \f(CW\*(C`agent\*(C'\fR — ends in a space character, the default user-agent string is appended. .IP "\(bu" 4 \&\f(CW\*(C`cookie_jar\*(C'\fR — An instance of HTTP::CookieJar — or equivalent class that supports the \f(CW\*(C`add\*(C'\fR and \f(CW\*(C`cookie_header\*(C'\fR methods .IP "\(bu" 4 \&\f(CW\*(C`default_headers\*(C'\fR — A hashref of default headers to apply to requests .IP "\(bu" 4 \&\f(CW\*(C`local_address\*(C'\fR — The local \s-1IP\s0 address to bind to .IP "\(bu" 4 \&\f(CW\*(C`keep_alive\*(C'\fR — Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1) .IP "\(bu" 4 \&\f(CW\*(C`max_redirect\*(C'\fR — Maximum number of redirects allowed (defaults to 5) .IP "\(bu" 4 \&\f(CW\*(C`max_size\*(C'\fR — Maximum response size in bytes (only when not using a data callback). If defined, requests with responses larger than this will return a 599 status code. .IP "\(bu" 4 \&\f(CW\*(C`http_proxy\*(C'\fR — \s-1URL\s0 of a proxy server to use for \s-1HTTP\s0 connections (default is \f(CW$ENV{http_proxy}\fR — if set) .IP "\(bu" 4 \&\f(CW\*(C`https_proxy\*(C'\fR — \s-1URL\s0 of a proxy server to use for \s-1HTTPS\s0 connections (default is \f(CW$ENV{https_proxy}\fR — if set) .IP "\(bu" 4 \&\f(CW\*(C`proxy\*(C'\fR — \s-1URL\s0 of a generic proxy server for both \s-1HTTP\s0 and \s-1HTTPS\s0 connections (default is \f(CW$ENV{all_proxy}\fR — if set) .IP "\(bu" 4 \&\f(CW\*(C`no_proxy\*(C'\fR — List of domain suffixes that should not be proxied. Must be a comma-separated string or an array reference. (default is \f(CW$ENV{no_proxy}\fR —) .IP "\(bu" 4 \&\f(CW\*(C`timeout\*(C'\fR — Request timeout in seconds (default is 60) If a socket open, read or write takes longer than the timeout, the request response status code will be 599. .IP "\(bu" 4 \&\f(CW\*(C`verify_SSL\*(C'\fR — A boolean that indicates whether to validate the \s-1SSL\s0 certificate of an \f(CW\*(C`https\*(C'\fR — connection (default is false) .IP "\(bu" 4 \&\f(CW\*(C`SSL_options\*(C'\fR — A hashref of \f(CW\*(C`SSL_*\*(C'\fR — options to pass through to IO::Socket::SSL .PP An accessor/mutator method exists for each attribute. .PP Passing an explicit \f(CW\*(C`undef\*(C'\fR for \f(CW\*(C`proxy\*(C'\fR, \f(CW\*(C`http_proxy\*(C'\fR or \f(CW\*(C`https_proxy\*(C'\fR will prevent getting the corresponding proxies from the environment. .PP Errors during request execution will result in a pseudo-HTTP status code of 599 and a reason of \*(L"Internal Exception\*(R". The content field in the response will contain the text of the error. .PP The \f(CW\*(C`keep_alive\*(C'\fR parameter enables a persistent connection, but only to a single destination scheme, host and port. If any connection-relevant attributes are modified via accessor, or if the process \s-1ID\s0 or thread \s-1ID\s0 change, the persistent connection will be dropped. If you want persistent connections across multiple destinations, use multiple HTTP::Tiny objects. .PP See \*(L"\s-1SSL SUPPORT\*(R"\s0 for more on the \f(CW\*(C`verify_SSL\*(C'\fR and \f(CW\*(C`SSL_options\*(C'\fR attributes. .SS "get|head|put|post|patch|delete" .IX Subsection "get|head|put|post|patch|delete" .Vb 3 \& $response = $http\->get($url); \& $response = $http\->get($url, \e%options); \& $response = $http\->head($url); .Ve .PP These methods are shorthand for calling \f(CW\*(C`request()\*(C'\fR for the given method. The \&\s-1URL\s0 must have unsafe characters escaped and international domain names encoded. See \f(CW\*(C`request()\*(C'\fR for valid options and a description of the response. .PP The \f(CW\*(C`success\*(C'\fR field of the response will be true if the status code is 2XX. .SS "post_form" .IX Subsection "post_form" .Vb 2 \& $response = $http\->post_form($url, $form_data); \& $response = $http\->post_form($url, $form_data, \e%options); .Ve .PP This method executes a \f(CW\*(C`POST\*(C'\fR request and sends the key/value pairs from a form data hash or array reference to the given \s-1URL\s0 with a \f(CW\*(C`content\-type\*(C'\fR of \&\f(CW\*(C`application/x\-www\-form\-urlencoded\*(C'\fR. If data is provided as an array reference, the order is preserved; if provided as a hash reference, the terms are sorted on key and value for consistency. See documentation for the \&\f(CW\*(C`www_form_urlencode\*(C'\fR method for details on the encoding. .PP The \s-1URL\s0 must have unsafe characters escaped and international domain names encoded. See \f(CW\*(C`request()\*(C'\fR for valid options and a description of the response. Any \f(CW\*(C`content\-type\*(C'\fR header or content in the options hashref will be ignored. .PP The \f(CW\*(C`success\*(C'\fR field of the response will be true if the status code is 2XX. .SS "mirror" .IX Subsection "mirror" .Vb 4 \& $response = $http\->mirror($url, $file, \e%options) \& if ( $response\->{success} ) { \& print "$file is up to date\en"; \& } .Ve .PP Executes a \f(CW\*(C`GET\*(C'\fR request for the \s-1URL\s0 and saves the response body to the file name provided. The \s-1URL\s0 must have unsafe characters escaped and international domain names encoded. If the file already exists, the request will include an \&\f(CW\*(C`If\-Modified\-Since\*(C'\fR header with the modification timestamp of the file. You may specify a different \f(CW\*(C`If\-Modified\-Since\*(C'\fR header yourself in the \f(CW\*(C`$options\->{headers}\*(C'\fR hash. .PP The \f(CW\*(C`success\*(C'\fR field of the response will be true if the status code is 2XX or if the status code is 304 (unmodified). .PP If the file was modified and the server response includes a properly formatted \f(CW\*(C`Last\-Modified\*(C'\fR header, the file modification time will be updated accordingly. .SS "request" .IX Subsection "request" .Vb 2 \& $response = $http\->request($method, $url); \& $response = $http\->request($method, $url, \e%options); .Ve .PP Executes an \s-1HTTP\s0 request of the given method type ('\s-1GET\s0', '\s-1HEAD\s0', '\s-1POST\s0', \&'\s-1PUT\s0', etc.) on the given \s-1URL.\s0 The \s-1URL\s0 must have unsafe characters escaped and international domain names encoded. .PP \&\fB\s-1NOTE\s0\fR: Method names are \fBcase-sensitive\fR per the \s-1HTTP/1.1\s0 specification. Don't use \f(CW\*(C`get\*(C'\fR when you really want \f(CW\*(C`GET\*(C'\fR. See \s-1LIMITATIONS\s0 for how this applies to redirection. .PP If the \s-1URL\s0 includes a \*(L"user:password\*(R" stanza, they will be used for Basic-style authorization headers. (Authorization headers will not be included in a redirected request.) For example: .PP .Vb 1 \& $http\->request(\*(AqGET\*(Aq, \*(Aqhttp://Aladdin:open sesame@example.com/\*(Aq); .Ve .PP If the \*(L"user:password\*(R" stanza contains reserved characters, they must be percent-escaped: .PP .Vb 1 \& $http\->request(\*(AqGET\*(Aq, \*(Aqhttp://john%40example.com:password@example.com/\*(Aq); .Ve .PP A hashref of options may be appended to modify the request. .PP Valid options are: .IP "\(bu" 4 \&\f(CW\*(C`headers\*(C'\fR — A hashref containing headers to include with the request. If the value for a header is an array reference, the header will be output multiple times with each value in the array. These headers over-write any default headers. .IP "\(bu" 4 \&\f(CW\*(C`content\*(C'\fR — A scalar to include as the body of the request \s-1OR\s0 a code reference that will be called iteratively to produce the body of the request .IP "\(bu" 4 \&\f(CW\*(C`trailer_callback\*(C'\fR — A code reference that will be called if it exists to provide a hashref of trailing headers (only used with chunked transfer-encoding) .IP "\(bu" 4 \&\f(CW\*(C`data_callback\*(C'\fR — A code reference that will be called for each chunks of the response body received. .IP "\(bu" 4 \&\f(CW\*(C`peer\*(C'\fR — Override host resolution and force all connections to go only to a specific peer address, regardless of the \s-1URL\s0 of the request. This will include any redirections! This options should be used with extreme caution (e.g. debugging or very special circumstances). It can be given as either a scalar or a code reference that will receive the hostname and whose response will be taken as the address. .PP The \f(CW\*(C`Host\*(C'\fR header is generated from the \s-1URL\s0 in accordance with \s-1RFC 2616.\s0 It is a fatal error to specify \f(CW\*(C`Host\*(C'\fR in the \f(CW\*(C`headers\*(C'\fR option. Other headers may be ignored or overwritten if necessary for transport compliance. .PP If the \f(CW\*(C`content\*(C'\fR option is a code reference, it will be called iteratively to provide the content body of the request. It should return the empty string or undef when the iterator is exhausted. .PP If the \f(CW\*(C`content\*(C'\fR option is the empty string, no \f(CW\*(C`content\-type\*(C'\fR or \&\f(CW\*(C`content\-length\*(C'\fR headers will be generated. .PP If the \f(CW\*(C`data_callback\*(C'\fR option is provided, it will be called iteratively until the entire response body is received. The first argument will be a string containing a chunk of the response body, the second argument will be the in-progress response hash reference, as described below. (This allows customizing the action of the callback based on the \f(CW\*(C`status\*(C'\fR or \f(CW\*(C`headers\*(C'\fR received prior to the content body.) .PP The \f(CW\*(C`request\*(C'\fR method returns a hashref containing the response. The hashref will have the following keys: .IP "\(bu" 4 \&\f(CW\*(C`success\*(C'\fR — Boolean indicating whether the operation returned a 2XX status code .IP "\(bu" 4 \&\f(CW\*(C`url\*(C'\fR — \s-1URL\s0 that provided the response. This is the \s-1URL\s0 of the request unless there were redirections, in which case it is the last \s-1URL\s0 queried in a redirection chain .IP "\(bu" 4 \&\f(CW\*(C`status\*(C'\fR — The \s-1HTTP\s0 status code of the response .IP "\(bu" 4 \&\f(CW\*(C`reason\*(C'\fR — The response phrase returned by the server .IP "\(bu" 4 \&\f(CW\*(C`content\*(C'\fR — The body of the response. If the response does not have any content or if a data callback is provided to consume the response body, this will be the empty string .IP "\(bu" 4 \&\f(CW\*(C`headers\*(C'\fR — A hashref of header fields. All header field names will be normalized to be lower case. If a header is repeated, the value will be an arrayref; it will otherwise be a scalar string containing the value .IP "\(bu" 4 \&\f(CW\*(C`protocol\*(C'\fR \- If this field exists, it is the protocol of the response such as \s-1HTTP/1.0\s0 or \s-1HTTP/1.1\s0 .IP "\(bu" 4 \&\f(CW\*(C`redirects\*(C'\fR If this field exists, it is an arrayref of response hash references from redirects in the same order that redirections occurred. If it does not exist, then no redirections occurred. .PP On an error during the execution of the request, the \f(CW\*(C`status\*(C'\fR field will contain 599, and the \f(CW\*(C`content\*(C'\fR field will contain the text of the error. .SS "www_form_urlencode" .IX Subsection "www_form_urlencode" .Vb 2 \& $params = $http\->www_form_urlencode( $data ); \& $response = $http\->get("http://example.com/query?$params"); .Ve .PP This method converts the key/value pairs from a data hash or array reference into a \f(CW\*(C`x\-www\-form\-urlencoded\*(C'\fR string. The keys and values from the data reference will be \s-1UTF\-8\s0 encoded and escaped per \s-1RFC 3986.\s0 If a value is an array reference, the key will be repeated with each of the values of the array reference. If data is provided as a hash reference, the key/value pairs in the resulting string will be sorted by key and value for consistent ordering. .SS "can_ssl" .IX Subsection "can_ssl" .Vb 3 \& $ok = HTTP::Tiny\->can_ssl; \& ($ok, $why) = HTTP::Tiny\->can_ssl; \& ($ok, $why) = $http\->can_ssl; .Ve .PP Indicates if \s-1SSL\s0 support is available. When called as a class object, it checks for the correct version of Net::SSLeay and IO::Socket::SSL. When called as an object methods, if \f(CW\*(C`SSL_verify\*(C'\fR is true or if \f(CW\*(C`SSL_verify_mode\*(C'\fR is set in \f(CW\*(C`SSL_options\*(C'\fR, it checks that a \s-1CA\s0 file is available. .PP In scalar context, returns a boolean indicating if \s-1SSL\s0 is available. In list context, returns the boolean and a (possibly multi-line) string of errors indicating why \s-1SSL\s0 isn't available. .SS "connected" .IX Subsection "connected" .Vb 2 \& $host = $http\->connected; \& ($host, $port) = $http\->connected; .Ve .PP Indicates if a connection to a peer is being kept alive, per the \f(CW\*(C`keep_alive\*(C'\fR option. .PP In scalar context, returns the peer host and port, joined with a colon, or \&\f(CW\*(C`undef\*(C'\fR (if no peer is connected). In list context, returns the peer host and port or an empty list (if no peer is connected). .PP \&\fBNote\fR: This method cannot reliably be used to discover whether the remote host has closed its end of the socket. .SH "SSL SUPPORT" .IX Header "SSL SUPPORT" Direct \f(CW\*(C`https\*(C'\fR connections are supported only if IO::Socket::SSL 1.56 or greater and Net::SSLeay 1.49 or greater are installed. An error will occur if new enough versions of these modules are not installed or if the \s-1SSL\s0 encryption fails. You can also use \f(CW\*(C`HTTP::Tiny::can_ssl()\*(C'\fR utility function that returns boolean to see if the required modules are installed. .PP An \f(CW\*(C`https\*(C'\fR connection may be made via an \f(CW\*(C`http\*(C'\fR proxy that supports the \s-1CONNECT\s0 command (i.e. \s-1RFC 2817\s0). You may not proxy \f(CW\*(C`https\*(C'\fR via a proxy that itself requires \f(CW\*(C`https\*(C'\fR to communicate. .PP \&\s-1SSL\s0 provides two distinct capabilities: .IP "\(bu" 4 Encrypted communication channel .IP "\(bu" 4 Verification of server identity .PP \&\fBBy default, HTTP::Tiny does not verify server identity\fR. .PP Server identity verification is controversial and potentially tricky because it depends on a (usually paid) third-party Certificate Authority (\s-1CA\s0) trust model to validate a certificate as legitimate. This discriminates against servers with self-signed certificates or certificates signed by free, community-driven \&\s-1CA\s0's such as CAcert.org . .PP By default, HTTP::Tiny does not make any assumptions about your trust model, threat level or risk tolerance. It just aims to give you an encrypted channel when you need one. .PP Setting the \f(CW\*(C`verify_SSL\*(C'\fR attribute to a true value will make HTTP::Tiny verify that an \s-1SSL\s0 connection has a valid \s-1SSL\s0 certificate corresponding to the host name of the connection and that the \s-1SSL\s0 certificate has been verified by a \s-1CA.\s0 Assuming you trust the \s-1CA,\s0 this will protect against a man-in-the-middle attack . If you are concerned about security, you should enable this option. .PP Certificate verification requires a file containing trusted \s-1CA\s0 certificates. .PP If the environment variable \f(CW\*(C`SSL_CERT_FILE\*(C'\fR is present, HTTP::Tiny will try to find a \s-1CA\s0 certificate file in that location. .PP If the Mozilla::CA module is installed, HTTP::Tiny will use the \s-1CA\s0 file included with it as a source of trusted \s-1CA\s0's. (This means you trust Mozilla, the author of Mozilla::CA, the \s-1CPAN\s0 mirror where you got Mozilla::CA, the toolchain used to install it, and your operating system security, right?) .PP If that module is not available, then HTTP::Tiny will search several system-specific default locations for a \s-1CA\s0 certificate file: .IP "\(bu" 4 /etc/ssl/certs/ca\-certificates.crt .IP "\(bu" 4 /etc/pki/tls/certs/ca\-bundle.crt .IP "\(bu" 4 /etc/ssl/ca\-bundle.pem .PP An error will be occur if \f(CW\*(C`verify_SSL\*(C'\fR is true and no \s-1CA\s0 certificate file is available. .PP If you desire complete control over \s-1SSL\s0 connections, the \f(CW\*(C`SSL_options\*(C'\fR attribute lets you provide a hash reference that will be passed through to \&\f(CW\*(C`IO::Socket::SSL::start_SSL()\*(C'\fR, overriding any options set by HTTP::Tiny. For example, to provide your own trusted \s-1CA\s0 file: .PP .Vb 3 \& SSL_options => { \& SSL_ca_file => $file_path, \& } .Ve .PP The \f(CW\*(C`SSL_options\*(C'\fR attribute could also be used for such things as providing a client certificate for authentication to a server or controlling the choice of cipher used for the \s-1SSL\s0 connection. See IO::Socket::SSL documentation for details. .SH "PROXY SUPPORT" .IX Header "PROXY SUPPORT" HTTP::Tiny can proxy both \f(CW\*(C`http\*(C'\fR and \f(CW\*(C`https\*(C'\fR requests. Only Basic proxy authorization is supported and it must be provided as part of the proxy \s-1URL:\s0 \&\f(CW\*(C`http://user:pass@proxy.example.com/\*(C'\fR. .PP HTTP::Tiny supports the following proxy environment variables: .IP "\(bu" 4 http_proxy or \s-1HTTP_PROXY\s0 .IP "\(bu" 4 https_proxy or \s-1HTTPS_PROXY\s0 .IP "\(bu" 4 all_proxy or \s-1ALL_PROXY\s0 .PP If the \f(CW\*(C`REQUEST_METHOD\*(C'\fR environment variable is set, then this might be a \s-1CGI\s0 process and \f(CW\*(C`HTTP_PROXY\*(C'\fR would be set from the \f(CW\*(C`Proxy:\*(C'\fR header, which is a security risk. If \f(CW\*(C`REQUEST_METHOD\*(C'\fR is set, \f(CW\*(C`HTTP_PROXY\*(C'\fR (the upper case variant only) is ignored, but \f(CW\*(C`CGI_HTTP_PROXY\*(C'\fR is considered instead. .PP Tunnelling \f(CW\*(C`https\*(C'\fR over an \f(CW\*(C`http\*(C'\fR proxy using the \s-1CONNECT\s0 method is supported. If your proxy uses \f(CW\*(C`https\*(C'\fR itself, you can not tunnel \f(CW\*(C`https\*(C'\fR over it. .PP Be warned that proxying an \f(CW\*(C`https\*(C'\fR connection opens you to the risk of a man-in-the-middle attack by the proxy server. .PP The \f(CW\*(C`no_proxy\*(C'\fR environment variable is supported in the format of a comma-separated list of domain extensions proxy should not be used for. .PP Proxy arguments passed to \f(CW\*(C`new\*(C'\fR will override their corresponding environment variables. .SH "LIMITATIONS" .IX Header "LIMITATIONS" HTTP::Tiny is \fIconditionally compliant\fR with the \&\s-1HTTP/1.1\s0 specifications : .IP "\(bu" 4 \&\*(L"Message Syntax and Routing\*(R" [\s-1RFC7230\s0] .IP "\(bu" 4 \&\*(L"Semantics and Content\*(R" [\s-1RFC7231\s0] .IP "\(bu" 4 \&\*(L"Conditional Requests\*(R" [\s-1RFC7232\s0] .IP "\(bu" 4 \&\*(L"Range Requests\*(R" [\s-1RFC7233\s0] .IP "\(bu" 4 \&\*(L"Caching\*(R" [\s-1RFC7234\s0] .IP "\(bu" 4 \&\*(L"Authentication\*(R" [\s-1RFC7235\s0] .PP It attempts to meet all \*(L"\s-1MUST\*(R"\s0 requirements of the specification, but does not implement all \*(L"\s-1SHOULD\*(R"\s0 requirements. (Note: it was developed against the earlier \s-1RFC 2616\s0 specification and may not yet meet the revised \s-1RFC 7230\-7235\s0 spec.) Additionally, HTTP::Tiny supports the \f(CW\*(C`PATCH\*(C'\fR method of \s-1RFC 5789.\s0 .PP Some particular limitations of note include: .IP "\(bu" 4 HTTP::Tiny focuses on correct transport. Users are responsible for ensuring that user-defined headers and content are compliant with the \s-1HTTP/1.1\s0 specification. .IP "\(bu" 4 Users must ensure that URLs are properly escaped for unsafe characters and that international domain names are properly encoded to \s-1ASCII.\s0 See URI::Escape, URI::_punycode and Net::IDN::Encode. .IP "\(bu" 4 Redirection is very strict against the specification. Redirection is only automatic for response codes 301, 302, 307 and 308 if the request method is \&'\s-1GET\s0' or '\s-1HEAD\s0'. Response code 303 is always converted into a '\s-1GET\s0' redirection, as mandated by the specification. There is no automatic support for status 305 (\*(L"Use proxy\*(R") redirections. .IP "\(bu" 4 There is no provision for delaying a request body using an \f(CW\*(C`Expect\*(C'\fR header. Unexpected \f(CW\*(C`1XX\*(C'\fR responses are silently ignored as per the specification. .IP "\(bu" 4 Only 'chunked' \f(CW\*(C`Transfer\-Encoding\*(C'\fR is supported. .IP "\(bu" 4 There is no support for a Request-URI of '*' for the '\s-1OPTIONS\s0' request. .IP "\(bu" 4 Headers mentioned in the RFCs and some other, well-known headers are generated with their canonical case. Other headers are sent in the case provided by the user. Except for control headers (which are sent first), headers are sent in arbitrary order. .PP Despite the limitations listed above, HTTP::Tiny is considered feature-complete. New feature requests should be directed to HTTP::Tiny::UA. .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 4 HTTP::Tiny::UA \- Higher level \s-1UA\s0 features for HTTP::Tiny .IP "\(bu" 4 HTTP::Thin \- HTTP::Tiny wrapper with HTTP::Request/HTTP::Response compatibility .IP "\(bu" 4 HTTP::Tiny::Mech \- Wrap WWW::Mechanize instance in HTTP::Tiny compatible interface .IP "\(bu" 4 IO::Socket::IP \- Required for IPv6 support .IP "\(bu" 4 IO::Socket::SSL \- Required for \s-1SSL\s0 support .IP "\(bu" 4 LWP::UserAgent \- If HTTP::Tiny isn't enough for you, this is the \*(L"standard\*(R" way to do things .IP "\(bu" 4 Mozilla::CA \- Required if you want to validate \s-1SSL\s0 certificates .IP "\(bu" 4 Net::SSLeay \- Required for \s-1SSL\s0 support .SH "SUPPORT" .IX Header "SUPPORT" .SS "Bugs / Feature Requests" .IX Subsection "Bugs / Feature Requests" Please report any bugs or feature requests through the issue tracker at . You will be notified automatically of any progress on your issue. .SS "Source Code" .IX Subsection "Source Code" This is open source software. The code repository is available for public review and contribution under the terms of the license. .PP .PP .Vb 1 \& git clone https://github.com/chansen/p5\-http\-tiny.git .Ve .SH "AUTHORS" .IX Header "AUTHORS" .IP "\(bu" 4 Christian Hansen .IP "\(bu" 4 David Golden .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" .IP "\(bu" 4 Alan Gardner .IP "\(bu" 4 Alessandro Ghedini .IP "\(bu" 4 A. Sinan Unur .IP "\(bu" 4 Brad Gilbert .IP "\(bu" 4 brian m. carlson .IP "\(bu" 4 Chris Nehren .IP "\(bu" 4 Chris Weyl .IP "\(bu" 4 Claes Jakobsson .IP "\(bu" 4 Clinton Gormley .IP "\(bu" 4 Craig A. Berry .IP "\(bu" 4 Craig Berry .IP "\(bu" 4 David Golden .IP "\(bu" 4 David Mitchell .IP "\(bu" 4 Dean Pearce .IP "\(bu" 4 Edward Zborowski .IP "\(bu" 4 Felipe Gasper .IP "\(bu" 4 Greg Kennedy .IP "\(bu" 4 James E Keenan .IP "\(bu" 4 James Raspass .IP "\(bu" 4 Jeremy Mates .IP "\(bu" 4 Jess Robinson .IP "\(bu" 4 Karen Etheridge .IP "\(bu" 4 Lukas Eklund .IP "\(bu" 4 Martin J. Evans .IP "\(bu" 4 Martin-Louis Bright .IP "\(bu" 4 Matthew Horsfall .IP "\(bu" 4 Michael R. Davis .IP "\(bu" 4 Mike Doherty .IP "\(bu" 4 Nicolas Rochelemagne .IP "\(bu" 4 Olaf Alders .IP "\(bu" 4 Olivier Mengué .IP "\(bu" 4 Petr Písař .IP "\(bu" 4 sanjay-cpu .IP "\(bu" 4 Serguei Trouchelle .IP "\(bu" 4 Shoichi Kaji .IP "\(bu" 4 SkyMarshal .IP "\(bu" 4 Sören Kornetzki .IP "\(bu" 4 Steve Grazzini .IP "\(bu" 4 Syohei \s-1YOSHIDA\s0 .IP "\(bu" 4 Tatsuhiko Miyagawa .IP "\(bu" 4 Tom Hukins .IP "\(bu" 4 Tony Cook .IP "\(bu" 4 Xavier Guimard .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2021 by Christian Hansen. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. man/man3/Crypt::SSLeay::Version.3pm000044400000011213152462503210012672 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Crypt::SSLeay::Version 3" .TH Crypt::SSLeay::Version 3 "2014-04-22" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Crypt::SSLeay::Version \- Obtain OpenSSL version information .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 8 \& use Crypt::SSLeay::Version qw(\e \& openssl_built_on \& openssl_cflags \& openssl_dir \& openssl_platform \& openssl_version \& openssl_version_number \& ); \& \& my $version = openssl_version(); \& \& if (openssl_cflags() =~ /DOPENSSL_NO_HEARTBEATS/) { \& print "OpenSSL was compiled without heartbeats\en"; \& } .Ve .SH "SUMMARY" .IX Header "SUMMARY" Exposes information provided by SSLeay_version . .SH "EXPORTS" .IX Header "EXPORTS" By default, the module exports nothing. You can ask for each subroutine bloew to be exported to your namespace. .SH "SUBROUTINES" .IX Header "SUBROUTINES" .SS "openssl_built_on" .IX Subsection "openssl_built_on" The date of the build process in the form \*(L"built on: ...\*(R" if available or ``built on: date not available'' otherwise. .SS "openssl_cflags" .IX Subsection "openssl_cflags" The compiler flags set for the compilation process in the form \*(L"compiler: ...\*(R" if available or \*(L"compiler: information not available\*(R" otherwise. .SS "openssl_dir" .IX Subsection "openssl_dir" The \f(CW\*(C`OPENSSLDIR\*(C'\fR setting of the library build in the form \*(L"\s-1OPENSSLDIR: ...\*(R"\s0 if available or \*(L"\s-1OPENSSLDIR: N/A\*(R"\s0 otherwise. .SS "openssl_platform" .IX Subsection "openssl_platform" The \*(L"Configure\*(R" target of the library build in the form \*(L"platform: ...\*(R" if available or \*(L"platform: information not available\*(R" otherwise. .SS "openssl_version" .IX Subsection "openssl_version" The version of the OpenSSL library including the release date. .SS "openssl_version_number" .IX Subsection "openssl_version_number" The value of the \f(CW\*(C`OPENSSL_VERSION_NUMBER\*(C'\fR macro as an unsigned integer. This value is more like a string as version information is packed into specific nibbles see \f(CW\*(C`crypto/opensslv.h\*(C'\fR in the OpenSSL source and for explanation. .SH "AUTHOR" .IX Header "AUTHOR" A. Sinan Unur \f(CW\*(C`\*(C'\fR .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (C) 2014 A. Sinan Unur. .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the terms of Artistic License 2.0 . man/man3/JSON::backportPP::Boolean.3pm000044400000005407152462503210013211 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON::backportPP::Boolean 3" .TH JSON::backportPP::Boolean 3 "2021-01-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" JSON::PP::Boolean \- dummy module providing JSON::PP::Boolean .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& # do not "use" yourself .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module exists only to provide overload resolution for Storable and similar modules. See \&\s-1JSON::PP\s0 for more info about this class. .SH "AUTHOR" .IX Header "AUTHOR" This idea is from JSON::XS::Boolean written by Marc Lehmann .SH "LICENSE" .IX Header "LICENSE" This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man3/DBI::Const::GetInfo::ODBC.3pm000044400000006221152462503210012642 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Const::GetInfo::ODBC 3" .TH DBI::Const::GetInfo::ODBC 3 "2015-05-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Const::GetInfo::ODBC \- ODBC Constants for GetInfo .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& The API for this module is private and subject to change. .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Information requested by \fBGetInfo()\fR. .PP The \s-1API\s0 for this module is private and subject to change. .SH "REFERENCES" .IX Header "REFERENCES" .Vb 2 \& MDAC SDK 2.6 \& ODBC version number (0x0351) \& \& sql.h \& sqlext.h .Ve .ie n .SS "%ReturnTypes" .el .SS "\f(CW%ReturnTypes\fP" .IX Subsection "%ReturnTypes" See: mk:@MSITStore:X:\edm\ecli\emdac\esdk26\eDocs\eodbc.chm::/htm/odbcsqlgetinfo.htm .PP .Vb 2 \& => : alias \& => !!! : edited .Ve .ie n .SS "%ReturnValues" .el .SS "\f(CW%ReturnValues\fP" .IX Subsection "%ReturnValues" See: sql.h, sqlext.h Edited: \s-1SQL_TXN_ISOLATION_OPTION\s0 .SH "TODO" .IX Header "TODO" .Vb 3 \& Corrections? \& SQL_NULL_COLLATION: ODBC vs ANSI \& Unique values for $ReturnValues{...}?, e.g. SQL_FILE_USAGE .Ve man/man3/DBI::DBD::Metadata.3pm000044400000016517152462503210011527 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::DBD::Metadata 3" .TH DBI::DBD::Metadata 3 "2015-05-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::DBD::Metadata \- Generate the code and data for some DBI metadata methods .SH "SYNOPSIS" .IX Header "SYNOPSIS" The idea is to extract metadata information from a good quality \&\s-1ODBC\s0 driver and use it to generate code and data to use in your own \&\s-1DBI\s0 driver for the same database. .PP To generate code to support the get_info method: .PP .Vb 1 \& perl \-MDBI::DBD::Metadata \-e "write_getinfo_pm(\*(Aqdbi:ODBC:dsn\-name\*(Aq,\*(Aquser\*(Aq,\*(Aqpass\*(Aq,\*(AqDriver\*(Aq)" \& \& perl \-MDBI::DBD::Metadata \-e write_getinfo_pm dbi:ODBC:foo_db username password Driver .Ve .PP To generate code to support the type_info method: .PP .Vb 1 \& perl \-MDBI::DBD::Metadata \-e "write_typeinfo_pm(\*(Aqdbi:ODBC:dsn\-name\*(Aq,\*(Aquser\*(Aq,\*(Aqpass\*(Aq,\*(AqDriver\*(Aq)" \& \& perl \-MDBI::DBD::Metadata \-e write_typeinfo_pm dbi:ODBC:dsn\-name user pass Driver .Ve .PP Where \f(CW\*(C`dbi:ODBC:dsn\-name\*(C'\fR is the connection to use to extract the data, and \f(CW\*(C`Driver\*(C'\fR is the name of the driver you want the code generated for (the driver name gets embedded into the output in numerous places). .SH "Generating a GetInfo package for a driver" .IX Header "Generating a GetInfo package for a driver" The \f(CW\*(C`write_getinfo_pm\*(C'\fR in the DBI::DBD::Metadata module generates a DBD::Driver::GetInfo package on standard output. .PP This method generates a DBD::Driver::GetInfo package from the data source you specified in the parameter list or in the environment variable \s-1DBI_DSN.\s0 DBD::Driver::GetInfo should help a \s-1DBD\s0 author implement the \s-1DBI\s0 \&\fBget_info()\fR method. Because you are just creating this package, it is very unlikely that DBD::Driver already provides a good implementation for \fBget_info()\fR. Thus you will probably connect via \s-1DBD::ODBC.\s0 .PP Once you are sure that it is producing reasonably sane data, you should typically redirect the standard output to lib/DBD/Driver/GetInfo.pm, and then hand edit the result. Do not forget to update your Makefile.PL and \s-1MANIFEST\s0 to include this as an extra \s-1PM\s0 file that should be installed. .PP If you connect via \s-1DBD::ODBC,\s0 you should use version 0.38 or greater; .PP Please take a critical look at the data returned! \&\s-1ODBC\s0 drivers vary dramatically in their quality. .PP The generator assumes that most values are static and places these values directly in the \f(CW%info\fR hash. A few examples show the use of \s-1CODE\s0 references and the implementation via subroutines. It is very likely that you will have to write additional subroutines for values depending on the session state or server version, e.g. \&\s-1SQL_DBMS_VER.\s0 .PP A possible implementation of \fBDBD::Driver::db::get_info()\fR may look like: .PP .Vb 7 \& sub get_info { \& my($dbh, $info_type) = @_; \& require DBD::Driver::GetInfo; \& my $v = $DBD::Driver::GetInfo::info{int($info_type)}; \& $v = $v\->($dbh) if ref $v eq \*(AqCODE\*(Aq; \& return $v; \& } .Ve .PP Please replace Driver (or \*(L"\*(R") with the name of your driver. Note that this stub function is generated for you by write_getinfo_pm function, but you must manually transfer the code to Driver.pm. .SH "Generating a TypeInfo package for a driver" .IX Header "Generating a TypeInfo package for a driver" The \f(CW\*(C`write_typeinfo_pm\*(C'\fR function in the DBI::DBD::Metadata module generates on standard output the data needed for a driver's type_info_all method. It also provides default implementations of the type_info_all method for inclusion in the driver's main implementation file. .PP The driver parameter is the name of the driver for which the methods will be generated; for the sake of examples, this will be \*(L"Driver\*(R". Typically, the dsn parameter will be of the form \*(L"dbi:ODBC:odbc_dsn\*(R", where the odbc_dsn is a \s-1DSN\s0 for one of the driver's databases. The user and pass parameters are the other optional connection parameters that will be provided to the \s-1DBI\s0 connect method. .PP Once you are sure that it is producing reasonably sane data, you should typically redirect the standard output to lib/DBD/Driver/TypeInfo.pm, and then hand edit the result if necessary. Do not forget to update your Makefile.PL and \s-1MANIFEST\s0 to include this as an extra \s-1PM\s0 file that should be installed. .PP Please take a critical look at the data returned! \&\s-1ODBC\s0 drivers vary dramatically in their quality. .PP The generator assumes that all the values are static and places these values directly in the \f(CW%info\fR hash. .PP A possible implementation of \fBDBD::Driver::type_info_all()\fR may look like: .PP .Vb 5 \& sub type_info_all { \& my ($dbh) = @_; \& require DBD::Driver::TypeInfo; \& return [ @$DBD::Driver::TypeInfo::type_info_all ]; \& } .Ve .PP Please replace Driver (or \*(L"\*(R") with the name of your driver. Note that this stub function is generated for you by the write_typeinfo_pm function, but you must manually transfer the code to Driver.pm. .SH "AUTHORS" .IX Header "AUTHORS" Jonathan Leffler (previously ), Jochen Wiedmann , Steffen Goeldner , and Tim Bunce . man/man3/DBI::SQL::Nano.3pm000044400000024023152462503210010737 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::SQL::Nano 3" .TH DBI::SQL::Nano 3 "2016-04-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::SQL::Nano \- a very tiny SQL engine .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 7 \& BEGIN { $ENV{DBI_SQL_NANO}=1 } # forces use of Nano rather than SQL::Statement \& use DBI::SQL::Nano; \& use Data::Dumper; \& my $stmt = DBI::SQL::Nano::Statement\->new( \& "SELECT bar,baz FROM foo WHERE qux = 1" \& ) or die "Couldn\*(Aqt parse"; \& print Dumper $stmt; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\f(CW\*(C`DBI::SQL::Nano\*(C'\fR is meant as a \fIvery\fR minimal \s-1SQL\s0 engine for use in situations where SQL::Statement is not available. In most situations you are better off installing SQL::Statement although DBI::SQL::Nano may be faster for some \fBvery\fR simple tasks. .PP DBI::SQL::Nano, like SQL::Statement is primarily intended to provide a \s-1SQL\s0 engine for use with some pure perl DBDs including \s-1DBD::DBM\s0, \s-1DBD::CSV\s0, DBD::AnyData, and DBD::Excel. It is not of much use in and of itself. You can dump out the structure of a parsed \s-1SQL\s0 statement, but that is about it. .SH "USAGE" .IX Header "USAGE" .SS "Setting the \s-1DBI_SQL_NANO\s0 flag" .IX Subsection "Setting the DBI_SQL_NANO flag" By default, when a \f(CW\*(C`DBD\*(C'\fR uses \f(CW\*(C`DBI::SQL::Nano\*(C'\fR, the module will look to see if \f(CW\*(C`SQL::Statement\*(C'\fR is installed. If it is, SQL::Statement objects are used. If SQL::Statement is not available, DBI::SQL::Nano objects are used. .PP In some cases, you may wish to use DBI::SQL::Nano objects even if SQL::Statement is available. To force usage of DBI::SQL::Nano objects regardless of the availability of SQL::Statement, set the environment variable \s-1DBI_SQL_NANO\s0 to 1. .PP You can set the environment variable in your shell prior to running your script (with \s-1SET\s0 or \s-1EXPORT\s0 or whatever), or else you can set it in your script by putting this at the top of the script: .PP .Vb 1 \& BEGIN { $ENV{DBI_SQL_NANO} = 1 } .Ve .SS "Supported \s-1SQL\s0 syntax" .IX Subsection "Supported SQL syntax" .Vb 2 \& Here\*(Aqs a pseudo\-BNF. Square brackets [] indicate optional items; \& Angle brackets <> indicate items defined elsewhere in the BNF. \& \& statement ::= \& DROP TABLE [IF EXISTS] \& | CREATE TABLE \& | INSERT INTO [] VALUES \& | DELETE FROM [] \& | UPDATE SET \& | SELECT FROM [] \& [] \& \& the optional IF EXISTS clause ::= \& * similar to MySQL \- prevents errors when trying to drop \& a table that doesn\*(Aqt exist \& \& identifiers ::= \& * table and column names should be valid SQL identifiers \& * especially avoid using spaces and commas in identifiers \& * note: there is no error checking for invalid names, some \& will be accepted, others will cause parse failures \& \& table_name ::= \& * only one table (no multiple table operations) \& * see identifier for valid table names \& \& col_def_list ::= \& * a parens delimited, comma\-separated list of column names \& * see identifier for valid column names \& * column types and column constraints may be included but are ignored \& e.g. these are all the same: \& (id,phrase) \& (id INT, phrase VARCHAR(40)) \& (id INT PRIMARY KEY, phrase VARCHAR(40) NOT NULL) \& * you are *strongly* advised to put in column types even though \& they are ignored ... it increases portability \& \& insert_col_list ::= \& * a parens delimited, comma\-separated list of column names \& * as in standard SQL, this is optional \& \& select_col_list ::= \& * a comma\-separated list of column names \& * or an asterisk denoting all columns \& \& val_list ::= \& * a parens delimited, comma\-separated list of values which can be: \& * placeholders (an unquoted question mark) \& * numbers (unquoted numbers) \& * column names (unquoted strings) \& * nulls (unquoted word NULL) \& * strings (delimited with single quote marks); \& * note: leading and trailing percent mark (%) and underscore (_) \& can be used as wildcards in quoted strings for use with \& the LIKE and CLIKE operators \& * note: escaped single quotation marks within strings are not \& supported, neither are embedded commas, use placeholders instead \& \& set_clause ::= \& * a comma\-separated list of column = value pairs \& * see val_list for acceptable value formats \& \& where_clause ::= \& * a single "column/value column/value" predicate, optionally \& preceded by "NOT" \& * note: multiple predicates combined with ORs or ANDs are not supported \& * see val_list for acceptable value formats \& * op may be one of: \& < > >= <= = <> LIKE CLIKE IS \& * CLIKE is a case insensitive LIKE \& \& order_clause ::= column_name [ASC|DESC] \& * a single column optional ORDER BY clause is supported \& * as in standard SQL, if neither ASC (ascending) nor \& DESC (descending) is specified, ASC becomes the default .Ve .SH "TABLES" .IX Header "TABLES" DBI::SQL::Nano::Statement operates on exactly one table. This table will be opened by inherit from DBI::SQL::Nano::Statement and implements the \&\f(CW\*(C`open_table\*(C'\fR method. .PP .Vb 5 \& sub open_table ($$$$$) \& { \& ... \& return Your::Table\->new( \e%attributes ); \& } .Ve .PP DBI::SQL::Nano::Statement_ expects a rudimentary interface is implemented by the table object, as well as SQL::Statement expects. .PP .Vb 1 \& package Your::Table; \& \& use vars qw(@ISA); \& @ISA = qw(DBI::SQL::Nano::Table); \& \& sub drop ($$) { ... } \& sub fetch_row ($$$) { ... } \& sub push_row ($$$) { ... } \& sub push_names ($$$) { ... } \& sub truncate ($$) { ... } \& sub seek ($$$$) { ... } .Ve .PP The base class interfaces are provided by DBI::SQL::Nano::Table_ in case of relying on DBI::SQL::Nano or SQL::Eval::Table (see SQL::Eval for details) otherwise. .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" There are no known bugs in DBI::SQL::Nano::Statement. If you find a one and want to report, please see \s-1DBI\s0 for how to report bugs. .PP DBI::SQL::Nano::Statement is designed to provide a minimal subset for executing \s-1SQL\s0 statements. .PP The most important limitation might be the restriction on one table per statement. This implies, that no JOINs are supported and there cannot be any foreign key relation between tables. .PP The where clause evaluation of DBI::SQL::Nano::Statement is very slow (SQL::Statement uses a precompiled evaluation). .PP \&\s-1INSERT\s0 can handle only one row per statement. To insert multiple rows, use placeholders as explained in \s-1DBI.\s0 .PP The DBI::SQL::Nano parser is very limited and does not support any additional syntax such as brackets, comments, functions, aggregations etc. .PP In contrast to SQL::Statement, temporary tables are not supported. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" Tim Bunce provided the original idea for this module, helped me out of the tangled trap of namespaces, and provided help and advice all along the way. Although I wrote it from the ground up, it is based on Jochen Wiedmann's original design of SQL::Statement, so much of the credit for the \s-1API\s0 goes to him. .SH "AUTHOR AND COPYRIGHT" .IX Header "AUTHOR AND COPYRIGHT" This module is originally written by Jeff Zucker < jzucker \s-1AT\s0 cpan.org > .PP This module is currently maintained by Jens Rehsack < jrehsack \s-1AT\s0 cpan.org > .PP Copyright (C) 2010 by Jens Rehsack, all rights reserved. Copyright (C) 2004 by Jeff Zucker, all rights reserved. .PP You may freely distribute and/or modify this module under the terms of either the \s-1GNU\s0 General Public License (\s-1GPL\s0) or the Artistic License, as specified in the Perl \s-1README\s0 file. man/man3/DBI::ProfileDumper::Apache.3pm000044400000020017152462503210013342 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::ProfileDumper::Apache 3" .TH DBI::ProfileDumper::Apache 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::ProfileDumper::Apache \- capture DBI profiling data from Apache/mod_perl .SH "SYNOPSIS" .IX Header "SYNOPSIS" Add this line to your \fIhttpd.conf\fR: .PP .Vb 1 \& PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache .Ve .PP (If you're using mod_perl2, see \*(L"When using mod_perl2\*(R" for some additional notes.) .PP Then restart your server. Access the code you wish to test using a web browser, then shutdown your server. This will create a set of \&\fIdbi.prof.*\fR files in your Apache log directory. .PP Get a profiling report with dbiprof: .PP .Vb 1 \& dbiprof /path/to/your/apache/logs/dbi.prof.* .Ve .PP When you're ready to perform another profiling run, delete the old files and start again. .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module interfaces DBI::ProfileDumper to Apache/mod_perl. Using this module you can collect profiling data from mod_perl applications. It works by creating a DBI::ProfileDumper data file for each Apache process. These files are created in your Apache log directory. You can then use the dbiprof utility to analyze the profile files. .SH "USAGE" .IX Header "USAGE" .SS "\s-1LOADING THE MODULE\s0" .IX Subsection "LOADING THE MODULE" The easiest way to use this module is just to set the \s-1DBI_PROFILE\s0 environment variable in your \fIhttpd.conf\fR: .PP .Vb 1 \& PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache .Ve .PP The \s-1DBI\s0 will look after loading and using the module when the first \s-1DBI\s0 handle is created. .PP It's also possible to use this module by setting the Profile attribute of any \s-1DBI\s0 handle: .PP .Vb 1 \& $dbh\->{Profile} = "2/DBI::ProfileDumper::Apache"; .Ve .PP See DBI::ProfileDumper for more possibilities, and DBI::Profile for full details of the \s-1DBI\s0's profiling mechanism. .SS "\s-1WRITING PROFILE DATA\s0" .IX Subsection "WRITING PROFILE DATA" The profile data files will be written to your Apache log directory by default. .PP The user that the httpd processes run as will need write access to the directory. So, for example, if you're running the child httpds as user 'nobody' and using chronolog to write to the logs directory, then you'll need to change the default. .PP You can change the destination directory either by specifying a \f(CW\*(C`Dir\*(C'\fR value when creating the profile (like \f(CW\*(C`File\*(C'\fR in the DBI::ProfileDumper docs), or you can use the \f(CW\*(C`DBI_PROFILE_APACHE_LOG_DIR\*(C'\fR env var to change that. For example: .PP .Vb 1 \& PerlSetEnv DBI_PROFILE_APACHE_LOG_DIR /server_root/logs .Ve .PP \fIWhen using mod_perl2\fR .IX Subsection "When using mod_perl2" .PP Under mod_perl2 you'll need to either set the \f(CW\*(C`DBI_PROFILE_APACHE_LOG_DIR\*(C'\fR env var, or enable the mod_perl2 \f(CW\*(C`GlobalRequest\*(C'\fR option, like this: .PP .Vb 1 \& PerlOptions +GlobalRequest .Ve .PP to the global config section you're about test with DBI::ProfileDumper::Apache. If you don't do one of those then you'll see messages in your error_log similar to: .PP .Vb 2 \& DBI::ProfileDumper::Apache on_destroy failed: Global $r object is not available. Set: \& PerlOptions +GlobalRequest in httpd.conf at ..../DBI/ProfileDumper/Apache.pm line 144 .Ve .PP \fINaming the files\fR .IX Subsection "Naming the files" .PP The default file name is inherited from DBI::ProfileDumper via the \&\fBfilename()\fR method, but DBI::ProfileDumper::Apache appends the parent pid and the current pid, separated by dots, to that name. .PP \fISilencing the log\fR .IX Subsection "Silencing the log" .PP By default a message is written to \s-1STDERR\s0 (i.e., the apache error_log file) when \fBflush_to_disk()\fR is called (either explicitly, or implicitly via \s-1DESTROY\s0). .PP That's usually very useful. If you don't want the log message you can silence it by setting the \f(CW\*(C`Quiet\*(C'\fR attribute true. .PP .Vb 1 \& PerlSetEnv DBI_PROFILE 2/DBI::ProfileDumper::Apache/Quiet:1 \& \& $dbh\->{Profile} = "!Statement/DBI::ProfileDumper/Quiet:1"; \& \& $dbh\->{Profile} = DBI::ProfileDumper\->new( \& Path => [ \*(Aq!Statement\*(Aq ] \& Quiet => 1 \& ); .Ve .SS "\s-1GATHERING PROFILE DATA\s0" .IX Subsection "GATHERING PROFILE DATA" Once you have the module loaded, use your application as you normally would. Stop the webserver when your tests are complete. Profile data files will be produced when Apache exits and you'll see something like this in your error_log: .PP .Vb 1 \& DBI::ProfileDumper::Apache writing to /usr/local/apache/logs/dbi.prof.2604.2619 .Ve .PP Now you can use dbiprof to examine the data: .PP .Vb 1 \& dbiprof /usr/local/apache/logs/dbi.prof.2604.* .Ve .PP By passing dbiprof a list of all generated files, dbiprof will automatically merge them into one result set. You can also pass dbiprof sorting and querying options, see dbiprof for details. .SS "\s-1CLEANING UP\s0" .IX Subsection "CLEANING UP" Once you've made some code changes, you're ready to start again. First, delete the old profile data files: .PP .Vb 1 \& rm /usr/local/apache/logs/dbi.prof.* .Ve .PP Then restart your server and get back to work. .SH "OTHER ISSUES" .IX Header "OTHER ISSUES" .SS "Memory usage" .IX Subsection "Memory usage" DBI::Profile can use a lot of memory for very active applications because it collects profiling data in memory for each distinct query run. Calling \f(CW\*(C`flush_to_disk()\*(C'\fR will write the current data to disk and free the memory it's using. For example: .PP .Vb 1 \& $dbh\->{Profile}\->flush_to_disk() if $dbh\->{Profile}; .Ve .PP or, rather than flush every time, you could flush less often: .PP .Vb 2 \& $dbh\->{Profile}\->flush_to_disk() \& if $dbh\->{Profile} and ++$i % 100; .Ve .SH "AUTHOR" .IX Header "AUTHOR" Sam Tregar .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2002 Sam Tregar .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself. man/man3/DBI::Gofer::Serializer::Base.3pm000044400000005526152462503210013546 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Serializer::Base 3" .TH DBI::Gofer::Serializer::Base 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Serializer::Base \- base class for Gofer serialization .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $serializer = $serializer_class\->new(); \& \& $string = $serializer\->serialize( $data ); \& ($string, $deserializer_class) = $serializer\->serialize( $data ); \& \& $data = $serializer\->deserialize( $string ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBI::Gofer::Serializer::* classes implement a very minimal subset of the Data::Serializer \s-1API.\s0 .PP Gofer serializers are expected to be very fast and are not required to deal with anything other than non-blessed references to arrays and hashes, and plain scalars. man/man3/DBI::Gofer::Serializer::DataDumper.3pm000044400000005225152462503210014716 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::Gofer::Serializer::DataDumper 3" .TH DBI::Gofer::Serializer::DataDumper 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::Gofer::Serializer::DataDumper \- Gofer serialization using DataDumper .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $serializer = DBI::Gofer::Serializer::DataDumper\->new(); \& \& $string = $serializer\->serialize( $data ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Uses DataDumper to serialize. Deserialization is not supported. The output of this class is only meant for human consumption. .PP See also DBI::Gofer::Serializer::Base. man/man3/Path::Class::Entity.3pm000044400000010535152462503210012227 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Path::Class::Entity 3" .TH Path::Class::Entity 3 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Path::Class::Entity \- Base class for files and directories .SH "VERSION" .IX Header "VERSION" version 0.37 .SH "DESCRIPTION" .IX Header "DESCRIPTION" This class is the base class for \f(CW\*(C`Path::Class::File\*(C'\fR and \&\f(CW\*(C`Path::Class::Dir\*(C'\fR, it is not used directly by callers. .SH "AUTHOR" .IX Header "AUTHOR" Ken Williams, kwilliams@cpan.org .SH "SEE ALSO" .IX Header "SEE ALSO" Path::Class man/man3/DBD::Gofer::Policy::classic.3pm000044400000006042152462503210013430 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Policy::classic 3" .TH DBD::Gofer::Policy::classic 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Policy::classic \- The 'classic' policy for DBD::Gofer .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& $dbh = DBI\->connect("dbi:Gofer:transport=...;policy=classic", ...) .Ve .PP The \f(CW\*(C`classic\*(C'\fR policy is the default DBD::Gofer policy, so need not be included in the \s-1DSN.\s0 .SH "DESCRIPTION" .IX Header "DESCRIPTION" Temporary docs: See the source code for list of policies and their defaults. .PP In a future version the policies and their defaults will be defined in the pod and parsed out at load-time. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. man/man3/DBI::ProfileSubs.3pm000044400000004700152462503210011535 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBI::ProfileSubs 3" .TH DBI::ProfileSubs 3 "2013-06-24" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBI::ProfileSubs \- Subroutines for dynamic profile Path .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& DBI_PROFILE=\*(Aq&norm_std_n3\*(Aq prog.pl .Ve .PP This is new and still experimental. .SH "TO DO" .IX Header "TO DO" Define come kind of naming convention for the subs. man/man3/DBD::File::Roadmap.3pm000044400000021532152462503210011644 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::File::Roadmap 3" .TH DBD::File::Roadmap 3 "2013-04-04" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::File::Roadmap \- Planned Enhancements for DBD::File and pure Perl DBD's .PP Jens Rehsack \- May 2010 .SH "SYNOPSIS" .IX Header "SYNOPSIS" This document gives a high level overview of the future of the DBD::File \s-1DBI\s0 driver and groundwork for pure Perl \s-1DBI\s0 drivers. .PP The planned enhancements cover features, testing, performance, reliability, extensibility and more. .SH "CHANGES AND ENHANCEMENTS" .IX Header "CHANGES AND ENHANCEMENTS" .SS "Features" .IX Subsection "Features" There are some features missing we would like to add, but there is no time plan: .IP "\s-1LOCK TABLE\s0" 4 .IX Item "LOCK TABLE" The newly implemented internal common table meta storage area would allow us to implement \s-1LOCK TABLE\s0 support based on file system \f(CW\*(C`flock ()\*(C'\fR support. .IP "Transaction support" 4 .IX Item "Transaction support" While DBD::AnyData recommends explicitly committing by importing and exporting tables, DBD::File might be enhanced in a future version to allow transparent transactions using the temporary tables of SQL::Statement as shadow (dirty) tables. .Sp Transaction support will heavily rely on lock table support. .IP "Data Dictionary Persistence" 4 .IX Item "Data Dictionary Persistence" SQL::Statement provides dictionary information when a \*(L"\s-1CREATE TABLE ...\*(R"\s0 statement is executed. This dictionary is preserved for some statement handle attribute fetches (as \f(CW\*(C`NULLABLE\*(C'\fR or \f(CW\*(C`PRECISION\*(C'\fR). .Sp It is planned to extend DBD::File to support data dictionaries to work on the tables in it. It is not planned to support one table in different dictionaries, but you can have several dictionaries in one directory. .IP "\s-1SQL\s0 Engine selecting on connect" 4 .IX Item "SQL Engine selecting on connect" Currently the \s-1SQL\s0 engine selected is chosen during the loading of the module DBI::SQL::Nano. Ideally end users should be able to select the engine used in \f(CW\*(C`DBI\->connect ()\*(C'\fR with a special DBD::File attribute. .PP Other points of view to the planned features (and more features for the SQL::Statement engine) are shown in SQL::Statement::Roadmap. .SS "Testing" .IX Subsection "Testing" DBD::File and the dependent \s-1DBD::DBM\s0 requires a lot more automated tests covering \s-1API\s0 stability and compatibility with optional modules like SQL::Statement. .SS "Performance" .IX Subsection "Performance" Several arguments for support of features like indexes on columns and cursors are made for \s-1DBD::CSV\s0 (which is a DBD::File based driver, too). Similar arguments could be made for \s-1DBD::DBM,\s0 DBD::AnyData, \&\s-1DBD::RAM\s0 or \s-1DBD::PO\s0 etc. .PP To improve the performance of the underlying \s-1SQL\s0 engines, a clean re-implementation seems to be required. Currently both engines are prematurely optimized and therefore it is not trivial to provide further optimization without the risk of breaking existing features. .PP Join the \s-1DBI\s0 developers \s-1IRC\s0 channel at to participate or post to the \s-1DBI\s0 Developers Mailing List. .SS "Reliability" .IX Subsection "Reliability" DBD::File currently lacks the following points: .IP "duplicate table names" 4 .IX Item "duplicate table names" It is currently possible to access a table quoted with a relative path (a) and additionally using an absolute path (b). If (a) and (b) are the same file that is not recognized (except for flock protection handled by the Operating System) and two independent tables are handled. .IP "invalid table names" 4 .IX Item "invalid table names" The current implementation does not prevent someone choosing a directory name as a physical file name for the table to open. .SS "Extensibility" .IX Subsection "Extensibility" I (Jens Rehsack) have some (partially for example only) \s-1DBD\s0's in mind: .IP "DBD::Sys" 4 .IX Item "DBD::Sys" Derive DBD::Sys from a common code base shared with DBD::File which handles all the emulation \s-1DBI\s0 needs (as getinfo, \s-1SQL\s0 engine handling, ...) .IP "DBD::Dir" 4 .IX Item "DBD::Dir" Provide a DBD::File derived to work with fixed table definitions through the file system to demonstrate how \s-1DBI /\s0 Pure Perl DBDs could handle databases with hierarchical structures. .IP "DBD::Join" 4 .IX Item "DBD::Join" Provide a \s-1DBI\s0 driver which is able to manage multiple connections to other Databases (as DBD::Multiplex), but allow them to point to different data sources and allow joins between the tables of them: .Sp .Vb 6 \& # Example \& # Let table \*(Aqlsof\*(Aq being a table in DBD::Sys giving a list of open files using lsof utility \& # Let table \*(Aqdir\*(Aq being a atable from DBD::Dir \& $sth = $dbh\->prepare( "select * from dir,lsof where path=\*(Aq/documents\*(Aq and dir.entry = lsof.filename" ) \& $sth\->execute(); # gives all open files in \*(Aq/documents\*(Aq \& ... \& \& # Let table \*(Aqfilesys\*(Aq a DBD::Sys table of known file systems on current host \& # Let table \*(Aqapplications\*(Aq a table of your Configuration Management Database \& # where current applications (relocatable, with mountpoints for filesystems) \& # are stored \& $sth = dbh\->prepare( "select * from applications,filesys where " . \& "application.mountpoint = filesys.mountpoint and ". \& "filesys.mounted is true" ); \& $sth\->execute(); # gives all currently mounted applications on this host .Ve .SH "PRIORITIES" .IX Header "PRIORITIES" Our priorities are focused on current issues. Initially many new test cases for DBD::File and \s-1DBD::DBM\s0 should be added to the \s-1DBI\s0 test suite. After that some additional documentation on how to use the DBD::File \s-1API\s0 will be provided. .PP Any additional priorities will come later and can be modified by (paying) users. .SH "RESOURCES AND CONTRIBUTIONS" .IX Header "RESOURCES AND CONTRIBUTIONS" See for \fIhow you can help\fR. .PP If your company has benefited from \s-1DBI,\s0 please consider if it could make a donation to The Perl Foundation \*(L"\s-1DBI\s0 Development\*(R" fund at to secure future development. .PP Alternatively, if your company would benefit from a specific new \&\s-1DBI\s0 feature, please consider sponsoring it's development through the options listed in the section \*(L"Commercial Support from the Author\*(R" on . .PP Using such targeted financing allows you to contribute to \s-1DBI\s0 development and rapidly get something specific and directly valuable to you in return. .PP My company also offers annual support contracts for the \s-1DBI,\s0 which provide another way to support the \s-1DBI\s0 and get something specific in return. Contact me for details. .PP Thank you. man/man3/DBD::Gofer.3pm000044400000057006152462503210010344 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer 3" .TH DBD::Gofer 3 "2020-01-26" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer \- A stateless\-proxy driver for communicating with a remote DBI .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use DBI; \& \& $original_dsn = "dbi:..."; # your original DBI Data Source Name \& \& $dbh = DBI\->connect("dbi:Gofer:transport=$transport;...;dsn=$original_dsn", \& $user, $passwd, \e%attributes); \& \& ... use $dbh as if it was connected to $original_dsn ... .Ve .PP The \f(CW\*(C`transport=$transport\*(C'\fR part specifies the name of the module to use to transport the requests to the remote \s-1DBI.\s0 If \f(CW$transport\fR doesn't contain any double colons then it's prefixed with \f(CW\*(C`DBD::Gofer::Transport::\*(C'\fR. .PP The \f(CW\*(C`dsn=$original_dsn\*(C'\fR part \fImust be the last element\fR of the \s-1DSN\s0 because everything after \f(CW\*(C`dsn=\*(C'\fR is assumed to be the \s-1DSN\s0 that the remote \s-1DBI\s0 should use. .PP The \f(CW\*(C`...\*(C'\fR represents attributes that influence the operation of the Gofer driver or transport. These are described below or in the documentation of the transport module being used. .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBD::Gofer is a \s-1DBI\s0 database driver that forwards requests to another \s-1DBI\s0 driver, usually in a separate process, often on a separate machine. It tries to be as transparent as possible so it appears that you are using the remote driver directly. .PP DBD::Gofer is very similar to DBD::Proxy. The major difference is that with DBD::Gofer no state is maintained on the remote end. That means every request contains all the information needed to create the required state. (So, for example, every request includes the \s-1DSN\s0 to connect to.) Each request can be sent to any available server. The server executes the request and returns a single response that includes all the data. .PP This is very similar to the way http works as a stateless protocol for the web. Each request from your web browser can be handled by a different web server process. .SS "Use Cases" .IX Subsection "Use Cases" This may seem like pointless overhead but there are situations where this is a very good thing. Let's consider a specific case. .PP Imagine using DBD::Gofer with an http transport. Your application calls \&\fBconnect()\fR, prepare(\*(L"select * from table where foo=?\*(R"), \fBbind_param()\fR, and \fBexecute()\fR. At this point DBD::Gofer builds a request containing all the information about the method calls. It then uses the httpd transport to send that request to an apache web server. .PP This 'dbi execute' web server executes the request (using DBI::Gofer::Execute and related modules) and builds a response that contains all the rows of data, if the statement returned any, along with all the attributes that describe the results, such as \f(CW$sth\fR\->{\s-1NAME\s0}. This response is sent back to DBD::Gofer which unpacks it and presents it to the application as if it had executed the statement itself. .SS "Advantages" .IX Subsection "Advantages" Okay, but you still don't see the point? Well let's consider what we've gained: .PP \fIConnection Pooling and Throttling\fR .IX Subsection "Connection Pooling and Throttling" .PP The 'dbi execute' web server leverages all the functionality of web infrastructure in terms of load balancing, high-availability, firewalls, access management, proxying, caching. .PP At its most basic level you get a configurable pool of persistent database connections. .PP \fISimple Scaling\fR .IX Subsection "Simple Scaling" .PP Got thousands of processes all trying to connect to the database? You can use DBD::Gofer to connect them to your smaller pool of 'dbi execute' web servers instead. .PP \fICaching\fR .IX Subsection "Caching" .PP Client-side caching is as simple as adding "\f(CW\*(C`cache=1\*(C'\fR" to the \s-1DSN.\s0 This feature alone can be worth using DBD::Gofer for. .PP \fIFewer Network Round-trips\fR .IX Subsection "Fewer Network Round-trips" .PP DBD::Gofer sends as few requests as possible (dependent on the policy being used). .PP \fIThin Clients / Unsupported Platforms\fR .IX Subsection "Thin Clients / Unsupported Platforms" .PP You no longer need drivers for your database on every system. DBD::Gofer is pure perl. .SH "CONSTRAINTS" .IX Header "CONSTRAINTS" There are some natural constraints imposed by the DBD::Gofer 'stateless' approach. But not many: .SS "You can't change database handle attributes after \fBconnect()\fP" .IX Subsection "You can't change database handle attributes after connect()" You can't change database handle attributes after you've connected. Use the \fBconnect()\fR call to specify all the attribute settings you want. .PP This is because it's critical that when a request is complete the database handle is left in the same state it was when first connected. .PP An exception is made for attributes with names starting "\f(CW\*(C`private_\*(C'\fR": They can be set after \fBconnect()\fR but the change is only applied locally. .SS "You can't change statement handle attributes after \fBprepare()\fP" .IX Subsection "You can't change statement handle attributes after prepare()" You can't change statement handle attributes after prepare. .PP An exception is made for attributes with names starting "\f(CW\*(C`private_\*(C'\fR": They can be set after \fBprepare()\fR but the change is only applied locally. .SS "You can't use transactions" .IX Subsection "You can't use transactions" AutoCommit only. Transactions aren't supported. .PP (In theory transactions could be supported when using a transport that maintains a connection, like \f(CW\*(C`stream\*(C'\fR does. If you're interested in this please get in touch via dbi\-dev@perl.org) .SS "You can't call driver-private sth methods" .IX Subsection "You can't call driver-private sth methods" But that's rarely needed anyway. .SH "GENERAL CAVEATS" .IX Header "GENERAL CAVEATS" A few important things to keep in mind when using DBD::Gofer: .SS "Temporary tables, locks, and other per-connection persistent state" .IX Subsection "Temporary tables, locks, and other per-connection persistent state" You shouldn't expect any per-session state to persist between requests. This includes locks and temporary tables. .PP Because the server-side may execute your requests via a different database connections, you can't rely on any per-connection persistent state, such as temporary tables, being available from one request to the next. .PP This is an easy trap to fall into. A good way to check for this is to test your code with a Gofer policy package that sets the \f(CW\*(C`connect_method\*(C'\fR policy to \&'connect' to force a new connection for each request. The \f(CW\*(C`pedantic\*(C'\fR policy does this. .SS "Driver-private Database Handle Attributes" .IX Subsection "Driver-private Database Handle Attributes" Some driver-private dbh attributes may not be available if the driver has not implemented the \fBprivate_attribute_info()\fR method (added in \s-1DBI 1.54\s0). .SS "Driver-private Statement Handle Attributes" .IX Subsection "Driver-private Statement Handle Attributes" Driver-private sth attributes can be set in the \fBprepare()\fR call. \s-1TODO\s0 .PP Some driver-private sth attributes may not be available if the driver has not implemented the \fBprivate_attribute_info()\fR method (added in \s-1DBI 1.54\s0). .SS "Multiple Resultsets" .IX Subsection "Multiple Resultsets" Multiple resultsets are supported only if the driver supports the \fBmore_results()\fR method (an exception is made for DBD::Sybase). .SS "Statement activity that also updates dbh attributes" .IX Subsection "Statement activity that also updates dbh attributes" Some drivers may update one or more dbh attributes after performing activity on a child sth. For example, DBD::mysql provides \f(CW$dbh\fR\->{mysql_insertid} in addition to \&\f(CW$sth\fR\->{mysql_insertid}. Currently mysql_insertid is supported via a hack but a more general mechanism is needed for other drivers to use. .SS "Methods that report an error always return undef" .IX Subsection "Methods that report an error always return undef" With DBD::Gofer, a method that sets an error always return an undef or empty list. That shouldn't be a problem in practice because the \s-1DBI\s0 doesn't define any methods that return meaningful values while also reporting an error. .SS "Subclassing only applies to client-side" .IX Subsection "Subclassing only applies to client-side" The RootClass and DbTypeSubclass attributes are not passed to the Gofer server. .SH "CAVEATS FOR SPECIFIC METHODS" .IX Header "CAVEATS FOR SPECIFIC METHODS" .SS "last_insert_id" .IX Subsection "last_insert_id" To enable use of last_insert_id you need to indicate to DBD::Gofer that you'd like to use it. You do that my adding a \f(CW\*(C`go_last_insert_id_args\*(C'\fR attribute to the \fBdo()\fR or \fBprepare()\fR method calls. For example: .PP .Vb 1 \& $dbh\->do($sql, { go_last_insert_id_args => [...] }); .Ve .PP or .PP .Vb 1 \& $sth = $dbh\->prepare($sql, { go_last_insert_id_args => [...] }); .Ve .PP The array reference should contains the args that you want passed to the \&\fBlast_insert_id()\fR method. .SS "execute_for_fetch" .IX Subsection "execute_for_fetch" The array methods \fBbind_param_array()\fR and \fBexecute_array()\fR are supported. When \fBexecute_array()\fR is called the data is serialized and executed in a single round-trip to the Gofer server. This makes it very fast, but requires enough memory to store all the serialized data. .PP The \fBexecute_for_fetch()\fR method currently isn't optimised, it uses the \s-1DBI\s0 fallback behaviour of executing each tuple individually. (It could be implemented as a wrapper for \fBexecute_array()\fR \- patches welcome.) .SH "TRANSPORTS" .IX Header "TRANSPORTS" DBD::Gofer doesn't concern itself with transporting requests and responses to and fro. For that it uses special Gofer transport modules. .PP Gofer transport modules usually come in pairs: one for the 'client' DBD::Gofer driver to use and one for the remote 'server' end. They have very similar names: .PP .Vb 2 \& DBD::Gofer::Transport:: \& DBI::Gofer::Transport:: .Ve .PP Sometimes the transports on the \s-1DBD\s0 and \s-1DBI\s0 sides may have different names. For example DBD::Gofer::Transport::http is typically used with DBI::Gofer::Transport::mod_perl (DBD::Gofer::Transport::http and DBI::Gofer::Transport::mod_perl modules are part of the GoferTransport-http distribution). .SS "Bundled Transports" .IX Subsection "Bundled Transports" Several transport modules are provided with DBD::Gofer: .PP \fInull\fR .IX Subsection "null" .PP The null transport is the simplest of them all. It doesn't actually transport the request anywhere. It just serializes (freezes) the request into a string, then thaws it back into a data structure before passing it to DBI::Gofer::Execute to execute. The same freeze and thaw is applied to the results. .PP The null transport is the best way to test if your application will work with Gofer. Just set the \s-1DBI_AUTOPROXY\s0 environment variable to "\f(CW\*(C`dbi:Gofer:transport=null;policy=pedantic\*(C'\fR" (see \*(L"Using \s-1DBI_AUTOPROXY\*(R"\s0 below) and run your application, or ideally its test suite, as usual. .PP It doesn't take any parameters. .PP \fIpipeone\fR .IX Subsection "pipeone" .PP The pipeone transport launches a subprocess for each request. It passes in the request and reads the response. .PP The fact that a new subprocess is started for each request ensures that the server side is truly stateless. While this does make the transport \fIvery\fR slow, it is useful as a way to test that your application doesn't depend on per-connection state, such as temporary tables, persisting between requests. .PP It's also useful both as a proof of concept and as a base class for the stream driver. .PP \fIstream\fR .IX Subsection "stream" .PP The stream driver also launches a subprocess and writes requests and reads responses, like the pipeone transport. In this case, however, the subprocess is expected to handle more that one request. (Though it will be automatically restarted if it exits.) .PP This is the first transport that is truly useful because it can launch the subprocess on a remote machine using \f(CW\*(C`ssh\*(C'\fR. This means you can now use DBD::Gofer to easily access any databases that's accessible from any system you can login to. You also get all the benefits of ssh, including encryption and optional compression. .PP See \*(L"Using \s-1DBI_AUTOPROXY\*(R"\s0 below for an example. .SS "Other Transports" .IX Subsection "Other Transports" Implementing a Gofer transport is \fIvery\fR simple, and more transports are very welcome. Just take a look at any existing transports that are similar to your needs. .PP \fIhttp\fR .IX Subsection "http" .PP See the GoferTransport-http distribution on \s-1CPAN:\s0 http://search.cpan.org/dist/GoferTransport\-http/ .PP \fIGearman\fR .IX Subsection "Gearman" .PP I know Ask Bjørn Hansen has implemented a transport for the \f(CW\*(C`gearman\*(C'\fR distributed job system, though it's not on \s-1CPAN\s0 at the time of writing this. .SH "CONNECTING" .IX Header "CONNECTING" Simply prefix your existing \s-1DSN\s0 with "\f(CW\*(C`dbi:Gofer:transport=$transport;dsn=\*(C'\fR" where \f(CW$transport\fR is the name of the Gofer transport you want to use (see \*(L"\s-1TRANSPORTS\*(R"\s0). The \f(CW\*(C`transport\*(C'\fR and \f(CW\*(C`dsn\*(C'\fR attributes must be specified and the \f(CW\*(C`dsn\*(C'\fR attributes must be last. .PP Other attributes can be specified in the \s-1DSN\s0 to configure DBD::Gofer and/or the Gofer transport module being used. The main attributes after \f(CW\*(C`transport\*(C'\fR, are \&\f(CW\*(C`url\*(C'\fR and \f(CW\*(C`policy\*(C'\fR. These and other attributes are described below. .SS "Using \s-1DBI_AUTOPROXY\s0" .IX Subsection "Using DBI_AUTOPROXY" The simplest way to try out DBD::Gofer is to set the \s-1DBI_AUTOPROXY\s0 environment variable. In this case you don't include the \f(CW\*(C`dsn=\*(C'\fR part. For example: .PP .Vb 1 \& export DBI_AUTOPROXY="dbi:Gofer:transport=null" .Ve .PP or, for a more useful example, try: .PP .Vb 1 \& export DBI_AUTOPROXY="dbi:Gofer:transport=stream;url=ssh:user@example.com" .Ve .SS "Connection Attributes" .IX Subsection "Connection Attributes" These attributes can be specified in the \s-1DSN.\s0 They can also be passed in the \&\e%attr parameter of the \s-1DBI\s0 connect method by adding a "\f(CW\*(C`go_\*(C'\fR" prefix to the name. .PP \fItransport\fR .IX Subsection "transport" .PP Specifies the Gofer transport class to use. Required. See \*(L"\s-1TRANSPORTS\*(R"\s0 above. .PP If the value does not include \f(CW\*(C`::\*(C'\fR then "\f(CW\*(C`DBD::Gofer::Transport::\*(C'\fR" is prefixed. .PP The transport object can be accessed via \f(CW$h\fR\->{go_transport}. .PP \fIdsn\fR .IX Subsection "dsn" .PP Specifies the \s-1DSN\s0 for the remote side to connect to. Required, and must be last. .PP \fIurl\fR .IX Subsection "url" .PP Used to tell the transport where to connect to. The exact form of the value depends on the transport used. .PP \fIpolicy\fR .IX Subsection "policy" .PP Specifies the policy to use. See \*(L"\s-1CONFIGURING BEHAVIOUR POLICY\*(R"\s0. .PP If the value does not include \f(CW\*(C`::\*(C'\fR then "\f(CW\*(C`DBD::Gofer::Policy\*(C'\fR" is prefixed. .PP The policy object can be accessed via \f(CW$h\fR\->{go_policy}. .PP \fItimeout\fR .IX Subsection "timeout" .PP Specifies a timeout, in seconds, to use when waiting for responses from the server side. .PP \fIretry_limit\fR .IX Subsection "retry_limit" .PP Specifies the number of times a failed request will be retried. Default is 0. .PP \fIretry_hook\fR .IX Subsection "retry_hook" .PP Specifies a code reference to be called to decide if a failed request should be retried. The code reference is called like this: .PP .Vb 2 \& $transport = $h\->{go_transport}; \& $retry = $transport\->go_retry_hook\->($request, $response, $transport); .Ve .PP If it returns true then the request will be retried, up to the \f(CW\*(C`retry_limit\*(C'\fR. If it returns a false but defined value then the request will not be retried. If it returns undef then the default behaviour will be used, as if \f(CW\*(C`retry_hook\*(C'\fR had not been specified. .PP The default behaviour is to retry requests where \f(CW$request\fR\->is_idempotent is true, or the error message matches \f(CW\*(C`/induced by DBI_GOFER_RANDOM/\*(C'\fR. .PP \fIcache\fR .IX Subsection "cache" .PP Specifies that client-side caching should be performed. The value is the name of a cache class to use. .PP Any class implementing get($key) and set($key, \f(CW$value\fR) methods can be used. That includes a great many powerful caching classes on \s-1CPAN,\s0 including the Cache and Cache::Cache distributions. .PP You can use "\f(CW\*(C`cache=1\*(C'\fR\*(L" is a shortcut for \*(R"\f(CW\*(C`cache=DBI::Util::CacheMemory\*(C'\fR". See DBI::Util::CacheMemory for a description of this simple fast default cache. .PP The cache object can be accessed via \f(CW$h\fR\->go_cache. For example: .PP .Vb 1 \& $dbh\->go_cache\->clear; # free up memory being used by the cache .Ve .PP The cache keys are the frozen (serialized) requests, and the values are the frozen responses. .PP The default behaviour is to only use the cache for requests where \&\f(CW$request\fR\->is_idempotent is true (i.e., the dbh has the ReadOnly attribute set or the \s-1SQL\s0 statement is obviously a \s-1SELECT\s0 without a \s-1FOR UPDATE\s0 clause.) .PP For even more control you can use the \f(CW\*(C`go_cache\*(C'\fR attribute to pass in an instantiated cache object. Individual methods, including \fBprepare()\fR, can also specify alternative caches via the \f(CW\*(C`go_cache\*(C'\fR attribute. For example, to specify no caching for a particular query, you could use .PP .Vb 1 \& $sth = $dbh\->prepare( $sql, { go_cache => 0 } ); .Ve .PP This can be used to implement different caching policies for different statements. .PP It's interesting to note that DBD::Gofer can be used to add client-side caching to any (gofer compatible) application, with no code changes and no need for a gofer server. Just set the \s-1DBI_AUTOPROXY\s0 environment variable like this: .PP .Vb 1 \& DBI_AUTOPROXY=\*(Aqdbi:Gofer:transport=null;cache=1\*(Aq .Ve .SH "CONFIGURING BEHAVIOUR POLICY" .IX Header "CONFIGURING BEHAVIOUR POLICY" DBD::Gofer supports a 'policy' mechanism that allows you to fine-tune the number of round-trips to the Gofer server. The policies are grouped into classes (which may be subclassed) and referenced by the name of the class. .PP The DBD::Gofer::Policy::Base class is the base class for all the policy packages and describes all the available policies. .PP Three policy packages are supplied with DBD::Gofer: .PP DBD::Gofer::Policy::pedantic is most 'transparent' but slowest because it makes more round-trips to the Gofer server. .PP DBD::Gofer::Policy::classic is a reasonable compromise \- it's the default policy. .PP DBD::Gofer::Policy::rush is fastest, but may require code changes in your applications. .PP Generally the default \f(CW\*(C`classic\*(C'\fR policy is fine. When first testing an existing application with Gofer it is a good idea to start with the \f(CW\*(C`pedantic\*(C'\fR policy first and then switch to \f(CW\*(C`classic\*(C'\fR or a custom policy, for final testing. .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. .SH "ACKNOWLEDGEMENTS" .IX Header "ACKNOWLEDGEMENTS" The development of DBD::Gofer and related modules was sponsored by Shopzilla.com (), where I currently work. .SH "SEE ALSO" .IX Header "SEE ALSO" DBI::Gofer::Request, DBI::Gofer::Response, DBI::Gofer::Execute. .PP DBI::Gofer::Transport::Base, DBD::Gofer::Policy::Base. .PP \&\s-1DBI\s0 .SH "Caveats for specific drivers" .IX Header "Caveats for specific drivers" This section aims to record issues to be aware of when using Gofer with specific drivers. It usually only documents issues that are not natural consequences of the limitations of the Gofer approach \- as documented above. .SH "TODO" .IX Header "TODO" This is just a random brain dump... (There's more in the source of the Changes file, not the pod) .PP Document policy mechanism .PP Add mechanism for transports to list config params and for Gofer to apply any that match (and warn if any left over?) .PP Driver-private sth attributes \- set via \fBprepare()\fR \- change \s-1DBI\s0 spec .PP add hooks into transport base class for checking & updating a result set cache ie via a standard cache interface such as: http://search.cpan.org/~robm/Cache\-FastMmap/FastMmap.pm http://search.cpan.org/~bradfitz/Cache\-Memcached/lib/Cache/Memcached.pm http://search.cpan.org/~dclinton/Cache\-Cache/ http://search.cpan.org/~cleishman/Cache/ Also caching instructions could be passed through the httpd transport layer in such a way that appropriate http cache headers are added to the results so that web caches (squid etc) could be used to implement the caching. (\s-1MUST\s0 require the use of \s-1GET\s0 rather than \s-1POST\s0 requests.) .PP Rework handling of installed_methods to not piggyback on dbh_attributes? .PP Perhaps support transactions for transports where it's possible (ie null and stream)? Would make stream transport (ie ssh) more useful to more people. .PP Make sth_result_attr more like dbh_attributes (using '*' etc) .PP Add \f(CW@val\fR = FETCH_many(@names) to \s-1DBI\s0 in C and use in Gofer/Execute? .PP Implement _new_sth in C. man/man3/IO::LockedFile.3pm000044400000030654152462503210011221 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LockedFile 3" .TH LockedFile 3 "2003-02-20" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" IO::LockedFile Class \- supply object methods for locking files .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use IO::LockedFile; \& \& # create new locked file object. $file will hold a file handle. \& # if the file is already locked, the method will not return until the \& # file is unlocked \& my $file = new IO::LockedFile(">locked1.txt"); \& \& # when we close the file \- it become unlocked. \& $file\->close(); \& \& # suppose we did not have the line above, we can also delete the \& # object, and the file is automatically unlocked and closed. \& $file = undef; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" In its simplistic use, the \fBIO::LockedFile\fR class gives us the same interface of the \fBIO::File\fR class with the unique difference that the files we deal with are locked using the \fBFlock\fR mechanism (using the \&\f(CW\*(C`flock\*(C'\fR function). .PP If during the running of the process, it crashed \- the file will be automatically unlocked. Actually \- if the \fBIO::LockedFile\fR object goes out of scope, the file is automatically closed and unlocked. .PP So, if you are just interested in having locked files with \f(CW\*(C`flock\*(C'\fR, you can skip most of the documentation below. .PP If, on the other hand, you are interested in locking files with other schemes then \fBFlock\fR, or you want to control the behavior of the locking (having non blocking lock for example), read on. .PP Actually the class \fBIO::LockedFile\fR is kind of abstract class. .PP Why abstract? Because methods of this class call the methods \f(CW\*(C`lock\*(C'\fR and \f(CW\*(C`unlock\*(C'\fR. But those methods are not really implemented in this class. They suppose to be implemented in the derived classes of \fBIO::LockedFile\fR. .PP Why \*(L"kind\*(R" of abstract? Because the constructor of this class will return an object! .PP How abstract class can create objects? This is done by having the constructor returning object that is actually an object of one of the derived classes of \&\fBIO::LockedFile\fR. .PP So by default the constructor of \fBIO::LockedFile\fR will return an object of \&\fBIO::LockedFile::Flock\fR. For example, the following: .PP .Vb 3 \& use IO::LockedFile; \& $lock = new IO::LockedFile(">bla"); \& print ref($lock); .Ve .PP Will give: .PP .Vb 1 \& IO::LockedFile::Flock .Ve .PP So what are the conclusions here? .PP First of all \- do not be surprised to get object of derived class from the constructor of \fBIO::LockedFile\fR. .PP Secondly \- by changing the default behavior of the constructor of \&\fBIO::LockedFile\fR, we can get object of other class which means that we have a locked file that is locked with other scheme. .PP The default behavior of the constructor is determined by the global options. .PP We can access this global options, or the options per object using the method \&\f(CW\*(C`set_option\*(C'\fR and \f(CW\*(C`get_option\*(C'\fR. .PP We can set the global options in the use line: .PP .Vb 1 \& use IO::LockedFile \*(AqFlock\*(Aq; # set the default scheme to be Flock \& \& use IO::LockedFile ( scheme => Flock ); .Ve .PP We can also set the options of a new object by passing the options to the constructor, as we will see below. We can change the options of an existing object by using the \f(CW\*(C`set_option\*(C'\fR method. .PP Which options are available? .IP "\fIscheme\fR" 4 .IX Item "scheme" The \fIscheme\fR let us define which derived class we use for the object we create. See below which derived classes are available. The default scheme is 'Flock'. .IP "\fIblock\fR" 4 .IX Item "block" The \fIblock\fR option can be 1 or 0 (true or false). If it is 1, a call to the \&\f(CW\*(C`open\*(C'\fR method or to the constructor will be blocked if the file we try to open is already locked. This means that those methods will not return till the file is unlocked. If the value of the \fIblock\fR option is 0, the \f(CW\*(C`open\*(C'\fR and the constructor will return immediately in any case. If the file is locked, those methods will return undef. The default value of the \fIblock\fR option is 1. .IP "\fIlock\fR" 4 .IX Item "lock" The \fIlock\fR option can be 1 or 0 (true or false). It defines if the file we open when we create the object will be opened locked. Sometimes, we want to have a file that can be locked, yet we do not want to open it locked from the beginning. For example if we want to print into a log file, usually we want to lock that file only when we print into it. Yet, it might be that when we open the file in the beginning we do not print into it immediately. In that case we will prefer to open the file as unlocked, and later we will lock it when needed. The default value of the \fIlock\fR option is 1. .PP There might be extra options that are used by one of the derived classes. So according to the scheme you choose to use, please look in the manual page of the class that implement that scheme. .PP Finally, some information that is connected to a certain scheme will be found in the classes that are derived from this class. For example, compatibility issues will be discussed in each derived classes. .PP The classes that currently implement the interface that \fBIO::LockedFile\fR defines are: .IP "\(bu" 4 \&\fBIO::LockedFile::Flock\fR .SH "CONSTRUCTOR" .IX Header "CONSTRUCTOR" .IP "new ( \s-1FILENAME\s0 [,MODE [,PERMS]] )" 4 .IX Item "new ( FILENAME [,MODE [,PERMS]] )" Creates an object that belong to one of the derived classes of \&\f(CW\*(C`IO::LockedFile\*(C'\fR. If it receives any parameters, they are passed to the method \f(CW\*(C`open\*(C'\fR. if the \f(CW\*(C`open\*(C'\fR fails, the object is destroyed. Otherwise, it is returned to the caller. The object will be the file handle of that opened file. .IP "new ( \s-1OPTIONS, FILENAME\s0 [,MODE [,PERMS]] )" 4 .IX Item "new ( OPTIONS, FILENAME [,MODE [,PERMS]] )" This version of the constructor is the same as above, with the difference that we send as the first parameter a reference to a hash \- \s-1OPTIONS.\s0 This hash let us change for this object only, the options from the default options. So for example if we want to change the \fIlock\fR option from its default we can do it as follow: \f(CW$file\fR = new IO::LockedFile( { lock => 0 }, \*(L">locked_later.txt\*(R" ); .SH "METHODS" .IX Header "METHODS" .IP "open ( \s-1FILENAME\s0 [,MODE [,PERMS]] )" 4 .IX Item "open ( FILENAME [,MODE [,PERMS]] )" The method let us open the file \s-1FILENAME.\s0 By default, the file will be opened as a locked file, and if the file that is opened is already locked, the method will not return until the file is unlocked. Of course this default behavior can be controlled by setting other options. The object will be the file handle of that opened file. The parameters that should be provided to this method are the same as the parameters that the method \f(CW\*(C`open\*(C'\fR of \&\fBIO::File\fR accepts. (like \*(L">file.txt\*(R" for example). Note that the open method checks if the file is opened for reading or for writing, and only then calls the lock method of the derived class that is being used. This way, for example, when using the \fBFlock\fR scheme, the lock will be a shared lock for a file that is being read, and exclusive lock for a file that is opened to be write. .IP "close ( )" 4 .IX Item "close ( )" The file will be closed and unlocked. The method returns the same as the close method of \fBIO::File\fR. .IP "lock ( )" 4 .IX Item "lock ( )" Practically this method does nothing, and returns 1 (true). This method will be overridden by the derived class that implements the scheme we use. When it is overridden, the method suppose to lock the file according to the scheme we use. If the file is already locked, and the \fIblock\fR option is 1 (true), the method will not return until the file is unlocked, and locked again by the method. If the \fIblock\fR option is 0 (false), the method will return 0 immediately. Besides, the lock method is aware if the file was opened for reading or for writing. Thus, for example, when using the \fBFlock\fR scheme, the method will create a shared lock for a file that is being read, and exclusive lock for a file that is opened to be write. .IP "unlock ( )" 4 .IX Item "unlock ( )" Practically this method does nothing, and returns 1 (true). This method will be overridden by the derived class that implements the scheme we use. When it is overridden, the method suppose to unlock the file according to the scheme we use, and return 1 (true) on success and 0 (false) on failure. .IP "have_lock ( )" 4 .IX Item "have_lock ( )" Will return 1 (true) if the file is already locked by this object. Will return 0 (false) otherwise. Note that this will not tell us anything about the situation of the file itself \- thus we should not use this method in order to check if the file is locked by someone else. .IP "print ( )" 4 .IX Item "print ( )" This method is exactly like the \f(CW\*(C`print\*(C'\fR method of \fBIO::Handle\fR, with the difference that when using this method, if the file is unlocked, then before printing to it, it will be locked and afterward it will be unlocked. .IP "truncate ( )" 4 .IX Item "truncate ( )" This method is exactly like the \f(CW\*(C`truncate\*(C'\fR method of \fBIO::Handle\fR, with the difference that when using this method, if the file is unlocked, then before truncating it, it will be locked and afterward it will be unlocked. .IP "is_writable ( )" 4 .IX Item "is_writable ( )" This method will return 1 (true) if the file was opened to write. Will return 0 (false) otherwise. .IP "should_block ( )" 4 .IX Item "should_block ( )" This method will return 1 (true) if the block option set to 1. Will return 0 (false) otherwise. .IP "should_lock ( )" 4 .IX Item "should_lock ( )" This method will return 1 (true) if the lock option set to 1. Will return 0 (false) otherwise. .IP "get_scheme ( )" 4 .IX Item "get_scheme ( )" This method will return the name of the scheme that is currently used. .SH "AUTHORS" .IX Header "AUTHORS" Rani Pinchuk, rani@cpan.org .PP Rob Napier, rnapier@employees.org .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2001\-2002 Ockham Technology N.V. & Rani Pinchuk. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBIO::File\fR\|(3), \&\fBIO::LockedFile::Flock\fR\|(3) man/man3/DBD::Proxy.3pm000044400000027264152462503210010426 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Proxy 3" .TH DBD::Proxy 3 "2014-09-21" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Proxy \- A proxy driver for the DBI .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use DBI; \& \& $dbh = DBI\->connect("dbi:Proxy:hostname=$host;port=$port;dsn=$db", \& $user, $passwd); \& \& # See the DBI module documentation for full details .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" DBD::Proxy is a Perl module for connecting to a database via a remote \&\s-1DBI\s0 driver. See DBD::Gofer for an alternative with different trade-offs. .PP This is of course not needed for \s-1DBI\s0 drivers which already support connecting to a remote database, but there are engines which don't offer network connectivity. .PP Another application is offering database access through a firewall, as the driver offers query based restrictions. For example you can restrict queries to exactly those that are used in a given \s-1CGI\s0 application. .PP Speaking of \s-1CGI,\s0 another application is (or rather, will be) to reduce the database connect/disconnect overhead from \s-1CGI\s0 scripts by using proxying the connect_cached method. The proxy server will hold the database connections open in a cache. The \s-1CGI\s0 script then trades the database connect/disconnect overhead for the DBD::Proxy connect/disconnect overhead which is typically much less. .SH "CONNECTING TO THE DATABASE" .IX Header "CONNECTING TO THE DATABASE" Before connecting to a remote database, you must ensure, that a Proxy server is running on the remote machine. There's no default port, so you have to ask your system administrator for the port number. See DBI::ProxyServer for details. .PP Say, your Proxy server is running on machine \*(L"alpha\*(R", port 3334, and you'd like to connect to an \s-1ODBC\s0 database called \*(L"mydb\*(R" as user \*(L"joe\*(R" with password \*(L"hello\*(R". When using \s-1DBD::ODBC\s0 directly, you'd do a .PP .Vb 1 \& $dbh = DBI\->connect("DBI:ODBC:mydb", "joe", "hello"); .Ve .PP With DBD::Proxy this becomes .PP .Vb 2 \& $dsn = "DBI:Proxy:hostname=alpha;port=3334;dsn=DBI:ODBC:mydb"; \& $dbh = DBI\->connect($dsn, "joe", "hello"); .Ve .PP You see, this is mainly the same. The DBD::Proxy module will create a connection to the Proxy server on \*(L"alpha\*(R" which in turn will connect to the \s-1ODBC\s0 database. .PP Refer to the \s-1DBI\s0 documentation on the \f(CW\*(C`connect\*(C'\fR method for a way to automatically use DBD::Proxy without having to change your code. .PP DBD::Proxy's \s-1DSN\s0 string has the format .PP .Vb 1 \& $dsn = "DBI:Proxy:key1=val1; ... ;keyN=valN;dsn=valDSN"; .Ve .PP In other words, it is a collection of key/value pairs. The following keys are recognized: .IP "hostname" 4 .IX Item "hostname" .PD 0 .IP "port" 4 .IX Item "port" .PD Hostname and port of the Proxy server; these keys must be present, no defaults. Example: .Sp .Vb 1 \& hostname=alpha;port=3334 .Ve .IP "dsn" 4 .IX Item "dsn" The value of this attribute will be used as a dsn name by the Proxy server. Thus it must have the format \f(CW\*(C`DBI:driver:...\*(C'\fR, in particular it will contain colons. The \fIdsn\fR value may contain semicolons, hence this key *must* be the last and it's value will be the complete remaining part of the dsn. Example: .Sp .Vb 1 \& dsn=DBI:ODBC:mydb .Ve .IP "cipher" 4 .IX Item "cipher" .PD 0 .IP "key" 4 .IX Item "key" .IP "usercipher" 4 .IX Item "usercipher" .IP "userkey" 4 .IX Item "userkey" .PD By using these fields you can enable encryption. If you set, for example, .Sp .Vb 1 \& cipher=$class;key=$key .Ve .Sp (note the semicolon) then DBD::Proxy will create a new cipher object by executing .Sp .Vb 1 \& $cipherRef = $class\->new(pack("H*", $key)); .Ve .Sp and pass this object to the RPC::PlClient module when creating a client. See RPC::PlClient. Example: .Sp .Vb 1 \& cipher=IDEA;key=97cd2375efa329aceef2098babdc9721 .Ve .Sp The usercipher/userkey attributes allow you to use two phase encryption: The cipher/key encryption will be used in the login and authorisation phase. Once the client is authorised, he will change to usercipher/userkey encryption. Thus the cipher/key pair is a \fBhost\fR based secret, typically less secure than the usercipher/userkey secret and readable by anyone. The usercipher/userkey secret is \fByour\fR private secret. .Sp Of course encryption requires an appropriately configured server. See \&\*(L"\s-1CONFIGURATION FILE\*(R"\s0 in DBD::ProxyServer. .IP "debug" 4 .IX Item "debug" Turn on debugging mode .IP "stderr" 4 .IX Item "stderr" This attribute will set the corresponding attribute of the RPC::PlClient object, thus logging will not use \fBsyslog()\fR, but redirected to stderr. This is the default under Windows. .Sp .Vb 1 \& stderr=1 .Ve .IP "logfile" 4 .IX Item "logfile" Similar to the stderr attribute, but output will be redirected to the given file. .Sp .Vb 1 \& logfile=/dev/null .Ve .IP "RowCacheSize" 4 .IX Item "RowCacheSize" The DBD::Proxy driver supports this attribute (which is \s-1DBI\s0 standard, as of \s-1DBI 1.02\s0). It's used to reduce network round-trips by fetching multiple rows in one go. The current default value is 20, but this may change. .IP "proxy_no_finish" 4 .IX Item "proxy_no_finish" This attribute can be used to reduce network traffic: If the application is calling \f(CW$sth\fR\->\fBfinish()\fR then the proxy tells the server to finish the remote statement handle. Of course this slows down things quite a lot, but is perfectly good for reducing memory usage with persistent connections. .Sp However, if you set the \fIproxy_no_finish\fR attribute to a \s-1TRUE\s0 value, either in the database handle or in the statement handle, then \fBfinish()\fR calls will be suppressed. This is what you want, for example, in small and fast \s-1CGI\s0 applications. .IP "proxy_quote" 4 .IX Item "proxy_quote" This attribute can be used to reduce network traffic: By default calls to \f(CW$dbh\fR\->\fBquote()\fR are passed to the remote driver. Of course this slows down things quite a lot, but is the safest default behaviour. .Sp However, if you set the \fIproxy_quote\fR attribute to the value '\f(CW\*(C`local\*(C'\fR' either in the database handle or in the statement handle, and the call to quote has only one parameter, then the local default \s-1DBI\s0 quote method will be used (which will be faster but may be wrong). .SH "KNOWN ISSUES" .IX Header "KNOWN ISSUES" .SS "Unproxied method calls" .IX Subsection "Unproxied method calls" If a method isn't being proxied, try declaring a stub sub in the appropriate package (DBD::Proxy::db for a dbh method, and DBD::Proxy::st for an sth method). For example: .PP .Vb 1 \& sub DBD::Proxy::db::selectall_arrayref; .Ve .PP That will enable selectall_arrayref to be proxied. .PP Currently many methods aren't explicitly proxied and so you get the \s-1DBI\s0's default methods executed on the client. .PP Some of those methods, like selectall_arrayref, may then call other methods that are proxied (selectall_arrayref calls fetchall_arrayref which calls fetch which is proxied). So things may appear to work but operate more slowly than the could. .PP This may all change in a later version. .SS "Complex handle attributes" .IX Subsection "Complex handle attributes" Sometimes handles are having complex attributes like hash refs or array refs and not simple strings or integers. For example, with \&\s-1DBD::CSV,\s0 you would like to write something like .PP .Vb 2 \& $dbh\->{"csv_tables"}\->{"passwd"} = \& { "sep_char" => ":", "eol" => "\en"; .Ve .PP The above example would advice the \s-1CSV\s0 driver to assume the file \&\*(L"passwd\*(R" to be in the format of the /etc/passwd file: Colons as separators and a line feed without carriage return as line terminator. .PP Surprisingly this example doesn't work with the proxy driver. To understand the reasons, you should consider the following: The Perl compiler is executing the above example in two steps: .IP "1." 4 The first step is fetching the value of the key \*(L"csv_tables\*(R" in the handle \f(CW$dbh\fR. The value returned is complex, a hash ref. .IP "2." 4 The second step is storing some value (the right hand side of the assignment) as the key \*(L"passwd\*(R" in the hash ref from step 1. .PP This becomes a little bit clearer, if we rewrite the above code: .PP .Vb 2 \& $tables = $dbh\->{"csv_tables"}; \& $tables\->{"passwd"} = { "sep_char" => ":", "eol" => "\en"; .Ve .PP While the examples work fine without the proxy, the fail due to a subtle difference in step 1: By \s-1DBI\s0 magic, the hash ref \&\f(CW$dbh\fR\->{'csv_tables'} is returned from the server to the client. The client creates a local copy. This local copy is the result of step 1. In other words, step 2 modifies a local copy of the hash ref, but not the server's hash ref. .PP The workaround is storing the modified local copy back to the server: .PP .Vb 3 \& $tables = $dbh\->{"csv_tables"}; \& $tables\->{"passwd"} = { "sep_char" => ":", "eol" => "\en"; \& $dbh\->{"csv_tables"} = $tables; .Ve .SH "SECURITY WARNING" .IX Header "SECURITY WARNING" RPC::PlClient used underneath is not secure due to serializing and deserializing data with Storable module. Use the proxy driver only in trusted environment. .SH "AUTHOR AND COPYRIGHT" .IX Header "AUTHOR AND COPYRIGHT" This module is Copyright (c) 1997, 1998 .PP .Vb 4 \& Jochen Wiedmann \& Am Eisteich 9 \& 72555 Metzingen \& Germany \& \& Email: joe@ispsoft.de \& Phone: +49 7123 14887 .Ve .PP The DBD::Proxy module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. In particular permission is granted to Tim Bunce for distributing this as a part of the \s-1DBI.\s0 .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1DBI\s0, RPC::PlClient, Storable man/man3/DBD::Gofer::Transport::corostream.3pm000044400000012663152462503210014730 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBD::Gofer::Transport::corostream 3" .TH DBD::Gofer::Transport::corostream 3 "2013-04-04" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBD::Gofer::Transport::corostream \- Async DBD::Gofer stream transport using Coro and AnyEvent .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& DBI_AUTOPROXY="dbi:Gofer:transport=corostream" perl some\-perl\-script\-using\-dbi.pl .Ve .PP or .PP .Vb 2 \& $dsn = ...; # the DSN for the driver and database you want to use \& $dbh = DBI\->connect("dbi:Gofer:transport=corostream;dsn=$dsn", ...); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \fI\s-1BIG WIN\s0\fR from using Coro is that it enables the use of existing \&\s-1DBI\s0 frameworks like DBIx::Class. .SH "KNOWN ISSUES AND LIMITATIONS" .IX Header "KNOWN ISSUES AND LIMITATIONS" .Vb 2 \& \- Uses Coro::Select so alters CORE::select globally \& Parent class probably needs refactoring to enable a more encapsulated approach. \& \& \- Doesn\*(Aqt prevent multiple concurrent requests \& Probably just needs a per\-connection semaphore \& \& \- Coro has many caveats. Caveat emptor. .Ve .SH "STATUS" .IX Header "STATUS" \&\s-1THIS IS CURRENTLY JUST A\s0 PROOF-OF-CONCEPT \s-1IMPLEMENTATION FOR EXPERIMENTATION.\s0 .PP Please note that I have no plans to develop this code further myself. I'd very much welcome contributions. Interested? Let me know! .SH "AUTHOR" .IX Header "AUTHOR" Tim Bunce, .SH "LICENCE AND COPYRIGHT" .IX Header "LICENCE AND COPYRIGHT" Copyright (c) 2010, Tim Bunce, Ireland. All rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic. .SH "SEE ALSO" .IX Header "SEE ALSO" DBD::Gofer::Transport::stream .PP DBD::Gofer .SH "APPENDIX" .IX Header "APPENDIX" Example code: .PP .Vb 1 \& #!perl \& \& use strict; \& use warnings; \& use Time::HiRes qw(time); \& \& BEGIN { $ENV{PERL_ANYEVENT_STRICT} = 1; $ENV{PERL_ANYEVENT_VERBOSE} = 1; } \& \& use AnyEvent; \& \& BEGIN { $ENV{DBI_TRACE} = 0; $ENV{DBI_GOFER_TRACE} = 0; $ENV{DBD_GOFER_TRACE} = 0; }; \& \& use DBI; \& \& $ENV{DBI_AUTOPROXY} = \*(Aqdbi:Gofer:transport=corostream\*(Aq; \& \& my $ticker = AnyEvent\->timer( after => 0, interval => 0.1, cb => sub { \& warn sprintf "\-tick\- %.2f\en", time \& } ); \& \& warn "connecting...\en"; \& my $dbh = DBI\->connect("dbi:NullP:"); \& warn "...connected\en"; \& \& for (1..3) { \& warn "entering DBI...\en"; \& $dbh\->do("sleep 0.3"); # pseudo\-sql understood by the DBD::NullP driver \& warn "...returned\en"; \& } \& \& warn "done."; .Ve .PP Example output: .PP .Vb 10 \& $ perl corogofer.pl \& connecting... \& \-tick\- 1293631437.14 \& \-tick\- 1293631437.14 \& ...connected \& entering DBI... \& \-tick\- 1293631437.25 \& \-tick\- 1293631437.35 \& \-tick\- 1293631437.45 \& \-tick\- 1293631437.55 \& ...returned \& entering DBI... \& \-tick\- 1293631437.66 \& \-tick\- 1293631437.76 \& \-tick\- 1293631437.86 \& ...returned \& entering DBI... \& \-tick\- 1293631437.96 \& \-tick\- 1293631438.06 \& \-tick\- 1293631438.16 \& ...returned \& done. at corogofer.pl line 39. .Ve .PP You can see that the timer callback is firing while the code 'waits' inside the \&\fBdo()\fR method for the response from the database. Normally that would block. man/man3/Net::HTTPS.3pm000044400000013260152462503210010333 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Net::HTTPS 3pm" .TH Net::HTTPS 3pm "2021-03-18" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::HTTPS \- Low\-level HTTP over SSL/TLS connection (client) .SH "VERSION" .IX Header "VERSION" version 6.21 .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`Net::HTTPS\*(C'\fR is a low-level \s-1HTTP\s0 over \s-1SSL/TLS\s0 client. The interface is the same as the interface for \f(CW\*(C`Net::HTTP\*(C'\fR, but the constructor takes additional parameters as accepted by IO::Socket::SSL. The \f(CW\*(C`Net::HTTPS\*(C'\fR object is an \f(CW\*(C`IO::Socket::SSL\*(C'\fR too, which makes it inherit additional methods from that base class. .PP For historical reasons this module also supports using \f(CW\*(C`Net::SSL\*(C'\fR (from the Crypt-SSLeay distribution) as its \s-1SSL\s0 driver and base class. This base is automatically selected if available and \f(CW\*(C`IO::Socket::SSL\*(C'\fR isn't. You might also force which implementation to use by setting \f(CW$Net::HTTPS::SSL_SOCKET_CLASS\fR before loading this module. If not set this variable is initialized from the \&\f(CW\*(C`PERL_NET_HTTPS_SSL_SOCKET_CLASS\*(C'\fR environment variable. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" You might set the \f(CW\*(C`PERL_NET_HTTPS_SSL_SOCKET_CLASS\*(C'\fR environment variable to the name of the base \s-1SSL\s0 implementation (and Net::HTTPS base class) to use. The default is \f(CW\*(C`IO::Socket::SSL\*(C'\fR. Currently the only other supported value is \f(CW\*(C`Net::SSL\*(C'\fR. .SH "SEE ALSO" .IX Header "SEE ALSO" Net::HTTP, IO::Socket::SSL .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2001\-2017 by Gisle Aas. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. man/man3/Path::Class::File.3pm000044400000044557152462503210011645 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Path::Class::File 3" .TH Path::Class::File 3 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Path::Class::File \- Objects representing files .SH "VERSION" .IX Header "VERSION" version 0.37 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Path::Class; # Exports file() by default \& \& my $file = file(\*(Aqfoo\*(Aq, \*(Aqbar.txt\*(Aq); # Path::Class::File object \& my $file = Path::Class::File\->new(\*(Aqfoo\*(Aq, \*(Aqbar.txt\*(Aq); # Same thing \& \& # Stringifies to \*(Aqfoo/bar.txt\*(Aq on Unix, \*(Aqfoo\ebar.txt\*(Aq on Windows, etc. \& print "file: $file\en"; \& \& if ($file\->is_absolute) { ... } \& if ($file\->is_relative) { ... } \& \& my $v = $file\->volume; # Could be \*(AqC:\*(Aq on Windows, empty string \& # on Unix, \*(AqMacintosh HD:\*(Aq on Mac OS \& \& $file\->cleanup; # Perform logical cleanup of pathname \& $file\->resolve; # Perform physical cleanup of pathname \& \& my $dir = $file\->dir; # A Path::Class::Dir object \& \& my $abs = $file\->absolute; # Transform to absolute path \& my $rel = $file\->relative; # Transform to relative path .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \f(CW\*(C`Path::Class::File\*(C'\fR class contains functionality for manipulating file names in a cross-platform way. .SH "METHODS" .IX Header "METHODS" .ie n .IP "$file = Path::Class::File\->new( , , ..., )" 4 .el .IP "\f(CW$file\fR = Path::Class::File\->new( , , ..., )" 4 .IX Item "$file = Path::Class::File->new( , , ..., )" .PD 0 .ie n .IP "$file = file( , , ..., )" 4 .el .IP "\f(CW$file\fR = file( , , ..., )" 4 .IX Item "$file = file( , , ..., )" .PD Creates a new \f(CW\*(C`Path::Class::File\*(C'\fR object and returns it. The arguments specify the path to the file. Any volume may also be specified as the first argument, or as part of the first argument. You can use platform-neutral syntax: .Sp .Vb 1 \& my $file = file( \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz.txt\*(Aq ); .Ve .Sp or platform-native syntax: .Sp .Vb 1 \& my $file = file( \*(Aqfoo/bar/baz.txt\*(Aq ); .Ve .Sp or a mixture of the two: .Sp .Vb 1 \& my $file = file( \*(Aqfoo/bar\*(Aq, \*(Aqbaz.txt\*(Aq ); .Ve .Sp All three of the above examples create relative paths. To create an absolute path, either use the platform native syntax for doing so: .Sp .Vb 1 \& my $file = file( \*(Aq/var/tmp/foo.txt\*(Aq ); .Ve .Sp or use an empty string as the first argument: .Sp .Vb 1 \& my $file = file( \*(Aq\*(Aq, \*(Aqvar\*(Aq, \*(Aqtmp\*(Aq, \*(Aqfoo.txt\*(Aq ); .Ve .Sp If the second form seems awkward, that's somewhat intentional \- paths like \f(CW\*(C`/var/tmp\*(C'\fR or \f(CW\*(C`\eWindows\*(C'\fR aren't cross-platform concepts in the first place, so they probably shouldn't appear in your code if you're trying to be cross-platform. The first form is perfectly fine, because paths like this may come from config files, user input, or whatever. .ie n .IP "$file\->stringify" 4 .el .IP "\f(CW$file\fR\->stringify" 4 .IX Item "$file->stringify" This method is called internally when a \f(CW\*(C`Path::Class::File\*(C'\fR object is used in a string context, so the following are equivalent: .Sp .Vb 2 \& $string = $file\->stringify; \& $string = "$file"; .Ve .ie n .IP "$file\->volume" 4 .el .IP "\f(CW$file\fR\->volume" 4 .IX Item "$file->volume" Returns the volume (e.g. \f(CW\*(C`C:\*(C'\fR on Windows, \f(CW\*(C`Macintosh HD:\*(C'\fR on Mac \s-1OS,\s0 etc.) of the object, if any. Otherwise, returns the empty string. .ie n .IP "$file\->basename" 4 .el .IP "\f(CW$file\fR\->basename" 4 .IX Item "$file->basename" Returns the name of the file as a string, without the directory portion (if any). .ie n .IP "$file\->components" 4 .el .IP "\f(CW$file\fR\->components" 4 .IX Item "$file->components" Returns a list of the directory components of this file, followed by the basename. .Sp Note: unlike \f(CW\*(C`$dir\->components\*(C'\fR, this method currently does not accept any arguments to select which elements of the list will be returned. It may do so in the future. Currently it throws an exception if such arguments are present. .ie n .IP "$file\->is_dir" 4 .el .IP "\f(CW$file\fR\->is_dir" 4 .IX Item "$file->is_dir" Returns a boolean value indicating whether this object represents a directory. Not surprisingly, \f(CW\*(C`Path::Class::File\*(C'\fR objects always return false, and Path::Class::Dir objects always return true. .ie n .IP "$file\->is_absolute" 4 .el .IP "\f(CW$file\fR\->is_absolute" 4 .IX Item "$file->is_absolute" Returns true or false depending on whether the file refers to an absolute path specifier (like \f(CW\*(C`/usr/local/foo.txt\*(C'\fR or \f(CW\*(C`\eWindows\eFoo.txt\*(C'\fR). .ie n .IP "$file\->is_relative" 4 .el .IP "\f(CW$file\fR\->is_relative" 4 .IX Item "$file->is_relative" Returns true or false depending on whether the file refers to a relative path specifier (like \f(CW\*(C`lib/foo.txt\*(C'\fR or \f(CW\*(C`.\eFoo.txt\*(C'\fR). .ie n .IP "$file\->cleanup" 4 .el .IP "\f(CW$file\fR\->cleanup" 4 .IX Item "$file->cleanup" Performs a logical cleanup of the file path. For instance: .Sp .Vb 2 \& my $file = file(\*(Aq/foo//baz/./foo.txt\*(Aq)\->cleanup; \& # $file now represents \*(Aq/foo/baz/foo.txt\*(Aq; .Ve .ie n .IP "$dir\->resolve" 4 .el .IP "\f(CW$dir\fR\->resolve" 4 .IX Item "$dir->resolve" Performs a physical cleanup of the file path. For instance: .Sp .Vb 2 \& my $file = file(\*(Aq/foo/baz/../foo.txt\*(Aq)\->resolve; \& # $file now represents \*(Aq/foo/foo.txt\*(Aq, assuming no symlinks .Ve .Sp This actually consults the filesystem to verify the validity of the path. .ie n .IP "$dir = $file\->dir" 4 .el .IP "\f(CW$dir\fR = \f(CW$file\fR\->dir" 4 .IX Item "$dir = $file->dir" Returns a \f(CW\*(C`Path::Class::Dir\*(C'\fR object representing the directory containing this file. .ie n .IP "$dir = $file\->parent" 4 .el .IP "\f(CW$dir\fR = \f(CW$file\fR\->parent" 4 .IX Item "$dir = $file->parent" A synonym for the \f(CW\*(C`dir()\*(C'\fR method. .ie n .IP "$abs = $file\->absolute" 4 .el .IP "\f(CW$abs\fR = \f(CW$file\fR\->absolute" 4 .IX Item "$abs = $file->absolute" Returns a \f(CW\*(C`Path::Class::File\*(C'\fR object representing \f(CW$file\fR as an absolute path. An optional argument, given as either a string or a Path::Class::Dir object, specifies the directory to use as the base of relativity \- otherwise the current working directory will be used. .ie n .IP "$rel = $file\->relative" 4 .el .IP "\f(CW$rel\fR = \f(CW$file\fR\->relative" 4 .IX Item "$rel = $file->relative" Returns a \f(CW\*(C`Path::Class::File\*(C'\fR object representing \f(CW$file\fR as a relative path. An optional argument, given as either a string or a \&\f(CW\*(C`Path::Class::Dir\*(C'\fR object, specifies the directory to use as the base of relativity \- otherwise the current working directory will be used. .ie n .IP "$foreign = $file\->as_foreign($type)" 4 .el .IP "\f(CW$foreign\fR = \f(CW$file\fR\->as_foreign($type)" 4 .IX Item "$foreign = $file->as_foreign($type)" Returns a \f(CW\*(C`Path::Class::File\*(C'\fR object representing \f(CW$file\fR as it would be specified on a system of type \f(CW$type\fR. Known types include \&\f(CW\*(C`Unix\*(C'\fR, \f(CW\*(C`Win32\*(C'\fR, \f(CW\*(C`Mac\*(C'\fR, \f(CW\*(C`VMS\*(C'\fR, and \f(CW\*(C`OS2\*(C'\fR, i.e. anything for which there is a subclass of \f(CW\*(C`File::Spec\*(C'\fR. .Sp Any generated objects (subdirectories, files, parents, etc.) will also retain this type. .ie n .IP "$foreign = Path::Class::File\->new_foreign($type, @args)" 4 .el .IP "\f(CW$foreign\fR = Path::Class::File\->new_foreign($type, \f(CW@args\fR)" 4 .IX Item "$foreign = Path::Class::File->new_foreign($type, @args)" Returns a \f(CW\*(C`Path::Class::File\*(C'\fR object representing a file as it would be specified on a system of type \f(CW$type\fR. Known types include \&\f(CW\*(C`Unix\*(C'\fR, \f(CW\*(C`Win32\*(C'\fR, \f(CW\*(C`Mac\*(C'\fR, \f(CW\*(C`VMS\*(C'\fR, and \f(CW\*(C`OS2\*(C'\fR, i.e. anything for which there is a subclass of \f(CW\*(C`File::Spec\*(C'\fR. .Sp The arguments in \f(CW@args\fR are the same as they would be specified in \&\f(CW\*(C`new()\*(C'\fR. .ie n .IP "$fh = $file\->open($mode, $permissions)" 4 .el .IP "\f(CW$fh\fR = \f(CW$file\fR\->open($mode, \f(CW$permissions\fR)" 4 .IX Item "$fh = $file->open($mode, $permissions)" Passes the given arguments, including \f(CW$file\fR, to \f(CW\*(C`IO::File\->new\*(C'\fR (which in turn calls \f(CW\*(C`IO::File\->open\*(C'\fR and returns the result as an IO::File object. If the opening fails, \f(CW\*(C`undef\*(C'\fR is returned and \f(CW$!\fR is set. .ie n .IP "$fh = $file\->\fBopenr()\fR" 4 .el .IP "\f(CW$fh\fR = \f(CW$file\fR\->\fBopenr()\fR" 4 .IX Item "$fh = $file->openr()" A shortcut for .Sp .Vb 1 \& $fh = $file\->open(\*(Aqr\*(Aq) or croak "Can\*(Aqt read $file: $!"; .Ve .ie n .IP "$fh = $file\->\fBopenw()\fR" 4 .el .IP "\f(CW$fh\fR = \f(CW$file\fR\->\fBopenw()\fR" 4 .IX Item "$fh = $file->openw()" A shortcut for .Sp .Vb 1 \& $fh = $file\->open(\*(Aqw\*(Aq) or croak "Can\*(Aqt write to $file: $!"; .Ve .ie n .IP "$fh = $file\->\fBopena()\fR" 4 .el .IP "\f(CW$fh\fR = \f(CW$file\fR\->\fBopena()\fR" 4 .IX Item "$fh = $file->opena()" A shortcut for .Sp .Vb 1 \& $fh = $file\->open(\*(Aqa\*(Aq) or croak "Can\*(Aqt append to $file: $!"; .Ve .ie n .IP "$file\->touch" 4 .el .IP "\f(CW$file\fR\->touch" 4 .IX Item "$file->touch" Sets the modification and access time of the given file to right now, if the file exists. If it doesn't exist, \f(CW\*(C`touch()\*(C'\fR will \fImake\fR it exist, and \- \s-1YES\s0! \- set its modification and access time to now. .ie n .IP "$file\->\fBslurp()\fR" 4 .el .IP "\f(CW$file\fR\->\fBslurp()\fR" 4 .IX Item "$file->slurp()" In a scalar context, returns the contents of \f(CW$file\fR in a string. In a list context, returns the lines of \f(CW$file\fR (according to how \f(CW$/\fR is set) as a list. If the file can't be read, this method will throw an exception. .Sp If you want \f(CW\*(C`chomp()\*(C'\fR run on each line of the file, pass a true value for the \f(CW\*(C`chomp\*(C'\fR or \f(CW\*(C`chomped\*(C'\fR parameters: .Sp .Vb 1 \& my @lines = $file\->slurp(chomp => 1); .Ve .Sp You may also use the \f(CW\*(C`iomode\*(C'\fR parameter to pass in an \s-1IO\s0 mode to use when opening the file, usually \s-1IO\s0 layers (though anything accepted by the \s-1MODE\s0 argument of \f(CW\*(C`open()\*(C'\fR is accepted here). Just make sure it's a \fIreading\fR mode. .Sp .Vb 2 \& my @lines = $file\->slurp(iomode => \*(Aq:crlf\*(Aq); \& my $lines = $file\->slurp(iomode => \*(Aq<:encoding(UTF\-8)\*(Aq); .Ve .Sp The default \f(CW\*(C`iomode\*(C'\fR is \f(CW\*(C`r\*(C'\fR. .Sp Lines can also be automatically split, mimicking the perl command-line option \f(CW\*(C`\-a\*(C'\fR by using the \f(CW\*(C`split\*(C'\fR parameter. If this parameter is used, each line will be returned as an array ref. .Sp .Vb 1 \& my @lines = $file\->slurp( chomp => 1, split => qr/\es*,\es*/ ); .Ve .Sp The \f(CW\*(C`split\*(C'\fR parameter can only be used in a list context. .ie n .IP "$file\->spew( $content );" 4 .el .IP "\f(CW$file\fR\->spew( \f(CW$content\fR );" 4 .IX Item "$file->spew( $content );" The opposite of \*(L"slurp\*(R", this takes a list of strings and prints them to the file in write mode. If the file can't be written to, this method will throw an exception. .Sp The content to be written can be either an array ref or a plain scalar. If the content is an array ref then each entry in the array will be written to the file. .Sp You may use the \f(CW\*(C`iomode\*(C'\fR parameter to pass in an \s-1IO\s0 mode to use when opening the file, just like \*(L"slurp\*(R" supports. .Sp .Vb 1 \& $file\->spew(iomode => \*(Aq>:raw\*(Aq, $content); .Ve .Sp The default \f(CW\*(C`iomode\*(C'\fR is \f(CW\*(C`w\*(C'\fR. .ie n .IP "$file\->spew_lines( $content );" 4 .el .IP "\f(CW$file\fR\->spew_lines( \f(CW$content\fR );" 4 .IX Item "$file->spew_lines( $content );" Just like \f(CW\*(C`spew\*(C'\fR, but, if \f(CW$content\fR is a plain scalar, appends $/ to it, or, if \f(CW$content\fR is an array ref, appends $/ to each element of the array. .Sp Can also take an \f(CW\*(C`iomode\*(C'\fR parameter like \f(CW\*(C`spew\*(C'\fR. Again, the default \f(CW\*(C`iomode\*(C'\fR is \f(CW\*(C`w\*(C'\fR. .ie n .IP "$file\->traverse(sub { ... }, @args)" 4 .el .IP "\f(CW$file\fR\->traverse(sub { ... }, \f(CW@args\fR)" 4 .IX Item "$file->traverse(sub { ... }, @args)" Calls the given callback on \f(CW$file\fR. This doesn't do much on its own, but see the associated documentation in Path::Class::Dir. .ie n .IP "$file\->\fBremove()\fR" 4 .el .IP "\f(CW$file\fR\->\fBremove()\fR" 4 .IX Item "$file->remove()" This method will remove the file in a way that works well on all platforms, and returns a boolean value indicating whether or not the file was successfully removed. .Sp \&\f(CW\*(C`remove()\*(C'\fR is better than simply calling Perl's \f(CW\*(C`unlink()\*(C'\fR function, because on some platforms (notably \s-1VMS\s0) you actually may need to call \&\f(CW\*(C`unlink()\*(C'\fR several times before all versions of the file are gone \- the \f(CW\*(C`remove()\*(C'\fR method handles this process for you. .ie n .IP "$st = $file\->\fBstat()\fR" 4 .el .IP "\f(CW$st\fR = \f(CW$file\fR\->\fBstat()\fR" 4 .IX Item "$st = $file->stat()" Invokes \f(CW\*(C`File::stat::stat()\*(C'\fR on this file and returns a File::stat object representing the result. .ie n .IP "$st = $file\->\fBlstat()\fR" 4 .el .IP "\f(CW$st\fR = \f(CW$file\fR\->\fBlstat()\fR" 4 .IX Item "$st = $file->lstat()" Same as \f(CW\*(C`stat()\*(C'\fR, but if \f(CW$file\fR is a symbolic link, \f(CW\*(C`lstat()\*(C'\fR stats the link instead of the file the link points to. .ie n .IP "$class = $file\->\fBdir_class()\fR" 4 .el .IP "\f(CW$class\fR = \f(CW$file\fR\->\fBdir_class()\fR" 4 .IX Item "$class = $file->dir_class()" Returns the class which should be used to create directory objects. .Sp Generally overridden whenever this class is subclassed. .ie n .IP "$copy = $file\->copy_to( $dest );" 4 .el .IP "\f(CW$copy\fR = \f(CW$file\fR\->copy_to( \f(CW$dest\fR );" 4 .IX Item "$copy = $file->copy_to( $dest );" Copies the \f(CW$file\fR to \f(CW$dest\fR. It returns a Path::Class::File object when successful, \f(CW\*(C`undef\*(C'\fR otherwise. .ie n .IP "$moved = $file\->move_to( $dest );" 4 .el .IP "\f(CW$moved\fR = \f(CW$file\fR\->move_to( \f(CW$dest\fR );" 4 .IX Item "$moved = $file->move_to( $dest );" Moves the \f(CW$file\fR to \f(CW$dest\fR, and updates \f(CW$file\fR accordingly. .Sp It returns \f(CW$file\fR is successful, \f(CW\*(C`undef\*(C'\fR otherwise. .SH "AUTHOR" .IX Header "AUTHOR" Ken Williams, kwilliams@cpan.org .SH "SEE ALSO" .IX Header "SEE ALSO" Path::Class, Path::Class::Dir, File::Spec man/man3/IO::Tty.3pm000044400000020230152462503210007765 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Tty 3" .TH Tty 3 "2021-01-22" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" IO::Tty \- Low\-level allocate a pseudo\-Tty, import constants. .SH "VERSION" .IX Header "VERSION" 1.16 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use IO::Tty qw(TIOCNOTTY); \& ... \& # use only to import constants, see IO::Pty to create ptys. .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\f(CW\*(C`IO::Tty\*(C'\fR is used internally by \f(CW\*(C`IO::Pty\*(C'\fR to create a pseudo-tty. You wouldn't want to use it directly except to import constants, use \&\f(CW\*(C`IO::Pty\*(C'\fR. For a list of importable constants, see IO::Tty::Constant. .PP Windows is now supported, but \s-1ONLY\s0 under the Cygwin environment, see . .PP Please note that pty creation is very system-dependend. From my experience, any modern \s-1POSIX\s0 system should be fine. Find below a list of systems that \f(CW\*(C`IO::Tty\*(C'\fR should work on. A more detailed table (which is slowly getting out-of-date) is available from the project pages document manager at SourceForge . .PP If you have problems on your system and your system is listed in the \&\*(L"verified\*(R" list, you probably have some non-standard setup, e.g. you compiled your Linux-kernel yourself and disabled ptys (bummer!). Please ask your friendly sysadmin for help. .PP If your system is not listed, unpack the latest version of \f(CW\*(C`IO::Tty\*(C'\fR, do a \f(CW\*(Aqperl Makefile.PL; make; make test; uname \-a\*(Aq\fR and send me (\fIRGiersig@cpan.org\fR) the results and I'll see what I can deduce from that. There are chances that it will work right out-of-the-box... .PP If it's working on your system, please send me a short note with details (version number, distribution, etc. 'uname \-a' and 'perl \-V' is a good start; also, the output from \*(L"perl Makefile.PL\*(R" contains a lot of interesting info, so please include that as well) so I can get an overview. Thanks! .SH "VERIFIED SYSTEMS, KNOWN ISSUES" .IX Header "VERIFIED SYSTEMS, KNOWN ISSUES" This is a list of systems that \f(CW\*(C`IO::Tty\*(C'\fR seems to work on ('make test' passes) with comments about \*(L"features\*(R": .IP "\(bu" 4 \&\s-1AIX 4.3\s0 .Sp Returns \s-1EIO\s0 instead of \s-1EOF\s0 when the slave is closed. Benign. .IP "\(bu" 4 \&\s-1AIX 5\s0.x .IP "\(bu" 4 FreeBSD 4.4 .Sp \&\s-1EOF\s0 on the slave tty is not reported back to the master. .IP "\(bu" 4 OpenBSD 2.8 .Sp The ioctl \s-1TIOCSCTTY\s0 sometimes fails. This is also known in Tcl/Expect, see http://expect.nist.gov/FAQ.html .Sp \&\s-1EOF\s0 on the slave tty is not reported back to the master. .IP "\(bu" 4 Darwin 7.9.0 .IP "\(bu" 4 \&\s-1HPUX 10.20 & 11.00\s0 .Sp \&\s-1EOF\s0 on the slave tty is not reported back to the master. .IP "\(bu" 4 \&\s-1IRIX 6.5\s0 .IP "\(bu" 4 Linux 2.2.x & 2.4.x .Sp Returns \s-1EIO\s0 instead of \s-1EOF\s0 when the slave is closed. Benign. .IP "\(bu" 4 \&\s-1OSF 4.0\s0 .Sp \&\s-1EOF\s0 on the slave tty is not reported back to the master. .IP "\(bu" 4 Solaris 8, 2.7, 2.6 .Sp Has the \*(L"feature\*(R" of returning \s-1EOF\s0 just once?! .Sp \&\s-1EOF\s0 on the slave tty is not reported back to the master. .IP "\(bu" 4 Windows NT/2k/XP (under Cygwin) .Sp When you send (print) a too long line (>160 chars) to a non-raw pty, the call just hangs forever and even \fBalarm()\fR cannot get you out. Don't complain to me... .Sp \&\s-1EOF\s0 on the slave tty is not reported back to the master. .IP "\(bu" 4 z/OS .PP The following systems have not been verified yet for this version, but a previous version worked on them: .IP "\(bu" 4 \&\s-1SCO\s0 Unix .IP "\(bu" 4 NetBSD .Sp probably the same as the other *BSDs... .PP If you have additions to these lists, please mail them to <\fIRGiersig@cpan.org\fR>. .SH "SEE ALSO" .IX Header "SEE ALSO" IO::Pty, IO::Tty::Constant .SH "MAILING LISTS" .IX Header "MAILING LISTS" As this module is mainly used by Expect, support for it is available via the two Expect mailing lists, expectperl-announce and expectperl-discuss, at .PP .Vb 1 \& http://lists.sourceforge.net/lists/listinfo/expectperl\-announce .Ve .PP and .PP .Vb 1 \& http://lists.sourceforge.net/lists/listinfo/expectperl\-discuss .Ve .SH "AUTHORS" .IX Header "AUTHORS" Originally by Graham Barr <\fIgbarr@pobox.com\fR>, based on the Ptty module by Nick Ing-Simmons <\fInik@tiuk.ti.com\fR>. .PP Now maintained and heavily rewritten by Roland Giersig <\fIRGiersig@cpan.org\fR>. .PP Contains copyrighted stuff from openssh v3.0p1, authored by Tatu Ylonen , Markus Friedl and Todd C. Miller . I also got a lot of inspiration from the pty code in Xemacs. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Now all code is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP Nevertheless the above \s-1AUTHORS\s0 retain their copyrights to the various parts and want to receive credit if their source code is used. See the source for details. .SH "DISCLAIMER" .IX Header "DISCLAIMER" \&\s-1THIS SOFTWARE IS PROVIDED\s0 ``\s-1AS IS\s0'' \s-1AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\s0 (\s-1INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES\s0; \s-1LOSS OF USE, DATA, OR PROFITS\s0; \s-1OR BUSINESS INTERRUPTION\s0) \s-1HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\s0 (\s-1INCLUDING NEGLIGENCE OR OTHERWISE\s0) \s-1ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\s0 .PP In other words: Use at your own risk. Provided as is. Your mileage may vary. Read the source, Luke! .PP And finally, just to be sure: .PP Any Use of This Product, in Any Manner Whatsoever, Will Increase the Amount of Disorder in the Universe. Although No Liability Is Implied Herein, the Consumer Is Warned That This Process Will Ultimately Lead to the Heat Death of the Universe. man/man1/dbiproxy.1000044400000017261152462503210010102 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBIPROXY 1" .TH DBIPROXY 1 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" dbiproxy \- A proxy server for the DBD::Proxy driver .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& dbiproxy \-\-localport= .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This tool is just a front end for the DBI::ProxyServer package. All it does is picking options from the command line and calling \&\fBDBI::ProxyServer::main()\fR. See DBI::ProxyServer for details. .PP Available options include: .IP "\fB\-\-chroot=dir\fR" 4 .IX Item "--chroot=dir" (\s-1UNIX\s0 only) After doing a \fBbind()\fR, change root directory to the given directory by doing a \fBchroot()\fR. This is useful for security, but it restricts the environment a lot. For example, you need to load \s-1DBI\s0 drivers in the config file or you have to create hard links to Unix sockets, if your drivers are using them. For example, with MySQL, a config file might contain the following lines: .Sp .Vb 9 \& my $rootdir = \*(Aq/var/dbiproxy\*(Aq; \& my $unixsockdir = \*(Aq/tmp\*(Aq; \& my $unixsockfile = \*(Aqmysql.sock\*(Aq; \& foreach $dir ($rootdir, "$rootdir$unixsockdir") { \& mkdir 0755, $dir; \& } \& link("$unixsockdir/$unixsockfile", \& "$rootdir$unixsockdir/$unixsockfile"); \& require DBD::mysql; \& \& { \& \*(Aqchroot\*(Aq => $rootdir, \& ... \& } .Ve .Sp If you don't know \fBchroot()\fR, think of an \s-1FTP\s0 server where you can see a certain directory tree only after logging in. See also the \-\-group and \&\-\-user options. .IP "\fB\-\-configfile=file\fR" 4 .IX Item "--configfile=file" Config files are assumed to return a single hash ref that overrides the arguments of the new method. However, command line arguments in turn take precedence over the config file. See the \*(L"\s-1CONFIGURATION FILE\*(R"\s0 section in the DBI::ProxyServer documentation for details on the config file. .IP "\fB\-\-debug\fR" 4 .IX Item "--debug" Turn debugging mode on. Mainly this asserts that logging messages of level \*(L"debug\*(R" are created. .IP "\fB\-\-facility=mode\fR" 4 .IX Item "--facility=mode" (\s-1UNIX\s0 only) Facility to use for Sys::Syslog. The default is \&\fBdaemon\fR. .IP "\fB\-\-group=gid\fR" 4 .IX Item "--group=gid" After doing a \fBbind()\fR, change the real and effective \s-1GID\s0 to the given. This is useful, if you want your server to bind to a privileged port (<1024), but don't want the server to execute as root. See also the \-\-user option. .Sp \&\s-1GID\s0's can be passed as group names or numeric values. .IP "\fB\-\-localaddr=ip\fR" 4 .IX Item "--localaddr=ip" By default a daemon is listening to any \s-1IP\s0 number that a machine has. This attribute allows one to restrict the server to the given \&\s-1IP\s0 number. .IP "\fB\-\-localport=port\fR" 4 .IX Item "--localport=port" This attribute sets the port on which the daemon is listening. It must be given somehow, as there's no default. .IP "\fB\-\-logfile=file\fR" 4 .IX Item "--logfile=file" Be default logging messages will be written to the syslog (Unix) or to the event log (Windows \s-1NT\s0). On other operating systems you need to specify a log file. The special value \*(L"\s-1STDERR\*(R"\s0 forces logging to stderr. See Net::Daemon::Log for details. .IP "\fB\-\-mode=modename\fR" 4 .IX Item "--mode=modename" The server can run in three different modes, depending on the environment. .Sp If you are running Perl 5.005 and did compile it for threads, then the server will create a new thread for each connection. The thread will execute the server's \fBRun()\fR method and then terminate. This mode is the default, you can force it with \*(L"\-\-mode=threads\*(R". .Sp If threads are not available, but you have a working \fBfork()\fR, then the server will behave similar by creating a new process for each connection. This mode will be used automatically in the absence of threads or if you use the \*(L"\-\-mode=fork\*(R" option. .Sp Finally there's a single-connection mode: If the server has accepted a connection, he will enter the \fBRun()\fR method. No other connections are accepted until the \fBRun()\fR method returns (if the client disconnects). This operation mode is useful if you have neither threads nor \fBfork()\fR, for example on the Macintosh. For debugging purposes you can force this mode with \*(L"\-\-mode=single\*(R". .IP "\fB\-\-pidfile=file\fR" 4 .IX Item "--pidfile=file" (\s-1UNIX\s0 only) If this option is present, a \s-1PID\s0 file will be created at the given location. Default is to not create a pidfile. .IP "\fB\-\-user=uid\fR" 4 .IX Item "--user=uid" After doing a \fBbind()\fR, change the real and effective \s-1UID\s0 to the given. This is useful, if you want your server to bind to a privileged port (<1024), but don't want the server to execute as root. See also the \-\-group and the \-\-chroot options. .Sp \&\s-1UID\s0's can be passed as group names or numeric values. .IP "\fB\-\-version\fR" 4 .IX Item "--version" Suppresses startup of the server; instead the version string will be printed and the program exits immediately. .SH "AUTHOR" .IX Header "AUTHOR" .Vb 4 \& Copyright (c) 1997 Jochen Wiedmann \& Am Eisteich 9 \& 72555 Metzingen \& Germany \& \& Email: joe@ispsoft.de \& Phone: +49 7123 14881 .Ve .PP The DBI::ProxyServer module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. In particular permission is granted to Tim Bunce for distributing this as a part of the \s-1DBI.\s0 .SH "SEE ALSO" .IX Header "SEE ALSO" DBI::ProxyServer, DBD::Proxy, \s-1DBI\s0 man/man1/lwp-request.1000044400000017722152462503210010534 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP-REQUEST 1" .TH LWP-REQUEST 1 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" lwp\-request \- Simple command line user agent .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBlwp-request\fR [\fB\-afPuUsSedvhx\fR] [\fB\-m\fR \fImethod\fR] [\fB\-b\fR \fIbase \s-1URL\s0\fR] [\fB\-t\fR \fItimeout\fR] [\fB\-i\fR \fIif-modified-since\fR] [\fB\-c\fR \fIcontent-type\fR] [\fB\-C\fR \fIcredentials\fR] [\fB\-p\fR \fIproxy-url\fR] [\fB\-o\fR \fIformat\fR] \fIurl\fR... .SH "DESCRIPTION" .IX Header "DESCRIPTION" This program can be used to send requests to \s-1WWW\s0 servers and your local file system. The request content for \s-1POST\s0 and \s-1PUT\s0 methods is read from stdin. The content of the response is printed on stdout. Error messages are printed on stderr. The program returns a status value indicating the number of URLs that failed. .PP The options are: .IP "\-m " 4 .IX Item "-m " Set which method to use for the request. If this option is not used, then the method is derived from the name of the program. .IP "\-f" 4 .IX Item "-f" Force request through, even if the program believes that the method is illegal. The server might reject the request eventually. .IP "\-b " 4 .IX Item "-b " This \s-1URI\s0 will be used as the base \s-1URI\s0 for resolving all relative URIs given as argument. .IP "\-t " 4 .IX Item "-t " Set the timeout value for the requests. The timeout is the amount of time that the program will wait for a response from the remote server before it fails. The default unit for the timeout value is seconds. You might append \*(L"m\*(R" or \*(L"h\*(R" to the timeout value to make it minutes or hours, respectively. The default timeout is '3m', i.e. 3 minutes. .IP "\-i
    " 4 .IX Item "-H
    " Send this \s-1HTTP\s0 header with each request. You can specify several, e.g.: .Sp .Vb 4 \& lwp\-request \e \& \-H \*(AqReferer: http://other.url/\*(Aq \e \& \-H \*(AqHost: somehost\*(Aq \e \& http://this.url/ .Ve .IP "\-C :" 4 .IX Item "-C :" Provide credentials for documents that are protected by Basic Authentication. If the document is protected and you did not specify the username and password with this option, then you will be prompted to provide these values. .PP The following options controls what is displayed by the program: .IP "\-u" 4 .IX Item "-u" Print request method and absolute \s-1URL\s0 as requests are made. .IP "\-U" 4 .IX Item "-U" Print request headers in addition to request method and absolute \s-1URL.\s0 .IP "\-s" 4 .IX Item "-s" Print response status code. This option is always on for \s-1HEAD\s0 requests. .IP "\-S" 4 .IX Item "-S" Print response status chain. This shows redirect and authorization requests that are handled by the library. .IP "\-e" 4 .IX Item "-e" Print response headers. This option is always on for \s-1HEAD\s0 requests. .IP "\-E" 4 .IX Item "-E" Print response status chain with full response headers. .IP "\-d" 4 .IX Item "-d" Do \fBnot\fR print the content of the response. .IP "\-o " 4 .IX Item "-o " Process \s-1HTML\s0 content in various ways before printing it. If the content type of the response is not \s-1HTML,\s0 then this option has no effect. The legal format values are; \f(CW\*(C`text\*(C'\fR, \f(CW\*(C`ps\*(C'\fR, \f(CW\*(C`links\*(C'\fR, \&\f(CW\*(C`html\*(C'\fR and \f(CW\*(C`dump\*(C'\fR. .Sp If you specify the \f(CW\*(C`text\*(C'\fR format then the \s-1HTML\s0 will be formatted as plain \f(CW\*(C`latin1\*(C'\fR text. If you specify the \f(CW\*(C`ps\*(C'\fR format then it will be formatted as Postscript. .Sp The \f(CW\*(C`links\*(C'\fR format will output all links found in the \s-1HTML\s0 document. Relative links will be expanded to absolute ones. .Sp The \f(CW\*(C`html\*(C'\fR format will reformat the \s-1HTML\s0 code and the \f(CW\*(C`dump\*(C'\fR format will just dump the \s-1HTML\s0 syntax tree. .Sp Note that the \f(CW\*(C`HTML\-Tree\*(C'\fR distribution needs to be installed for this option to work. In addition the \f(CW\*(C`HTML\-Format\*(C'\fR distribution needs to be installed for \f(CW\*(C`\-o text\*(C'\fR or \f(CW\*(C`\-o ps\*(C'\fR to work. .IP "\-v" 4 .IX Item "-v" Print the version number of the program and quit. .IP "\-h" 4 .IX Item "-h" Print usage message and quit. .IP "\-a" 4 .IX Item "-a" Set text(ascii) mode for content input and output. If this option is not used, content input and output is done in binary mode. .PP Because this program is implemented using the \s-1LWP\s0 library, it will only support the protocols that \s-1LWP\s0 supports. .SH "SEE ALSO" .IX Header "SEE ALSO" lwp-mirror, \s-1LWP\s0 .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 1995\-1999 Gisle Aas. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas man/man1/json_xs.1000044400000020407152462503210007721 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON_XS 1" .TH JSON_XS 1 "2018-11-15" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" json_xs \- JSON::XS commandline utility .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& json_xs [\-v] [\-f inputformat] [\-t outputformat] .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fIjson_xs\fR converts between some input and output formats (one of them is \&\s-1JSON\s0). .PP The default input format is \f(CW\*(C`json\*(C'\fR and the default output format is \&\f(CW\*(C`json\-pretty\*(C'\fR. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\-v" 4 .IX Item "-v" Be slightly more verbose. .IP "\-f fromformat" 4 .IX Item "-f fromformat" Read a file in the given format from \s-1STDIN.\s0 .Sp \&\f(CW\*(C`fromformat\*(C'\fR can be one of: .RS 4 .IP "json \- a json text encoded, either utf\-8, utf16\-be/le, utf32\-be/le" 4 .IX Item "json - a json text encoded, either utf-8, utf16-be/le, utf32-be/le" .PD 0 .IP "cbor \- \s-1CBOR\s0 (\s-1RFC 7049,\s0 \s-1CBOR::XS\s0), a kind of binary \s-1JSON\s0" 4 .IX Item "cbor - CBOR (RFC 7049, CBOR::XS), a kind of binary JSON" .IP "storable \- a Storable frozen value" 4 .IX Item "storable - a Storable frozen value" .IP "storable-file \- a Storable file (Storable has two incompatible formats)" 4 .IX Item "storable-file - a Storable file (Storable has two incompatible formats)" .IP "bencode \- use Convert::Bencode, if available (used by torrent files, among others)" 4 .IX Item "bencode - use Convert::Bencode, if available (used by torrent files, among others)" .IP "clzf \- Compress::LZF format (requires that module to be installed)" 4 .IX Item "clzf - Compress::LZF format (requires that module to be installed)" .ie n .IP "eval \- evaluate the given code as (non\-utf\-8) Perl, basically the reverse of ""\-t dump""" 4 .el .IP "eval \- evaluate the given code as (non\-utf\-8) Perl, basically the reverse of ``\-t dump''" 4 .IX Item "eval - evaluate the given code as (non-utf-8) Perl, basically the reverse of -t dump" .IP "yaml \- \s-1YAML\s0 format (requires that module to be installed)" 4 .IX Item "yaml - YAML format (requires that module to be installed)" .IP "string \- do not attempt to decode the file data" 4 .IX Item "string - do not attempt to decode the file data" .ie n .IP "none \- nothing is read, creates an ""undef"" scalar \- mainly useful with ""\-e""" 4 .el .IP "none \- nothing is read, creates an \f(CWundef\fR scalar \- mainly useful with \f(CW\-e\fR" 4 .IX Item "none - nothing is read, creates an undef scalar - mainly useful with -e" .RE .RS 4 .RE .IP "\-t toformat" 4 .IX Item "-t toformat" .PD Write the file in the given format to \s-1STDOUT.\s0 .Sp \&\f(CW\*(C`toformat\*(C'\fR can be one of: .RS 4 .IP "json, json\-utf\-8 \- json, utf\-8 encoded" 4 .IX Item "json, json-utf-8 - json, utf-8 encoded" .PD 0 .IP "json-pretty \- as above, but pretty-printed" 4 .IX Item "json-pretty - as above, but pretty-printed" .IP "json\-utf\-16le, json\-utf\-16be \- little endian/big endian utf\-16" 4 .IX Item "json-utf-16le, json-utf-16be - little endian/big endian utf-16" .IP "json\-utf\-32le, json\-utf\-32be \- little endian/big endian utf\-32" 4 .IX Item "json-utf-32le, json-utf-32be - little endian/big endian utf-32" .IP "cbor \- \s-1CBOR\s0 (\s-1RFC 7049,\s0 \s-1CBOR::XS\s0), a kind of binary \s-1JSON\s0" 4 .IX Item "cbor - CBOR (RFC 7049, CBOR::XS), a kind of binary JSON" .IP "cbor-packed \- \s-1CBOR\s0 using extensions to make it smaller" 4 .IX Item "cbor-packed - CBOR using extensions to make it smaller" .IP "storable \- a Storable frozen value in network format" 4 .IX Item "storable - a Storable frozen value in network format" .IP "storable-file \- a Storable file in network format (Storable has two incompatible formats)" 4 .IX Item "storable-file - a Storable file in network format (Storable has two incompatible formats)" .IP "bencode \- use Convert::Bencode, if available (used by torrent files, among others)" 4 .IX Item "bencode - use Convert::Bencode, if available (used by torrent files, among others)" .IP "clzf \- Compress::LZF format" 4 .IX Item "clzf - Compress::LZF format" .IP "yaml \- \s-1YAML::XS\s0 format" 4 .IX Item "yaml - YAML::XS format" .IP "dump \- Data::Dump" 4 .IX Item "dump - Data::Dump" .IP "dumper \- Data::Dumper" 4 .IX Item "dumper - Data::Dumper" .IP "string \- writes the data out as if it were a string" 4 .IX Item "string - writes the data out as if it were a string" .ie n .IP "none \- nothing gets written, mainly useful together with ""\-e""" 4 .el .IP "none \- nothing gets written, mainly useful together with \f(CW\-e\fR" 4 .IX Item "none - nothing gets written, mainly useful together with -e" .PD Note that Data::Dumper doesn't handle self-referential data structures correctly \- use \*(L"dump\*(R" instead. .RE .RS 4 .RE .IP "\-e code" 4 .IX Item "-e code" Evaluate perl code after reading the data and before writing it out again \&\- can be used to filter, create or extract data. The data that has been written is in \f(CW$_\fR, and whatever is in there is written out afterwards. .SH "EXAMPLES" .IX Header "EXAMPLES" .Vb 1 \& json_xs \-t none pretty.json .Ve .PP Prettify the \s-1JSON\s0 file \fIsrc.json\fR to \fIdst.json\fR. .PP .Vb 1 \& json_xs \-f storable\-file {"announce\-list"}}\*(Aq \-t string .Ve .PP Print the tracker list inside a torrent file. .PP .Vb 1 \& lwp\-request http://cpantesters.perl.org/show/JSON\-XS.json | json_xs .Ve .PP Fetch the cpan-testers result summary \f(CW\*(C`JSON::XS\*(C'\fR and pretty-print it. .SH "AUTHOR" .IX Header "AUTHOR" Copyright (C) 2008 Marc Lehmann man/man1/lwp-mirror.1000044400000006302152462503210010346 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP-MIRROR 1" .TH LWP-MIRROR 1 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" lwp\-mirror \- Simple mirror utility .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& lwp\-mirror [\-v] [\-t timeout] .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This program can be used to mirror a document from a \s-1WWW\s0 server. The document is only transferred if the remote copy is newer than the local copy. If the local copy is newer nothing happens. .PP Use the \f(CW\*(C`\-v\*(C'\fR option to print the version number of this program. .PP The timeout value specified with the \f(CW\*(C`\-t\*(C'\fR option. The timeout value is the time that the program will wait for response from the remote server before it fails. The default unit for the timeout value is seconds. You might append \*(L"m\*(R" or \*(L"h\*(R" to the timeout value to make it minutes or hours, respectively. .PP Because this program is implemented using the \s-1LWP\s0 library, it only supports the protocols that \s-1LWP\s0 supports. .SH "SEE ALSO" .IX Header "SEE ALSO" lwp-request, \s-1LWP\s0 .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas man/man1/dbilogstrip.1000044400000006763152462503210010571 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBILOGSTRIP 1" .TH DBILOGSTRIP 1 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" dbilogstrip \- filter to normalize DBI trace logs for diff'ing .SH "SYNOPSIS" .IX Header "SYNOPSIS" Read \s-1DBI\s0 trace file \f(CW\*(C`dbitrace.log\*(C'\fR and write out a stripped version to \f(CW\*(C`dbitrace_stripped.log\*(C'\fR .PP .Vb 1 \& dbilogstrip dbitrace.log > dbitrace_stripped.log .Ve .PP Run \f(CW\*(C`yourscript.pl\*(C'\fR twice, each with different sets of arguments, with \&\s-1DBI_TRACE\s0 enabled. Filter the output and trace through \f(CW\*(C`dbilogstrip\*(C'\fR into a separate file for each run. Then compare using diff. (This example assumes you're using a standard shell.) .PP .Vb 3 \& DBI_TRACE=2 perl yourscript.pl ...args1... 2>&1 | dbilogstrip > dbitrace1.log \& DBI_TRACE=2 perl yourscript.pl ...args2... 2>&1 | dbilogstrip > dbitrace2.log \& diff \-u dbitrace1.log dbitrace2.log .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Replaces any hex addresses, e.g, \f(CW0x128f72ce\fR with \f(CW\*(C`0xN\*(C'\fR. .PP Replaces any references to process id or thread id, like \f(CW\*(C`pid#6254\*(C'\fR with \f(CW\*(C`pidN\*(C'\fR. .PP So a \s-1DBI\s0 trace line like this: .PP .Vb 1 \& \-> STORE for DBD::DBM::st (DBI::st=HASH(0x19162a0)~0x191f9c8 \*(Aqf_params\*(Aq ARRAY(0x1922018)) thr#1800400 .Ve .PP will look like this: .PP .Vb 1 \& \-> STORE for DBD::DBM::st (DBI::st=HASH(0xN)~0xN \*(Aqf_params\*(Aq ARRAY(0xN)) thrN .Ve man/man1/json_pp.1000044400000012211152462503210007700 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "JSON_PP 1" .TH JSON_PP 1 "2021-01-17" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" json_pp \- JSON::PP command utility .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& json_pp [\-v] [\-f from_format] [\-t to_format] [\-json_opt options_to_json1[,options_to_json2[,...]]] .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" json_pp converts between some input and output formats (one of them is \s-1JSON\s0). This program was copied from json_xs and modified. .PP The default input format is json and the default output format is json with pretty option. .SH "OPTIONS" .IX Header "OPTIONS" .SS "\-f" .IX Subsection "-f" .Vb 1 \& \-f from_format .Ve .PP Reads a data in the given format from \s-1STDIN.\s0 .PP Format types: .IP "json" 4 .IX Item "json" as \s-1JSON\s0 .IP "eval" 4 .IX Item "eval" as Perl code .SS "\-t" .IX Subsection "-t" Writes a data in the given format to \s-1STDOUT.\s0 .IP "null" 4 .IX Item "null" no action. .IP "json" 4 .IX Item "json" as \s-1JSON\s0 .IP "dumper" 4 .IX Item "dumper" as Data::Dumper .SS "\-json_opt" .IX Subsection "-json_opt" options to \s-1JSON::PP\s0 .PP Acceptable options are: .PP .Vb 2 \& ascii latin1 utf8 pretty indent space_before space_after relaxed canonical allow_nonref \& allow_singlequote allow_barekey allow_bignum loose escape_slash indent_length .Ve .PP Multiple options must be separated by commas: .PP .Vb 1 \& Right: \-json_opt pretty,canonical \& \& Wrong: \-json_opt pretty \-json_opt canonical .Ve .SS "\-v" .IX Subsection "-v" Verbose option, but currently no action in fact. .SS "\-V" .IX Subsection "-V" Prints version and exits. .SH "EXAMPLES" .IX Header "EXAMPLES" .Vb 2 \& $ perl \-e\*(Aqprint q|{"foo":"あい","bar":1234567890000000000000000}|\*(Aq |\e \& json_pp \-f json \-t dumper \-json_opt pretty,utf8,allow_bignum \& \& $VAR1 = { \& \*(Aqbar\*(Aq => bless( { \& \*(Aqvalue\*(Aq => [ \& \*(Aq0000000\*(Aq, \& \*(Aq0000000\*(Aq, \& \*(Aq5678900\*(Aq, \& \*(Aq1234\*(Aq \& ], \& \*(Aqsign\*(Aq => \*(Aq+\*(Aq \& }, \*(AqMath::BigInt\*(Aq ), \& \*(Aqfoo\*(Aq => "\ex{3042}\ex{3044}" \& }; \& \& $ perl \-e\*(Aqprint q|{"foo":"あい","bar":1234567890000000000000000}|\*(Aq |\e \& json_pp \-f json \-t dumper \-json_opt pretty \& \& $VAR1 = { \& \*(Aqbar\*(Aq => \*(Aq1234567890000000000000000\*(Aq, \& \*(Aqfoo\*(Aq => "\ex{e3}\ex{81}\ex{82}\ex{e3}\ex{81}\ex{84}" \& }; .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1JSON::PP\s0, json_xs .SH "AUTHOR" .IX Header "AUTHOR" Makamaka Hannyaharamitu, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2010 by Makamaka Hannyaharamitu .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. man/man1/dbiprof.1000044400000014566152462503210007674 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBIPROF 1" .TH DBIPROF 1 "2021-11-23" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" dbiprof \- command\-line client for DBI::ProfileData .SH "SYNOPSIS" .IX Header "SYNOPSIS" See a report of the ten queries with the longest total runtime in the profile dump file \fIprof1.out\fR: .PP .Vb 1 \& dbiprof prof1.out .Ve .PP See the top 10 most frequently run queries in the profile file \&\fIdbi.prof\fR (the default): .PP .Vb 1 \& dbiprof \-\-sort count .Ve .PP See the same report with 15 entries: .PP .Vb 1 \& dbiprof \-\-sort count \-\-number 15 .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This tool is a command-line client for the DBI::ProfileData. It allows you to analyze the profile data file produced by DBI::ProfileDumper and produce various useful reports. .SH "OPTIONS" .IX Header "OPTIONS" This program accepts the following options: .IP "\-\-number N" 4 .IX Item "--number N" Produce this many items in the report. Defaults to 10. If set to \&\*(L"all\*(R" then all results are shown. .IP "\-\-sort field" 4 .IX Item "--sort field" Sort results by the given field. Sorting by multiple fields isn't currently supported (patches welcome). The available sort fields are: .RS 4 .IP "total" 4 .IX Item "total" Sorts by total time run time across all runs. This is the default sort. .IP "longest" 4 .IX Item "longest" Sorts by the longest single run. .IP "count" 4 .IX Item "count" Sorts by total number of runs. .IP "first" 4 .IX Item "first" Sorts by the time taken in the first run. .IP "shortest" 4 .IX Item "shortest" Sorts by the shortest single run. .IP "key1" 4 .IX Item "key1" Sorts by the value of the first element in the Path, which should be numeric. You can also sort by \f(CW\*(C`key2\*(C'\fR and \f(CW\*(C`key3\*(C'\fR. .RE .RS 4 .RE .IP "\-\-reverse" 4 .IX Item "--reverse" Reverses the selected sort. For example, to see a report of the shortest overall time: .Sp .Vb 1 \& dbiprof \-\-sort total \-\-reverse .Ve .IP "\-\-match keyN=value" 4 .IX Item "--match keyN=value" Consider only items where the specified key matches the given value. Keys are numbered from 1. For example, let's say you used a DBI::Profile Path of: .Sp .Vb 1 \& [ DBIprofile_Statement, DBIprofile_Methodname ] .Ve .Sp And called dbiprof as in: .Sp .Vb 1 \& dbiprof \-\-match key2=execute .Ve .Sp Your report would only show execute queries, leaving out prepares, fetches, etc. .Sp If the value given starts and ends with slashes (\f(CW\*(C`/\*(C'\fR) then it will be treated as a regular expression. For example, to only include \s-1SELECT\s0 queries where key1 is the statement: .Sp .Vb 1 \& dbiprof \-\-match key1=/^SELECT/ .Ve .Sp By default the match expression is matched case-insensitively, but this can be changed with the \-\-case\-sensitive option. .IP "\-\-exclude keyN=value" 4 .IX Item "--exclude keyN=value" Remove items for where the specified key matches the given value. For example, to exclude all prepare entries where key2 is the method name: .Sp .Vb 1 \& dbiprof \-\-exclude key2=prepare .Ve .Sp Like \f(CW\*(C`\-\-match\*(C'\fR, If the value given starts and ends with slashes (\f(CW\*(C`/\*(C'\fR) then it will be treated as a regular expression. For example, to exclude \s-1UPDATE\s0 queries where key1 is the statement: .Sp .Vb 1 \& dbiprof \-\-match key1=/^UPDATE/ .Ve .Sp By default the exclude expression is matched case-insensitively, but this can be changed with the \-\-case\-sensitive option. .IP "\-\-case\-sensitive" 4 .IX Item "--case-sensitive" Using this option causes \-\-match and \-\-exclude to work case-sensitively. Defaults to off. .IP "\-\-delete" 4 .IX Item "--delete" Sets the \f(CW\*(C`DeleteFiles\*(C'\fR option to DBI::ProfileData which causes the files to be deleted after reading. See DBI::ProfileData for more details. .IP "\-\-dumpnodes" 4 .IX Item "--dumpnodes" Print the list of nodes in the form of a perl data structure. Use the \f(CW\*(C`\-sort\*(C'\fR option if you want the list sorted. .IP "\-\-version" 4 .IX Item "--version" Print the dbiprof version number and exit. .SH "AUTHOR" .IX Header "AUTHOR" Sam Tregar .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2002 Sam Tregar .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself. .SH "SEE ALSO" .IX Header "SEE ALSO" DBI::ProfileDumper, DBI::Profile, \s-1DBI\s0. man/man1/lwp-download.1000044400000010316152462503210010643 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP-DOWNLOAD 1" .TH LWP-DOWNLOAD 1 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" lwp\-download \- Fetch large files from the web .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& lwp\-download [\-a] [\-s] [] \& \& Options: \& \& \-a save the file in ASCII mode \& \-s use HTTP headers to guess output filename .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \fBlwp-download\fR program will save the file at \fIurl\fR to a local file. .PP If \fIlocal path\fR is not specified, then the current directory is assumed. .PP If \fIlocal path\fR is a directory, then the last segment of the path of the \&\fIurl\fR is appended to form a local filename. If the \fIurl\fR path ends with slash the name \*(L"index\*(R" is used. With the \fB\-s\fR option pick up the last segment of the filename from server provided sources like the Content-Disposition header or any redirect URLs. A file extension to match the server reported Content-Type might also be appended. If a file with the produced filename already exists, then \fBlwp-download\fR will prompt before it overwrites and will fail if its standard input is not a terminal. This form of invocation will also fail is no acceptable filename can be derived from the sources mentioned above. .PP If \fIlocal path\fR is not a directory, then it is simply used as the path to save into. If the file already exists it's overwritten. .PP The \fIlwp-download\fR program is implemented using the \fIlibwww-perl\fR library. It is better suited to down load big files than the \&\fIlwp-request\fR program because it does not store the file in memory. Another benefit is that it will keep you updated about its progress and that you don't have much options to worry about. .PP Use the \f(CW\*(C`\-a\*(C'\fR option to save the file in text (\s-1ASCII\s0) mode. Might make a difference on DOSish systems. .SH "EXAMPLE" .IX Header "EXAMPLE" Fetch the newest and greatest perl version: .PP .Vb 3 \& $ lwp\-download http://www.perl.com/CPAN/src/latest.tar.gz \& Saving to \*(Aqlatest.tar.gz\*(Aq... \& 11.4 MB received in 8 seconds (1.43 MB/sec) .Ve .SH "AUTHOR" .IX Header "AUTHOR" Gisle Aas man/man1/lwp-dump.1000044400000010041152462503210007774 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "LWP-DUMP 1" .TH LWP-DUMP 1 "2021-10-25" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" lwp\-dump \- See what headers and content is returned for a URL .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBlwp-dump\fR [ \fIoptions\fR ] \fI\s-1URL\s0\fR .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \fBlwp-dump\fR program will get the resource identified by the \s-1URL\s0 and then dump the response object to \s-1STDOUT.\s0 This will display the headers returned and the initial part of the content, escaped so that it's safe to display even binary content. The escapes syntax used is the same as for Perl's double quoted strings. If there is no content the string \*(L"(no content)\*(R" is shown in its place. .PP The following options are recognized: .IP "\fB\-\-agent\fR \fIstring\fR" 4 .IX Item "--agent string" Override the user agent string passed to the server. .IP "\fB\-\-keep\-client\-headers\fR" 4 .IX Item "--keep-client-headers" \&\s-1LWP\s0 internally generate various \f(CW\*(C`Client\-*\*(C'\fR headers that are stripped by \&\fBlwp-dump\fR in order to show the headers exactly as the server provided them. This option will suppress this. .IP "\fB\-\-max\-length\fR \fIn\fR" 4 .IX Item "--max-length n" How much of the content to show. The default is 512. Set this to 0 for unlimited. .Sp If the content is longer then the string is chopped at the limit and the string \*(L"...\en(### more bytes not shown)\*(R" appended. .IP "\fB\-\-method\fR \fIstring\fR" 4 .IX Item "--method string" Use the given method for the request instead of the default \*(L"\s-1GET\*(R".\s0 .IP "\fB\-\-parse\-head\fR" 4 .IX Item "--parse-head" By default \fBlwp-dump\fR will not try to initialize headers by looking at the head section of \s-1HTML\s0 documents. This option enables this. This corresponds to \&\*(L"parse_head\*(R" in LWP::UserAgent. .IP "\fB\-\-request\fR" 4 .IX Item "--request" Also dump the request sent. .SH "SEE ALSO" .IX Header "SEE ALSO" lwp-request, \s-1LWP\s0, \*(L"dump\*(R" in HTTP::Message man/man1/use-devel-checklib.1000044400000006560152462503210011675 0ustar00.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "USE-DEVEL-CHECKLIB 1" .TH USE-DEVEL-CHECKLIB 1 "2019-11-12" "perl v5.26.3" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" use\-devel\-checklib \- (DEPRECATED)a script to package Devel::CheckLib with your code. .SH "DESCRIPTION" .IX Header "DESCRIPTION" This script was \s-1DEPRECATED.\s0 .PP If you need to depend on this library, you should use `configure_requires` in Makefile.PL or Build.PL instead. .SH "WARNINGS, BUGS and FEEDBACK" .IX Header "WARNINGS, BUGS and FEEDBACK" This script has not been thoroughly tested. You should check by hand that it has done what you expected after running it. .PP If you use Module::Build::Compat to write a Makefile.PL, then you will need to re-run this script whenever you have generated a new Makefile.PL. .PP I welcome feedback about my code, including constructive criticism. Bug reports should be made using or by email. .SH "SEE ALSO" .IX Header "SEE ALSO" Devel::CheckLib .SH "AUTHOR" .IX Header "AUTHOR" David Cantrell <\fIdavid@cantrell.org.uk\fR> .SH "COPYRIGHT and LICENCE" .IX Header "COPYRIGHT and LICENCE" Copyright 2007 David Cantrell .PP This software is free-as-in-speech software, and may be used, distributed, and modified under the same conditions as perl itself. .SH "CONSPIRACY" .IX Header "CONSPIRACY" This module is also free-as-in-mason software. licenses/alt-cyrus-sasl-lib/COPYING000064400000003505152463742640013053 0ustar00/* CMU libsasl * Tim Martin * Rob Earhart * Rob Siemborski */ /* * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any other legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ doc/alt-cyrus-sasl-lib/getsasl.html000064400000124433152463742640013314 0ustar00 Get SASL — Cyrus SASL 2.1.27 documentation
    doc/alt-cyrus-sasl-lib/index.html000064400000160740152463742640012762 0ustar00 Cyrus SASL — Cyrus SASL 2.1.27 documentation

    Cyrus SASL

    Welcome to Cyrus SASL.

    What is Cyrus SASL?

    Simple Authentication and Security Layer (SASL) is a specification that describes how authentication mechanisms can be plugged into an application protocol on the wire. Cyrus SASL is an implementation of SASL that makes it easy for application developers to integrate authentication mechanisms into their application in a generic way.

    The latest stable version of Cyrus SASL is 2.1.26.

    Cyrus IMAP uses Cyrus SASL to provide authentication support to the mail server, however it is just one project using Cyrus SASL.

    Features

    Cyrus SASL provides a number of authentication plugins out of the box.

    Berkeley DB, GDBM, or NDBM (sasldb), PAM, MySQL, PostgreSQL, SQLite, LDAP, Active Directory(LDAP), DCE, Kerberos 4 and 5, proxied IMAP auth, getpwent, shadow, SIA, Courier Authdaemon, httpform, APOP and SASL mechanisms: ANONYMOUS, CRAM-MD5, DIGEST-MD5, EXTERNAL, GSSAPI, LOGIN, NTLM, OTP, PASSDSS, PLAIN, SR

    This document is an introduction to Cyrus SASL. It is not intended to be an exhaustive reference for the SASL Application Programming Interface (API), which is detailed in the SASL manual pages, and the libsasl.h header file.

    Known Bugs

    libtool doesn’t always link libraries together. In our environment, we only have static Krb5 libraries; the GSSAPI plugin should link these libraries in on platforms that support it (Solaris and Linux among them) but it does not. It also doesn’t always get the runpath of libraries correct.

    Cyrus SASL

    IMAP

    doc/alt-cyrus-sasl-lib/packager.html000064400000122021152463742640013416 0ustar00 Note for Packagers — Cyrus SASL 2.1.27 documentation

    Note for Packagers

    People considering doing binary distributions that include saslauthd should be aware that the code is covered by several slightly different (but compatible) licenses, due to how it was contributed. Details can be found within the source code.

    doc/alt-cyrus-sasl-lib/developer.html000064400000137703152463742640013643 0ustar00 Developers — Cyrus SASL 2.1.27 documentation
    doc/alt-cyrus-sasl-lib/search.html000064400000120070152463742640013110 0ustar00 Search — Cyrus SASL 2.1.27 documentation

    doc/alt-cyrus-sasl-lib/download.html000064400000146030152463742640013456 0ustar00 Download — Cyrus SASL 2.1.27 documentation
    doc/alt-cyrus-sasl-lib/operations.html000064400000166562152463742640014046 0ustar00 Operations — Cyrus SASL 2.1.27 documentation

    Operations

    doc/alt-cyrus-sasl-lib/genindex.html000064400000217316152463742640013456 0ustar00 Index — Cyrus SASL 2.1.27 documentation

    Index

    Symbols | A | C | K | L | M | N | O | P | R | S

    Symbols

    A

    C

    K

    L

    M

    N

    O

    P

    R

    S

    doc/alt-cyrus-sasl-lib/AUTHORS000064400000004312152463742640012025 0ustar00Rob Siemborski wrote and tested the conversion to the SASLv2 API. Ken Murchison worked on the OTP, NTLM, SRP and SQL plugins, as well as helping to track down bugs as they appear. He also added support for HTTP authentication. Rob Earhart wrote the build/installation procedure, wrote and tested some of the code, and provided general guidance and coding advice. Leif Johansson wrote the GSSAPI plugin, with contributions from Sam Hartman . Leandro Santi added Courier authdaemon support. Alexey Melnikov wrote the first pass of the DIGEST-MD5 plugin and continues to work on it. He also wrote a good deal of the current Windows support. Rainer Schoepf contributed the LOGIN plugin, based on Tim Martin's PLAIN plugin. Simon Loader wrote the MySQL auxprop module. Rolf Braun wrote the MacOS ports. Howard Chu put a good deal of work into OS/390 portability, correct building of static libraries, and a slew of misc. bugfixes. Tim Martin wrote, debugged, and tested most of the SASLv1 code. Larry Greenfield complained. a lot. Chris Newman wrote the initial version of the SASL API, as well as the version 2 SASL API (documented in sasl.h, saslutil.h, saslplug.h, and prop.h). Ryan Troll started the Windows port, and both Larry Greenfield and Alexey Melnikov have done more work on it. getaddrinfo.c was written by Hajimu UMEMOTO which is based on the IPv6 code written by KIKUCHI Takahiro Igor Brezac has done a good deal of work on the saslauthd LDAP module. Jeremy Rumpf implemented the credential cache, unified the different IPC methods under a common framework. Fabian Knittel wrote auth_pam plugin, based on Debian's pwcheck_pam daemon by Michael-John Turner . saslauthd was originally contributed by Lyndon Nerenberg on behalf of MessagingDirect Ltd. doc/alt-cyrus-sasl-lib/setup.html000064400000134340152463742640013010 0ustar00 Setup — Cyrus SASL 2.1.27 documentation
    doc/alt-cyrus-sasl-lib/support.html000064400000121064152463742640013363 0ustar00 Support/Community — Cyrus SASL 2.1.27 documentation

    Support/Community

    Please read our support and bug reporting guidelines in the Cyrus IMAP project.

    doc/nghttp2/README.rst000064400000140613152464121240010374 0ustar00nghttp2 - HTTP/2 C Library ========================== This is an implementation of the Hypertext Transfer Protocol version 2 in C. The framing layer of HTTP/2 is implemented as a reusable C library. On top of that, we have implemented an HTTP/2 client, server and proxy. We have also developed load test and benchmarking tools for HTTP/2. An HPACK encoder and decoder are available as a public API. Development Status ------------------ nghttp2 was originally developed based on `RFC 7540 `_ HTTP/2 and `RFC 7541 `_ HPACK - Header Compression for HTTP/2. Now we are updating our code to implement `RFC 9113 `_. The nghttp2 code base was forked from the spdylay (https://github.com/tatsuhiro-t/spdylay) project. Public Test Server ------------------ The following endpoints are available to try out our nghttp2 implementation. * https://nghttp2.org/ (TLS + ALPN and HTTP/3) This endpoint supports ``h2`` and ``http/1.1`` via ALPN and requires TLSv1.2 for HTTP/2 connection. It also supports HTTP/3. * http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct) ``h2c`` and ``http/1.1``. Requirements ------------ The following package is required to build the libnghttp2 library: * pkg-config >= 0.20 To build the documentation, you need to install: * sphinx (http://sphinx-doc.org/) If you need libnghttp2 (C library) only, then the above packages are all you need. Use ``--enable-lib-only`` to ensure that only libnghttp2 is built. This avoids potential build error related to building bundled applications. To build and run the application programs (``nghttp``, ``nghttpd``, ``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages are required: * OpenSSL >= 1.1.1; or wolfSSL >= 5.7.0; or LibreSSL >= 3.8.1; or aws-lc >= 1.19.0; or BoringSSL * libev >= 4.11 * zlib >= 1.2.3 * libc-ares >= 1.7.5 To enable ``-a`` option (getting linked assets from the downloaded resource) in ``nghttp``, the following package is required: * libxml2 >= 2.6.26 To enable systemd support in nghttpx, the following package is required: * libsystemd-dev >= 209 The HPACK tools require the following package: * jansson >= 2.5 To build sources under the examples directory, libevent is required: * libevent-openssl >= 2.0.8 To mitigate heap fragmentation in long running server programs (``nghttpd`` and ``nghttpx``), jemalloc is recommended: * jemalloc .. note:: Alpine Linux currently does not support malloc replacement due to musl limitations. See details in issue `#762 `_. For BoringSSL or aws-lc build, to enable :rfc:`8879` TLS Certificate Compression in applications, the following library is required: * libbrotli-dev >= 1.0.9 To enable mruby support for nghttpx, `mruby `_ is required. We need to build mruby with C++ ABI explicitly turned on, and probably need other mrgems, mruby is managed by git submodule under third-party/mruby directory. Currently, mruby support for nghttpx is disabled by default. To enable mruby support, use ``--with-mruby`` configure option. Note that at the time of this writing, libmruby-dev and mruby packages in Debian/Ubuntu are not usable for nghttp2, since they do not enable C++ ABI. To build mruby, the following packages are required: * ruby * bison nghttpx supports `neverbleed `_, privilege separation engine for OpenSSL. In short, it minimizes the risk of private key leakage when serious bug like Heartbleed is exploited. The neverbleed is disabled by default. To enable it, use ``--with-neverbleed`` configure option. To enable the experimental HTTP/3 support for h2load and nghttpx, the following libraries are required: * `quictls `_; or wolfSSL; or LibreSSL (does not support 0RTT); or aws-lc; or `BoringSSL `_ (commit db1a8456167249f95b854a1cd24c6b553d0f1567); or OpenSSL >= 3.5.0 * `ngtcp2 `_ >= 1.16.0 * `nghttp3 `_ >= 1.12.0 Use ``--enable-http3`` configure option to enable HTTP/3 feature for h2load and nghttpx. In order to build optional eBPF program to direct an incoming QUIC UDP datagram to a correct socket for nghttpx, the following libraries are required: * libbpf-dev >= 0.7.0 Use ``--with-libbpf`` configure option to build eBPF program. libelf-dev is needed to build libbpf. For Ubuntu 20.04, you can build libbpf from `the source code `_. nghttpx requires eBPF program for reloading its configuration and hot swapping its executable. Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8 is known to be adequate. In order to compile the C++ source code, C++20 compliant compiler is required. At least g++ >= 12 and clang++ >= 18 are known to work. .. note:: To enable mruby support in nghttpx, and use ``--with-mruby`` configure option. .. note:: Mac OS X users may need the ``--disable-threads`` configure option to disable multi-threading in nghttpd, nghttpx and h2load to prevent them from crashing. A patch is welcome to make multi threading work on Mac OS X platform. .. note:: To compile the associated applications (nghttp, nghttpd, nghttpx and h2load), you must use the ``--enable-app`` configure option and ensure that the specified requirements above are met. Normally, configure script checks required dependencies to build these applications, and enable ``--enable-app`` automatically, so you don't have to use it explicitly. But if you found that applications were not built, then using ``--enable-app`` may find that cause, such as the missing dependency. .. note:: In order to detect third party libraries, pkg-config is used (however we don't use pkg-config for some libraries (e.g., libev)). By default, pkg-config searches ``*.pc`` file in the standard locations (e.g., /usr/lib/pkgconfig). If it is necessary to use ``*.pc`` file in the custom location, specify paths to ``PKG_CONFIG_PATH`` environment variable, and pass it to configure script, like so: .. code-block:: text $ ./configure PKG_CONFIG_PATH=/path/to/pkgconfig For pkg-config managed libraries, ``*_CFLAG`` and ``*_LIBS`` environment variables are defined (e.g., ``OPENSSL_CFLAGS``, ``OPENSSL_LIBS``). Specifying non-empty string to these variables completely overrides pkg-config. In other words, if they are specified, pkg-config is not used for detection, and user is responsible to specify the correct values to these variables. For complete list of these variables, run ``./configure -h``. If you are using Ubuntu 22.04 LTS, run the following to install the required packages: .. code-block:: text sudo apt-get install g++ clang make binutils autoconf automake \ autotools-dev libtool pkg-config \ zlib1g-dev libssl-dev libxml2-dev libev-dev \ libevent-dev libjansson-dev \ libc-ares-dev libjemalloc-dev libsystemd-dev \ ruby-dev bison libelf-dev Building nghttp2 from release tar archive ----------------------------------------- The nghttp2 project regularly releases tar archives which includes nghttp2 source code, and generated build files. They can be downloaded from `Releases `_ page. Building nghttp2 from git requires autotools development packages. Building from tar archives does not require them, and thus it is much easier. The usual build step is as follows: .. code-block:: text $ tar xf nghttp2-X.Y.Z.tar.bz2 $ cd nghttp2-X.Y.Z $ ./configure $ make Building from git ----------------- Building from git is easy, but please be sure that at least autoconf 2.68 is used: .. code-block:: text $ git submodule update --init $ autoreconf -i $ automake $ autoconf $ ./configure $ make Notes for building on Windows (MSVC) ------------------------------------ The easiest way to build native Windows nghttp2 dll is use `cmake `_. The free version of `Visual C++ Build Tools `_ works fine. 1. Install cmake for windows 2. Open "Visual C++ ... Native Build Tool Command Prompt", and inside nghttp2 directly, run ``cmake``. 3. Then run ``cmake --build`` to build library. 4. nghttp2.dll, nghttp2.lib, nghttp2.exp are placed under lib directory. Note that the above steps most likely produce nghttp2 library only. No bundled applications are compiled. Notes for building on Windows (Mingw/Cygwin) -------------------------------------------- Under Mingw environment, you can only compile the library, it's ``libnghttp2-X.dll`` and ``libnghttp2.a``. If you want to compile the applications(``h2load``, ``nghttp``, ``nghttpx``, ``nghttpd``), you need to use the Cygwin environment. Under Cygwin environment, to compile the applications you need to compile and install the libev first. Secondly, you need to undefine the macro ``__STRICT_ANSI__``, if you not, the functions ``fdopen``, ``fileno`` and ``strptime`` will not available. the sample command like this: .. code-block:: text $ export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib" $ export CXXFLAGS=$CFLAGS $ ./configure $ make If you want to compile the applications under ``examples/``, you need to remove or rename the ``event.h`` from libev's installation, because it conflicts with libevent's installation. Notes for installation on Linux systems -------------------------------------------- After installing nghttp2 tool suite with ``make install`` one might experience a similar error: .. code-block:: text nghttpx: error while loading shared libraries: libnghttp2.so.14: cannot open shared object file: No such file or directory This means that the tool is unable to locate the ``libnghttp2.so`` shared library. To update the shared library cache run ``sudo ldconfig``. Building the documentation -------------------------- .. note:: Documentation is still incomplete. To build the documentation, run: .. code-block:: text $ make html The documents will be generated under ``doc/manual/html/``. The generated documents will not be installed with ``make install``. The online documentation is available at https://nghttp2.org/documentation/ Build HTTP/3 enabled h2load and nghttpx --------------------------------------- To build h2load and nghttpx with HTTP/3 feature enabled, run the configure script with ``--enable-http3``. For nghttpx to reload configurations and swapping its executable while gracefully terminating old worker processes, eBPF is required. Run the configure script with ``--enable-http3 --with-libbpf`` to build eBPF program. The QUIC keying material must be set with ``--frontend-quic-secret-file`` in order to keep the existing connections alive during reload. The detailed steps to build HTTP/3 enabled h2load and nghttpx follow. Build aws-lc: .. code-block:: text $ git clone --depth 1 -b v1.62.0 https://github.com/aws/aws-lc $ cd aws-lc $ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt $ make -j$(nproc) -C build $ cmake --install build $ cd .. Build nghttp3: .. code-block:: text $ git clone --depth 1 -b v1.12.0 https://github.com/ngtcp2/nghttp3 $ cd nghttp3 $ git submodule update --init --depth 1 $ autoreconf -i $ ./configure --prefix=$PWD/build --enable-lib-only $ make -j$(nproc) $ make install $ cd .. Build ngtcp2: .. code-block:: text $ git clone --depth 1 -b v1.17.0 https://github.com/ngtcp2/ngtcp2 $ cd ngtcp2 $ git submodule update --init --depth 1 $ autoreconf -i $ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl \ BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include" \ BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto" $ make -j$(nproc) $ make install $ cd .. If your Linux distribution does not have libbpf-dev >= 0.7.0, build from source: .. code-block:: text $ git clone --depth 1 -b v1.6.2 https://github.com/libbpf/libbpf $ cd libbpf $ PREFIX=$PWD/build make -C src install $ cd .. Build nghttp2: .. code-block:: text $ git clone https://github.com/nghttp2/nghttp2 $ cd nghttp2 $ git submodule update --init $ autoreconf -i $ ./configure --with-mruby --enable-http3 --with-libbpf \ CC=clang-19 CXX=clang++-19 \ PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \ LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64" $ make -j$(nproc) The eBPF program ``reuseport_kern.o`` should be found under bpf directory. Pass ``--quic-bpf-program-file=bpf/reuseport_kern.o`` option to nghttpx to load it. See also `HTTP/3 section in nghttpx - HTTP/2 proxy - HOW-TO `_. Unit tests ---------- Unit tests are done by simply running ``make check``. Integration tests ----------------- We have the integration tests for the nghttpx proxy server. The tests are written in the `Go programming language `_ and uses its testing framework. We depend on the following libraries: * golang.org/x/net/http2 * golang.org/x/net/websocket * https://github.com/tatsuhiro-t/go-nghttp2 Go modules will download these dependencies automatically. To run the tests, run the following command under ``integration-tests`` directory: .. code-block:: text $ make it Inside the tests, we use port 3009 to run the test subject server. Migration from v0.7.15 or earlier --------------------------------- nghttp2 v1.0.0 introduced several backward incompatible changes. In this section, we describe these changes and how to migrate to v1.0.0. ALPN protocol ID is now ``h2`` and ``h2c`` ++++++++++++++++++++++++++++++++++++++++++ Previously we announced ``h2-14`` and ``h2c-14``. v1.0.0 implements final protocol version, and we changed ALPN ID to ``h2`` and ``h2c``. The macros ``NGHTTP2_PROTO_VERSION_ID``, ``NGHTTP2_PROTO_VERSION_ID_LEN``, ``NGHTTP2_CLEARTEXT_PROTO_VERSION_ID``, and ``NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN`` have been updated to reflect this change. Basically, existing applications do not have to do anything, just recompiling is enough for this change. Use word "client magic" where we use "client connection preface" ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ We use "client connection preface" to mean first 24 bytes of client connection preface. This is technically not correct, since client connection preface is composed of 24 bytes client magic byte string followed by SETTINGS frame. For clarification, we call "client magic" for this 24 bytes byte string and updated API. * ``NGHTTP2_CLIENT_CONNECTION_PREFACE`` was replaced with ``NGHTTP2_CLIENT_MAGIC``. * ``NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN`` was replaced with ``NGHTTP2_CLIENT_MAGIC_LEN``. * ``NGHTTP2_BAD_PREFACE`` was renamed as ``NGHTTP2_BAD_CLIENT_MAGIC`` The already deprecated ``NGHTTP2_CLIENT_CONNECTION_HEADER`` and ``NGHTTP2_CLIENT_CONNECTION_HEADER_LEN`` were removed. If application uses these macros, just replace old ones with new ones. Since v1.0.0, client magic is sent by library (see next subsection), so client application may just remove these macro use. Client magic is sent by library +++++++++++++++++++++++++++++++ Previously nghttp2 library did not send client magic, which is first 24 bytes byte string of client connection preface, and client applications have to send it by themselves. Since v1.0.0, client magic is sent by library via first call of ``nghttp2_session_send()`` or ``nghttp2_session_mem_send2()``. The client applications which send client magic must remove the relevant code. Remove HTTP Alternative Services (Alt-Svc) related code +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Alt-Svc specification is not finalized yet. To make our API stable, we have decided to remove all Alt-Svc related API from nghttp2. * ``NGHTTP2_EXT_ALTSVC`` was removed. * ``nghttp2_ext_altsvc`` was removed. We have already removed the functionality of Alt-Svc in v0.7 series and they have been essentially noop. The application using these macro and struct, remove those lines. Use nghttp2_error in nghttp2_on_invalid_frame_recv_callback +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Previously ``nghttp2_on_invalid_frame_recv_cb_called`` took the ``error_code``, defined in ``nghttp2_error_code``, as parameter. But they are not detailed enough to debug. Therefore, we decided to use more detailed ``nghttp2_error`` values instead. The application using this callback should update the callback signature. If it treats ``error_code`` as HTTP/2 error code, update the code so that it is treated as ``nghttp2_error``. Receive client magic by default +++++++++++++++++++++++++++++++ Previously nghttp2 did not process client magic (24 bytes byte string). To make it deal with it, we had to use ``nghttp2_option_set_recv_client_preface()``. Since v1.0.0, nghttp2 processes client magic by default and ``nghttp2_option_set_recv_client_preface()`` was removed. Some application may want to disable this behaviour, so we added ``nghttp2_option_set_no_recv_client_magic()`` to achieve this. The application using ``nghttp2_option_set_recv_client_preface()`` with nonzero value, just remove it. The application using ``nghttp2_option_set_recv_client_preface()`` with zero value or not using it must use ``nghttp2_option_set_no_recv_client_magic()`` with nonzero value. Client, Server and Proxy programs --------------------------------- The ``src`` directory contains the HTTP/2 client, server and proxy programs. nghttp - client +++++++++++++++ ``nghttp`` is a HTTP/2 client. It can connect to the HTTP/2 server with prior knowledge, HTTP Upgrade and ALPN TLS extension. It has verbose output mode for framing information. Here is sample output from ``nghttp`` client: .. code-block:: text $ nghttp -nv https://nghttp2.org [ 0.190] Connected The negotiated protocol: h2 [ 0.212] recv SETTINGS frame (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.212] send SETTINGS frame (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.212] send SETTINGS frame ; ACK (niv=0) [ 0.212] send PRIORITY frame (dep_stream_id=0, weight=201, exclusive=0) [ 0.212] send PRIORITY frame (dep_stream_id=0, weight=101, exclusive=0) [ 0.212] send PRIORITY frame (dep_stream_id=0, weight=1, exclusive=0) [ 0.212] send PRIORITY frame (dep_stream_id=7, weight=1, exclusive=0) [ 0.212] send PRIORITY frame (dep_stream_id=3, weight=1, exclusive=0) [ 0.212] send HEADERS frame ; END_STREAM | END_HEADERS | PRIORITY (padlen=0, dep_stream_id=11, weight=16, exclusive=0) ; Open new stream :method: GET :path: / :scheme: https :authority: nghttp2.org accept: */* accept-encoding: gzip, deflate user-agent: nghttp2/1.0.1-DEV [ 0.221] recv SETTINGS frame ; ACK (niv=0) [ 0.221] recv (stream_id=13) :method: GET [ 0.221] recv (stream_id=13) :scheme: https [ 0.221] recv (stream_id=13) :path: /stylesheets/screen.css [ 0.221] recv (stream_id=13) :authority: nghttp2.org [ 0.221] recv (stream_id=13) accept-encoding: gzip, deflate [ 0.222] recv (stream_id=13) user-agent: nghttp2/1.0.1-DEV [ 0.222] recv PUSH_PROMISE frame ; END_HEADERS (padlen=0, promised_stream_id=2) [ 0.222] recv (stream_id=13) :status: 200 [ 0.222] recv (stream_id=13) date: Thu, 21 May 2015 16:38:14 GMT [ 0.222] recv (stream_id=13) content-type: text/html [ 0.222] recv (stream_id=13) last-modified: Fri, 15 May 2015 15:38:06 GMT [ 0.222] recv (stream_id=13) etag: W/"555612de-19f6" [ 0.222] recv (stream_id=13) link: ; rel=preload; as=stylesheet [ 0.222] recv (stream_id=13) content-encoding: gzip [ 0.222] recv (stream_id=13) server: nghttpx nghttp2/1.0.1-DEV [ 0.222] recv (stream_id=13) via: 1.1 nghttpx [ 0.222] recv (stream_id=13) strict-transport-security: max-age=31536000 [ 0.222] recv HEADERS frame ; END_HEADERS (padlen=0) ; First response header [ 0.222] recv DATA frame ; END_STREAM [ 0.222] recv (stream_id=2) :status: 200 [ 0.222] recv (stream_id=2) date: Thu, 21 May 2015 16:38:14 GMT [ 0.222] recv (stream_id=2) content-type: text/css [ 0.222] recv (stream_id=2) last-modified: Fri, 15 May 2015 15:38:06 GMT [ 0.222] recv (stream_id=2) etag: W/"555612de-9845" [ 0.222] recv (stream_id=2) content-encoding: gzip [ 0.222] recv (stream_id=2) server: nghttpx nghttp2/1.0.1-DEV [ 0.222] recv (stream_id=2) via: 1.1 nghttpx [ 0.222] recv (stream_id=2) strict-transport-security: max-age=31536000 [ 0.222] recv HEADERS frame ; END_HEADERS (padlen=0) ; First push response header [ 0.228] recv DATA frame ; END_STREAM [ 0.228] send GOAWAY frame (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[]) The HTTP Upgrade is performed like so: .. code-block:: text $ nghttp -nvu http://nghttp2.org [ 0.011] Connected [ 0.011] HTTP Upgrade request GET / HTTP/1.1 Host: nghttp2.org Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: AAMAAABkAAQAAP__ Accept: */* User-Agent: nghttp2/1.0.1-DEV [ 0.018] HTTP Upgrade response HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: h2c [ 0.018] HTTP Upgrade success [ 0.018] recv SETTINGS frame (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.018] send SETTINGS frame (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.018] send SETTINGS frame ; ACK (niv=0) [ 0.018] send PRIORITY frame (dep_stream_id=0, weight=201, exclusive=0) [ 0.018] send PRIORITY frame (dep_stream_id=0, weight=101, exclusive=0) [ 0.018] send PRIORITY frame (dep_stream_id=0, weight=1, exclusive=0) [ 0.018] send PRIORITY frame (dep_stream_id=7, weight=1, exclusive=0) [ 0.018] send PRIORITY frame (dep_stream_id=3, weight=1, exclusive=0) [ 0.018] send PRIORITY frame (dep_stream_id=11, weight=16, exclusive=0) [ 0.019] recv (stream_id=1) :method: GET [ 0.019] recv (stream_id=1) :scheme: http [ 0.019] recv (stream_id=1) :path: /stylesheets/screen.css [ 0.019] recv (stream_id=1) host: nghttp2.org [ 0.019] recv (stream_id=1) user-agent: nghttp2/1.0.1-DEV [ 0.019] recv PUSH_PROMISE frame ; END_HEADERS (padlen=0, promised_stream_id=2) [ 0.019] recv (stream_id=1) :status: 200 [ 0.019] recv (stream_id=1) date: Thu, 21 May 2015 16:39:16 GMT [ 0.019] recv (stream_id=1) content-type: text/html [ 0.019] recv (stream_id=1) content-length: 6646 [ 0.019] recv (stream_id=1) last-modified: Fri, 15 May 2015 15:38:06 GMT [ 0.019] recv (stream_id=1) etag: "555612de-19f6" [ 0.019] recv (stream_id=1) link: ; rel=preload; as=stylesheet [ 0.019] recv (stream_id=1) accept-ranges: bytes [ 0.019] recv (stream_id=1) server: nghttpx nghttp2/1.0.1-DEV [ 0.019] recv (stream_id=1) via: 1.1 nghttpx [ 0.019] recv HEADERS frame ; END_HEADERS (padlen=0) ; First response header [ 0.019] recv DATA frame ; END_STREAM [ 0.019] recv (stream_id=2) :status: 200 [ 0.019] recv (stream_id=2) date: Thu, 21 May 2015 16:39:16 GMT [ 0.019] recv (stream_id=2) content-type: text/css [ 0.019] recv (stream_id=2) content-length: 38981 [ 0.019] recv (stream_id=2) last-modified: Fri, 15 May 2015 15:38:06 GMT [ 0.019] recv (stream_id=2) etag: "555612de-9845" [ 0.019] recv (stream_id=2) accept-ranges: bytes [ 0.019] recv (stream_id=2) server: nghttpx nghttp2/1.0.1-DEV [ 0.019] recv (stream_id=2) via: 1.1 nghttpx [ 0.019] recv HEADERS frame ; END_HEADERS (padlen=0) ; First push response header [ 0.026] recv DATA frame [ 0.027] recv DATA frame [ 0.027] send WINDOW_UPDATE frame (window_size_increment=33343) [ 0.032] send WINDOW_UPDATE frame (window_size_increment=33707) [ 0.032] recv DATA frame ; END_STREAM [ 0.032] recv SETTINGS frame ; ACK (niv=0) [ 0.032] send GOAWAY frame (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[]) Using the ``-s`` option, ``nghttp`` prints out some timing information for requests, sorted by completion time: .. code-block:: text $ nghttp -nas https://nghttp2.org/ ***** Statistics ***** Request timing: responseEnd: the time when last byte of response was received relative to connectEnd requestStart: the time just before first byte of request was sent relative to connectEnd. If '*' is shown, this was pushed by server. process: responseEnd - requestStart code: HTTP status code size: number of bytes received as response body without inflation. URI: request URI see http://www.w3.org/TR/resource-timing/#processing-model sorted by 'complete' id responseEnd requestStart process code size request path 13 +37.19ms +280us 36.91ms 200 2K / 2 +72.65ms * +36.38ms 36.26ms 200 8K /stylesheets/screen.css 17 +77.43ms +38.67ms 38.75ms 200 3K /javascripts/octopress.js 15 +78.12ms +38.66ms 39.46ms 200 3K /javascripts/modernizr-2.0.js Using the ``-r`` option, ``nghttp`` writes more detailed timing data to the given file in HAR format. nghttpd - server ++++++++++++++++ ``nghttpd`` is a multi-threaded static web server. By default, it uses SSL/TLS connection. Use ``--no-tls`` option to disable it. ``nghttpd`` only accepts HTTP/2 connections via ALPN or direct HTTP/2 connections. No HTTP Upgrade is supported. The ``-p`` option allows users to configure server push. Just like ``nghttp``, it has a verbose output mode for framing information. Here is sample output from ``nghttpd``: .. code-block:: text $ nghttpd --no-tls -v 8080 IPv4: listen 0.0.0.0:8080 IPv6: listen :::8080 [id=1] [ 1.521] send SETTINGS frame (niv=1) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [id=1] [ 1.521] recv SETTINGS frame (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [id=1] [ 1.521] recv SETTINGS frame ; ACK (niv=0) [id=1] [ 1.521] recv PRIORITY frame (dep_stream_id=0, weight=201, exclusive=0) [id=1] [ 1.521] recv PRIORITY frame (dep_stream_id=0, weight=101, exclusive=0) [id=1] [ 1.521] recv PRIORITY frame (dep_stream_id=0, weight=1, exclusive=0) [id=1] [ 1.521] recv PRIORITY frame (dep_stream_id=7, weight=1, exclusive=0) [id=1] [ 1.521] recv PRIORITY frame (dep_stream_id=3, weight=1, exclusive=0) [id=1] [ 1.521] recv (stream_id=13) :method: GET [id=1] [ 1.521] recv (stream_id=13) :path: / [id=1] [ 1.521] recv (stream_id=13) :scheme: http [id=1] [ 1.521] recv (stream_id=13) :authority: localhost:8080 [id=1] [ 1.521] recv (stream_id=13) accept: */* [id=1] [ 1.521] recv (stream_id=13) accept-encoding: gzip, deflate [id=1] [ 1.521] recv (stream_id=13) user-agent: nghttp2/1.0.0-DEV [id=1] [ 1.521] recv HEADERS frame ; END_STREAM | END_HEADERS | PRIORITY (padlen=0, dep_stream_id=11, weight=16, exclusive=0) ; Open new stream [id=1] [ 1.521] send SETTINGS frame ; ACK (niv=0) [id=1] [ 1.521] send HEADERS frame ; END_HEADERS (padlen=0) ; First response header :status: 200 server: nghttpd nghttp2/1.0.0-DEV content-length: 10 cache-control: max-age=3600 date: Fri, 15 May 2015 14:49:04 GMT last-modified: Tue, 30 Sep 2014 12:40:52 GMT [id=1] [ 1.522] send DATA frame ; END_STREAM [id=1] [ 1.522] stream_id=13 closed [id=1] [ 1.522] recv GOAWAY frame (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[]) [id=1] [ 1.522] closed nghttpx - proxy +++++++++++++++ ``nghttpx`` is a multi-threaded reverse proxy for HTTP/3, HTTP/2, and HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server push. We reworked ``nghttpx`` command-line interface, and as a result, there are several incompatibles from 1.8.0 or earlier. This is necessary to extend its capability, and secure the further feature enhancements in the future release. Please read `Migration from nghttpx v1.8.0 or earlier `_ to know how to migrate from earlier releases. ``nghttpx`` implements `important performance-oriented features `_ in TLS, such as session IDs, session tickets (with automatic key rotation), dynamic record sizing, ALPN, forward secrecy and HTTP/2. ``nghttpx`` also offers the functionality to share ticket keys among multiple ``nghttpx`` instances via memcached. ``nghttpx`` has 2 operation modes: ================== ======================== ================ ============= Mode option Frontend Backend Note ================== ======================== ================ ============= default mode HTTP/3, HTTP/2, HTTP/1.1 HTTP/1.1, HTTP/2 Reverse proxy ``--http2-proxy`` HTTP/3, HTTP/2, HTTP/1.1 HTTP/1.1, HTTP/2 Forward proxy ================== ======================== ================ ============= The interesting mode at the moment is the default mode. It works like a reverse proxy and listens for HTTP/3, HTTP/2, and HTTP/1.1 and can be deployed as a SSL/TLS terminator for existing web server. In all modes, the frontend connections are encrypted by SSL/TLS by default. To disable encryption, use the ``no-tls`` keyword in ``--frontend`` option. If encryption is disabled, incoming HTTP/1.1 connections can be upgraded to HTTP/2 through HTTP Upgrade. On the other hard, backend connections are not encrypted by default. To encrypt backend connections, use ``tls`` keyword in ``--backend`` option. ``nghttpx`` supports a configuration file. See the ``--conf`` option and sample configuration file ``nghttpx.conf.sample``. In the default mode, ``nghttpx`` works as reverse proxy to the backend server: .. code-block:: text Client <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server [reverse proxy] With the ``--http2-proxy`` option, it works as forward proxy, and it is so called secure HTTP/2 proxy: .. code-block:: text Client <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy [secure proxy] (e.g., Squid, ATS) The ``Client`` in the above example needs to be configured to use ``nghttpx`` as secure proxy. At the time of this writing, both Chrome and Firefox support secure HTTP/2 proxy. One way to configure Chrome to use a secure proxy is to create a proxy.pac script like this: .. code-block:: javascript function FindProxyForURL(url, host) { return "HTTPS SERVERADDR:PORT"; } ``SERVERADDR`` and ``PORT`` is the hostname/address and port of the machine nghttpx is running on. Please note that Chrome requires a valid certificate for secure proxy. Then run Chrome with the following arguments: .. code-block:: text $ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn The backend HTTP/2 connections can be tunneled through an HTTP proxy. The proxy is specified using ``--backend-http-proxy-uri``. The following figure illustrates how nghttpx talks to the outside HTTP/2 proxy through an HTTP proxy: .. code-block:: text Client <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) -- --===================---> HTTP/2 Proxy (HTTP proxy tunnel) (e.g., nghttpx -s) Benchmarking tool ----------------- The ``h2load`` program is a benchmarking tool for HTTP/3, HTTP/2, and HTTP/1.1. The UI of ``h2load`` is heavily inspired by ``weighttp`` (https://github.com/lighttpd/weighttp). The typical usage is as follows: .. code-block:: text $ h2load -n100000 -c100 -m100 https://localhost:8443/ starting benchmark... spawning thread #0: 100 concurrent clients, 100000 total requests Protocol: TLSv1.2 Cipher: ECDHE-RSA-AES128-GCM-SHA256 Server Temp Key: ECDH P-256 256 bits progress: 10% done progress: 20% done progress: 30% done progress: 40% done progress: 50% done progress: 60% done progress: 70% done progress: 80% done progress: 90% done progress: 100% done finished in 771.26ms, 129658 req/s, 4.71MB/s requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx traffic: 3812300 bytes total, 1009900 bytes headers, 1000000 bytes data min max mean sd +/- sd time for request: 25.12ms 124.55ms 51.07ms 15.36ms 84.87% time for connect: 208.94ms 254.67ms 241.38ms 7.95ms 63.00% time to 1st byte: 209.11ms 254.80ms 241.51ms 7.94ms 63.00% The above example issued total 100,000 requests, using 100 concurrent clients (in other words, 100 HTTP/2 sessions), and a maximum of 100 streams per client. With the ``-t`` option, ``h2load`` will use multiple native threads to avoid saturating a single core on client side. .. warning:: **Don't use this tool against publicly available servers.** That is considered a DOS attack. Please only use it against your private servers. If the experimental HTTP/3 is enabled, h2load can send requests to HTTP/3 server. To do this, specify ``h3`` to ``--alpn-list`` option like so: .. code-block:: text $ h2load --alpn-list h3 https://127.0.0.1:4433 For nghttp2 v1.58 or earlier, use ``--npn-list`` instead of ``--alpn-list``. HPACK tools ----------- The ``src`` directory contains the HPACK tools. The ``deflatehd`` program is a command-line header compression tool. The ``inflatehd`` program is a command-line header decompression tool. Both tools read input from stdin and write output to stdout. Errors are written to stderr. They take JSON as input and output. We (mostly) use the same JSON data format described at https://github.com/http2jp/hpack-test-case. deflatehd - header compressor +++++++++++++++++++++++++++++ The ``deflatehd`` program reads JSON data or HTTP/1-style header fields from stdin and outputs compressed header block in JSON. For the JSON input, the root JSON object must include a ``cases`` key. Its value has to include the sequence of input header set. They share the same compression context and are processed in the order they appear. Each item in the sequence is a JSON object and it must include a ``headers`` key. Its value is an array of JSON objects, which includes exactly one name/value pair. Example: .. code-block:: json { "cases": [ { "headers": [ { ":method": "GET" }, { ":path": "/" } ] }, { "headers": [ { ":method": "POST" }, { ":path": "/" } ] } ] } With the ``-t`` option, the program can accept more familiar HTTP/1 style header field blocks. Each header set is delimited by an empty line: Example: .. code-block:: text :method: GET :scheme: https :path: / :method: POST user-agent: nghttp2 The output is in JSON object. It should include a ``cases`` key and its value is an array of JSON objects, which has at least the following keys: seq The index of header set in the input. input_length The sum of the length of the name/value pairs in the input. output_length The length of the compressed header block. percentage_of_original_size ``output_length`` / ``input_length`` * 100 wire The compressed header block as a hex string. headers The input header set. header_table_size The header table size adjusted before deflating the header set. Examples: .. code-block:: json { "cases": [ { "seq": 0, "input_length": 66, "output_length": 20, "percentage_of_original_size": 30.303030303030305, "wire": "01881f3468e5891afcbf83868a3d856659c62e3f", "headers": [ { ":authority": "example.org" }, { ":method": "GET" }, { ":path": "/" }, { ":scheme": "https" }, { "user-agent": "nghttp2" } ], "header_table_size": 4096 } , { "seq": 1, "input_length": 74, "output_length": 10, "percentage_of_original_size": 13.513513513513514, "wire": "88448504252dd5918485", "headers": [ { ":authority": "example.org" }, { ":method": "POST" }, { ":path": "/account" }, { ":scheme": "https" }, { "user-agent": "nghttp2" } ], "header_table_size": 4096 } ] } The output can be used as the input for ``inflatehd`` and ``deflatehd``. With the ``-d`` option, the extra ``header_table`` key is added and its associated value includes the state of dynamic header table after the corresponding header set was processed. The value includes at least the following keys: entries The entry in the header table. If ``referenced`` is ``true``, it is in the reference set. The ``size`` includes the overhead (32 bytes). The ``index`` corresponds to the index of header table. The ``name`` is the header field name and the ``value`` is the header field value. size The sum of the spaces entries occupied, this includes the entry overhead. max_size The maximum header table size. deflate_size The sum of the spaces entries occupied within ``max_deflate_size``. max_deflate_size The maximum header table size the encoder uses. This can be smaller than ``max_size``. In this case, the encoder only uses up to first ``max_deflate_size`` buffer. Since the header table size is still ``max_size``, the encoder has to keep track of entries outside the ``max_deflate_size`` but inside the ``max_size`` and make sure that they are no longer referenced. Example: .. code-block:: json { "cases": [ { "seq": 0, "input_length": 66, "output_length": 20, "percentage_of_original_size": 30.303030303030305, "wire": "01881f3468e5891afcbf83868a3d856659c62e3f", "headers": [ { ":authority": "example.org" }, { ":method": "GET" }, { ":path": "/" }, { ":scheme": "https" }, { "user-agent": "nghttp2" } ], "header_table_size": 4096, "header_table": { "entries": [ { "index": 1, "name": "user-agent", "value": "nghttp2", "referenced": true, "size": 49 }, { "index": 2, "name": ":scheme", "value": "https", "referenced": true, "size": 44 }, { "index": 3, "name": ":path", "value": "/", "referenced": true, "size": 38 }, { "index": 4, "name": ":method", "value": "GET", "referenced": true, "size": 42 }, { "index": 5, "name": ":authority", "value": "example.org", "referenced": true, "size": 53 } ], "size": 226, "max_size": 4096, "deflate_size": 226, "max_deflate_size": 4096 } } , { "seq": 1, "input_length": 74, "output_length": 10, "percentage_of_original_size": 13.513513513513514, "wire": "88448504252dd5918485", "headers": [ { ":authority": "example.org" }, { ":method": "POST" }, { ":path": "/account" }, { ":scheme": "https" }, { "user-agent": "nghttp2" } ], "header_table_size": 4096, "header_table": { "entries": [ { "index": 1, "name": ":method", "value": "POST", "referenced": true, "size": 43 }, { "index": 2, "name": "user-agent", "value": "nghttp2", "referenced": true, "size": 49 }, { "index": 3, "name": ":scheme", "value": "https", "referenced": true, "size": 44 }, { "index": 4, "name": ":path", "value": "/", "referenced": false, "size": 38 }, { "index": 5, "name": ":method", "value": "GET", "referenced": false, "size": 42 }, { "index": 6, "name": ":authority", "value": "example.org", "referenced": true, "size": 53 } ], "size": 269, "max_size": 4096, "deflate_size": 269, "max_deflate_size": 4096 } } ] } inflatehd - header decompressor +++++++++++++++++++++++++++++++ The ``inflatehd`` program reads JSON data from stdin and outputs decompressed name/value pairs in JSON. The root JSON object must include the ``cases`` key. Its value has to include the sequence of compressed header blocks. They share the same compression context and are processed in the order they appear. Each item in the sequence is a JSON object and it must have at least a ``wire`` key. Its value is a compressed header block as a hex string. Example: .. code-block:: json { "cases": [ { "wire": "8285" }, { "wire": "8583" } ] } The output is a JSON object. It should include a ``cases`` key and its value is an array of JSON objects, which has at least following keys: seq The index of the header set in the input. headers A JSON array that includes decompressed name/value pairs. wire The compressed header block as a hex string. header_table_size The header table size adjusted before inflating compressed header block. Example: .. code-block:: json { "cases": [ { "seq": 0, "wire": "01881f3468e5891afcbf83868a3d856659c62e3f", "headers": [ { ":authority": "example.org" }, { ":method": "GET" }, { ":path": "/" }, { ":scheme": "https" }, { "user-agent": "nghttp2" } ], "header_table_size": 4096 } , { "seq": 1, "wire": "88448504252dd5918485", "headers": [ { ":method": "POST" }, { ":path": "/account" }, { "user-agent": "nghttp2" }, { ":scheme": "https" }, { ":authority": "example.org" } ], "header_table_size": 4096 } ] } The output can be used as the input for ``deflatehd`` and ``inflatehd``. With the ``-d`` option, the extra ``header_table`` key is added and its associated value includes the state of the dynamic header table after the corresponding header set was processed. The format is the same as ``deflatehd``. Contribution ------------ [This text was composed based on 1.2. License section of curl/libcurl project.] When contributing with code, you agree to put your changes and new code under the same license nghttp2 is already using unless stated and agreed otherwise. When changing existing source code, do not alter the copyright of the original file(s). The copyright will still be owned by the original creator(s) or those who have been assigned copyright by the original author(s). By submitting a patch to the nghttp2 project, you (or your employer, as the case may be) agree to assign the copyright of your submission to us. .. the above really needs to be reworded to pass legal muster. We will credit you for your changes as far as possible, to give credit but also to keep a trace back to who made what changes. Please always provide us with your full real name when contributing! See `Contribution Guidelines `_ for more details. Versioning ---------- In general, we follow `Semantic Versioning `_. We may release PATCH releases between the regular releases, mainly for severe security bug fixes. We have no plan to break API compatibility changes involving soname bump, so MAJOR version will stay 1 for the foreseeable future. License ------- The MIT License man/man1/nghttpx.1000064400000261235152464121240007743 0ustar00.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "NGHTTPX" "1" "Oct 25, 2025" "1.68.0" "nghttp2" .SH NAME nghttpx \- HTTP/2 proxy .SH SYNOPSIS .sp \fBnghttpx\fP [OPTIONS]... [ ] .SH DESCRIPTION .sp A reverse proxy for HTTP/3, HTTP/2, and HTTP/1. .INDENT 0.0 .TP .B Set path to server\(aqs private key. Required unless \(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option. .UNINDENT .INDENT 0.0 .TP .B Set path to server\(aqs certificate. Required unless \(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option. .UNINDENT .SH OPTIONS .sp The options are categorized into several groups. .SS Connections .INDENT 0.0 .TP .B \-b, \-\-backend=(,|unix:)[;[[:...]][[;]...] Set backend host and port. The multiple backend addresses are accepted by repeating this option. UNIX domain socket can be specified by prefixing path name with \(dqunix:\(dq (e.g., unix:/var/run/backend.sock). .sp Optionally, if s are given, the backend address is only used if request matches the pattern. The pattern matching is closely designed to ServeMux in net/http package of Go programming language. consists of path, host + path or just host. The path must start with \(dq\fI/\fP\(dq. If it ends with \(dq\fI/\fP\(dq, it matches all request path in its subtree. To deal with the request to the directory without trailing slash, the path which ends with \(dq\fI/\fP\(dq also matches the request path which only lacks trailing \(aq\fI/\fP\(aq (e.g., path \(dq\fI/foo/\fP\(dq matches request path \(dq\fI/foo\fP\(dq). If it does not end with \(dq\fI/\fP\(dq, it performs exact match against the request path. If host is given, it performs a match against the request host. For a request received on the frontend listener with \(dqsni\-fwd\(dq parameter enabled, SNI host is used instead of a request host. If host alone is given, \(dq\fI/\fP\(dq is appended to it, so that it matches all request paths under the host (e.g., specifying \(dqnghttp2.org\(dq equals to \(dqnghttp2.org/\(dq). CONNECT method is treated specially. It does not have path, and we don\(aqt allow empty path. To workaround this, we assume that CONNECT method has \(dq\fI/\fP\(dq as path. .sp Patterns with host take precedence over patterns with just path. Then, longer patterns take precedence over shorter ones. .sp Host can include \(dq*\(dq in the left most position to indicate wildcard match (only suffix match is done). The \(dq*\(dq must match at least one character. For example, host pattern \(dq*.nghttp2.org\(dq matches against \(dqwww.nghttp2.org\(dq and \(dqgit.ngttp2.org\(dq, but does not match against \(dqnghttp2.org\(dq. The exact hosts match takes precedence over the wildcard hosts match. .sp If path part ends with \(dq*\(dq, it is treated as wildcard path. The wildcard path behaves differently from the normal path. For normal path, match is made around the boundary of path component separator,\(dq\fI/\fP\(dq. On the other hand, the wildcard path does not take into account the path component separator. All paths which include the wildcard path without last \(dq*\(dq as prefix, and are strictly longer than wildcard path without last \(dq*\(dq are matched. \(dq*\(dq must match at least one character. For example, the pattern \(dq\fI/foo*\fP\(dq matches \(dq\fI/foo/\fP\(dq and \(dq\fI/foobar\fP\(dq. But it does not match \(dq\fI/foo\fP\(dq, or \(dq\fI/fo\fP\(dq. .sp If is omitted or empty string, \(dq\fI/\fP\(dq is used as pattern, which matches all request paths (catch\-all pattern). The catch\-all backend must be given. .sp When doing a match, nghttpx made some normalization to pattern, request host and path. For host part, they are converted to lower case. For path part, percent\-encoded unreserved characters defined in RFC 3986 are decoded, and any dot\-segments (\(dq..\(dq and \(dq.\(dq) are resolved and removed. .sp For example, \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org/httpbin/\(aq matches the request host \(dqnghttp2.org\(dq and the request path \(dq\fI/httpbin/get\fP\(dq, but does not match the request host \(dqnghttp2.org\(dq and the request path \(dq\fI/index.html\fP\(dq. .sp The multiple s can be specified, delimiting them by \(dq:\(dq. Specifying \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org:www.nghttp2.org\(aq has the same effect to specify \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org\(aq and \fI\%\-b\fP\(aq127.0.0.1,8080;www.nghttp2.org\(aq. .sp The backend addresses sharing same are grouped together forming load balancing group. .sp Several parameters are accepted after . The parameters are delimited by \(dq;\(dq. The available parameters are: \(dqproto=\(dq, \(dqtls\(dq, \(dqsni=\(dq, \(dqfall=\(dq, \(dqrise=\(dq, \(dqaffinity=\(dq, \(dqdns\(dq, \(dqredirect\-if\-not\-tls\(dq, \(dqupgrade\-scheme\(dq, \(dqmruby=\(dq, \(dqread\-timeout=\(dq, \(dqwrite\-timeout=\(dq, \(dqgroup=\(dq, \(dqgroup\-weight=\(dq, \(dqweight=\(dq, and \(dqdnf\(dq. The parameter consists of keyword, and optionally followed by \(dq=\(dq and value. For example, the parameter \(dqproto=h2\(dq consists of the keyword \(dqproto\(dq and value \(dqh2\(dq. The parameter \(dqtls\(dq consists of the keyword \(dqtls\(dq without value. Each parameter is described as follows. .sp The backend application protocol can be specified using optional \(dqproto\(dq parameter, and in the form of \(dqproto=\(dq. should be one of the following list without quotes: \(dqh2\(dq, \(dqhttp/1.1\(dq. The default value of is \(dqhttp/1.1\(dq. Note that usually \(dqh2\(dq refers to HTTP/2 over TLS. But in this option, it may mean HTTP/2 over cleartext TCP unless \(dqtls\(dq keyword is used (see below). .sp TLS can be enabled by specifying optional \(dqtls\(dq parameter. TLS is not enabled by default. .sp With \(dqsni=\(dq parameter, it can override the TLS SNI field value with given . This will default to the backend name .sp The feature to detect whether backend is online or offline can be enabled using optional \(dqfall\(dq and \(dqrise\(dq parameters. Using \(dqfall=\(dq parameter, if nghttpx cannot connect to a this backend times in a row, this backend is assumed to be offline, and it is excluded from load balancing. If is 0, this backend never be excluded from load balancing whatever times nghttpx cannot connect to it, and this is the default. There is also \(dqrise=\(dq parameter. After backend was excluded from load balancing group, nghttpx periodically attempts to make a connection to the failed backend, and if the connection is made successfully times in a row, the backend is assumed to be online, and it is now eligible for load balancing target. If is 0, a backend is permanently offline, once it goes in that state, and this is the default behaviour. .sp The session affinity is enabled using \(dqaffinity=\(dq parameter. If \(dqip\(dq is given in , client IP based session affinity is enabled. If \(dqcookie\(dq is given in , cookie based session affinity is enabled. If \(dqnone\(dq is given in , session affinity is disabled, and this is the default. The session affinity is enabled per . If at least one backend has \(dqaffinity\(dq parameter, and its is not \(dqnone\(dq, session affinity is enabled for all backend servers sharing the same . It is advised to set \(dqaffinity\(dq parameter to all backend explicitly if session affinity is desired. The session affinity may break if one of the backend gets unreachable, or backend settings are reloaded or replaced by API. .sp If \(dqaffinity=cookie\(dq is used, the additional configuration is required. \(dqaffinity\-cookie\-name=\(dq must be used to specify a name of cookie to use. Optionally, \(dqaffinity\-cookie\-path=\(dq can be used to specify a path which cookie is applied. The optional \(dqaffinity\-cookie\-secure=\(dq controls the Secure attribute of a cookie. The default value is \(dqauto\(dq, and the Secure attribute is determined by a request scheme. If a request scheme is \(dqhttps\(dq, then Secure attribute is set. Otherwise, it is not set. If is \(dqyes\(dq, the Secure attribute is always set. If is \(dqno\(dq, the Secure attribute is always omitted. \(dqaffinity\-cookie\-stickiness=\(dq controls stickiness of this affinity. If is \(dqloose\(dq, removing or adding a backend server might break the affinity and the request might be forwarded to a different backend server. If is \(dqstrict\(dq, removing the designated backend server breaks affinity, but adding new backend server does not cause breakage. If the designated backend server becomes unavailable, new backend server is chosen as if the request does not have an affinity cookie. defaults to \(dqloose\(dq. .sp By default, name resolution of backend host name is done at start up, or reloading configuration. If \(dqdns\(dq parameter is given, name resolution takes place dynamically. This is useful if backend address changes frequently. If \(dqdns\(dq is given, name resolution of backend host name at start up, or reloading configuration is skipped. .sp If \(dqredirect\-if\-not\-tls\(dq parameter is used, the matched backend requires that frontend connection is TLS encrypted. If it isn\(aqt, nghttpx responds to the request with 308 status code, and https URI the client should use instead is included in Location header field. The port number in redirect URI is 443 by default, and can be changed using \fI\%\-\-redirect\-https\-port\fP option. If at least one backend has \(dqredirect\-if\-not\-tls\(dq parameter, this feature is enabled for all backend servers sharing the same . It is advised to set \(dqredirect\-if\-no\-tls\(dq parameter to all backends explicitly if this feature is desired. .sp If \(dqupgrade\-scheme\(dq parameter is used along with \(dqtls\(dq parameter, HTTP/2 :scheme pseudo header field is changed to \(dqhttps\(dq from \(dqhttp\(dq when forwarding a request to this particular backend. This is a workaround for a backend server which requires \(dqhttps\(dq :scheme pseudo header field on TLS encrypted connection. .sp \(dqmruby=\(dq parameter specifies a path to mruby script file which is invoked when this pattern is matched. All backends which share the same pattern must have the same mruby path. .sp \(dqread\-timeout=\(dq and \(dqwrite\-timeout=\(dq parameters specify the read and write timeout of the backend connection when this pattern is matched. All backends which share the same pattern must have the same timeouts. If these timeouts are entirely omitted for a pattern, \fI\%\-\-backend\-read\-timeout\fP and \fI\%\-\-backend\-write\-timeout\fP are used. .sp \(dqgroup=\(dq parameter specifies the name of group this backend address belongs to. By default, it belongs to the unnamed default group. The name of group is unique per pattern. \(dqgroup\-weight=\(dq parameter specifies the weight of the group. The higher weight gets more frequently selected by the load balancing algorithm. must be [1, 256] inclusive. The weight 8 has 4 times more weight than 2. must be the same for all addresses which share the same . If \(dqgroup\-weight\(dq is omitted in an address, but the other address which belongs to the same group specifies \(dqgroup\-weight\(dq, its weight is used. If no \(dqgroup\-weight\(dq is specified for all addresses, the weight of a group becomes 1. \(dqgroup\(dq and \(dqgroup\-weight\(dq are ignored if session affinity is enabled. .sp \(dqweight=\(dq parameter specifies the weight of the backend address inside a group which this address belongs to. The higher weight gets more frequently selected by the load balancing algorithm. must be [1, 256] inclusive. The weight 8 has 4 times more weight than weight 2. If this parameter is omitted, weight becomes 1. \(dqweight\(dq is ignored if session affinity is enabled. .sp If \(dqdnf\(dq parameter is specified, an incoming request is not forwarded to a backend and just consumed along with the request body (actually a backend server never be contacted). It is expected that the HTTP response is generated by mruby script (see \(dqmruby=\(dq parameter above). \(dqdnf\(dq is an abbreviation of \(dqdo not forward\(dq. .sp Since \(dq;\(dq and \(dq:\(dq are used as delimiter, must not contain these characters. In order to include \(dq:\(dq in , one has to specify \(dq%3A\(dq (which is percent\-encoded from of \(dq:\(dq) instead. Since \(dq;\(dq has special meaning in shell, the option value must be quoted. .sp Default: \fB127.0.0.1,80\fP .UNINDENT .INDENT 0.0 .TP .B \-f, \-\-frontend=(,|unix:)[[;]...] Set frontend host and port. If is \(aq*\(aq, it assumes all addresses including both IPv4 and IPv6. UNIX domain socket can be specified by prefixing path name with \(dqunix:\(dq (e.g., unix:/var/run/nghttpx.sock). This option can be used multiple times to listen to multiple addresses. .sp This option can take 0 or more parameters, which are described below. Note that \(dqapi\(dq and \(dqhealthmon\(dq parameters are mutually exclusive. .sp Optionally, TLS can be disabled by specifying \(dqno\-tls\(dq parameter. TLS is enabled by default. .sp If \(dqsni\-fwd\(dq parameter is used, when performing a match to select a backend server, SNI host name received from the client is used instead of the request host. See \fI\%\-\-backend\fP option about the pattern match. .sp To make this frontend as API endpoint, specify \(dqapi\(dq parameter. This is disabled by default. It is important to limit the access to the API frontend. Otherwise, someone may change the backend server, and break your services, or expose confidential information to the outside the world. .sp To make this frontend as health monitor endpoint, specify \(dqhealthmon\(dq parameter. This is disabled by default. Any requests which come through this address are replied with 200 HTTP status, without no body. .sp To accept PROXY protocol version 1 and 2 on frontend connection, specify \(dqproxyproto\(dq parameter. This is disabled by default. .sp To receive HTTP/3 (QUIC) traffic, specify \(dqquic\(dq parameter. It makes nghttpx listen on UDP port rather than TCP port. UNIX domain socket, \(dqapi\(dq, and \(dqhealthmon\(dq parameters cannot be used with \(dqquic\(dq parameter. .sp Default: \fB*,3000\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backlog= Set listen backlog size. .sp Default: \fB65536\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-address\-family=(auto|IPv4|IPv6) Specify address family of backend connections. If \(dqauto\(dq is given, both IPv4 and IPv6 are considered. If \(dqIPv4\(dq is given, only IPv4 address is considered. If \(dqIPv6\(dq is given, only IPv6 address is considered. .sp Default: \fBauto\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http\-proxy\-uri= Specify proxy URI in the form \X'tty: link http:/'\fI\%http:/\fP\X'tty: link'/[:@]:. If a proxy requires authentication, specify and . Note that they must be properly percent\-encoded. This proxy is used when the backend connection is HTTP/2. First, make a CONNECT request to the proxy and it connects to the backend on behalf of nghttpx. This forms tunnel. After that, nghttpx performs SSL/TLS handshake with the downstream through the tunnel. The timeouts when connecting and making CONNECT request can be specified by \fI\%\-\-backend\-read\-timeout\fP and \fI\%\-\-backend\-write\-timeout\fP options. .UNINDENT .SS Performance .INDENT 0.0 .TP .B \-n, \-\-workers= Set the number of worker threads. .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-\-single\-thread Run everything in one thread inside the worker process. This feature is provided for better debugging experience, or for the platforms which lack thread support. If threading is disabled, this option is always enabled. .UNINDENT .INDENT 0.0 .TP .B \-\-read\-rate= Set maximum average read rate on frontend connection. Setting 0 to this option means read rate is unlimited. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-read\-burst= Set maximum read burst size on frontend connection. Setting 0 to this option means read burst size is unlimited. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-write\-rate= Set maximum average write rate on frontend connection. Setting 0 to this option means write rate is unlimited. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-write\-burst= Set maximum write burst size on frontend connection. Setting 0 to this option means write burst size is unlimited. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-worker\-read\-rate= Set maximum average read rate on frontend connection per worker. Setting 0 to this option means read rate is unlimited. Not implemented yet. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-worker\-read\-burst= Set maximum read burst size on frontend connection per worker. Setting 0 to this option means read burst size is unlimited. Not implemented yet. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-worker\-write\-rate= Set maximum average write rate on frontend connection per worker. Setting 0 to this option means write rate is unlimited. Not implemented yet. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-worker\-write\-burst= Set maximum write burst size on frontend connection per worker. Setting 0 to this option means write burst size is unlimited. Not implemented yet. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-worker\-frontend\-connections= Set maximum number of simultaneous connections frontend accepts. Setting 0 means unlimited. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-connections\-per\-host= Set maximum number of backend concurrent connections (and/or streams in case of HTTP/2) per origin host. This option is meaningful when \fI\%\-\-http2\-proxy\fP option is used. The origin host is determined by authority portion of request URI (or :authority header field for HTTP/2). To limit the number of connections per frontend for default mode, use \fI\%\-\-backend\-connections\-per\-frontend\fP\&. .sp Default: \fB8\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-connections\-per\-frontend= Set maximum number of backend concurrent connections (and/or streams in case of HTTP/2) per frontend. This option is only used for default mode. 0 means unlimited. To limit the number of connections per host with \fI\%\-\-http2\-proxy\fP option, use \fI\%\-\-backend\-connections\-per\-host\fP\&. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-rlimit\-nofile= Set maximum number of open files (RLIMIT_NOFILE) to . If 0 is given, nghttpx does not set the limit. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-rlimit\-memlock= Set maximum number of bytes of memory that may be locked into RAM. If 0 is given, nghttpx does not set the limit. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-request\-buffer= Set buffer size used to store backend request. .sp Default: \fB16K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-response\-buffer= Set buffer size used to store backend response. .sp Default: \fB128K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-fastopen= Enables \(dqTCP Fast Open\(dq for the listening socket and limits the maximum length for the queue of connections that have not yet completed the three\-way handshake. If value is 0 then fast open is disabled. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-kqueue Don\(aqt use kqueue. This option is only applicable for the platforms which have kqueue. For other platforms, this option will be simply ignored. .UNINDENT .SS Timeout .INDENT 0.0 .TP .B \-\-frontend\-http2\-idle\-timeout= Specify idle timeout for HTTP/2 frontend connection. If no active streams exist for this duration, connection is closed. .sp Default: \fB3m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http3\-idle\-timeout= Specify idle timeout for HTTP/3 frontend connection. If no active streams exist for this duration, connection is closed. .sp Default: \fB3m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-write\-timeout= Specify write timeout for all frontend connections. .sp Default: \fB30s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-keep\-alive\-timeout= Specify keep\-alive timeout for frontend HTTP/1 connection. .sp Default: \fB1m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-header\-timeout= Specify duration that the server waits for an HTTP request header fields to be received completely. On timeout, HTTP/1 and HTTP/2 connections are closed. For HTTP/3, the stream is shutdown, and the connection itself is left intact. .sp Default: \fB1m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-stream\-read\-timeout= Specify read timeout for HTTP/2 streams. 0 means no timeout. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-stream\-write\-timeout= Specify write timeout for HTTP/2 streams. 0 means no timeout. .sp Default: \fB1m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-read\-timeout= Specify read timeout for backend connection. .sp Default: \fB1m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-write\-timeout= Specify write timeout for backend connection. .sp Default: \fB30s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-connect\-timeout= Specify timeout before establishing TCP connection to backend. .sp Default: \fB30s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-keep\-alive\-timeout= Specify keep\-alive timeout for backend HTTP/1 connection. .sp Default: \fB2s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-listener\-disable\-timeout= After accepting connection failed, connection listener is disabled for a given amount of time. Specifying 0 disables this feature. .sp Default: \fB30s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-setting\-timeout= Specify timeout before SETTINGS ACK is received from client. .sp Default: \fB10s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http2\-settings\-timeout= Specify timeout before SETTINGS ACK is received from backend server. .sp Default: \fB10s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-max\-backoff= Specify maximum backoff interval. This is used when doing health check against offline backend (see \(dqfail\(dq parameter in \fI\%\-\-backend\fP option). It is also used to limit the maximum interval to temporarily disable backend when nghttpx failed to connect to it. These intervals are calculated using exponential backoff, and consecutive failed attempts increase the interval. This option caps its maximum value. .sp Default: \fB2m\fP .UNINDENT .SS SSL/TLS .INDENT 0.0 .TP .B \-\-ciphers= Set allowed cipher list for frontend connection. The format of the string is described in OpenSSL ciphers(1). This option sets cipher suites for TLSv1.2. Use \fI\%\-\-tls13\-ciphers\fP for TLSv1.3. .sp Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:DHE\-RSA\-AES128\-GCM\-SHA256:DHE\-RSA\-AES256\-GCM\-SHA384\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls13\-ciphers= Set allowed cipher list for frontend connection. The format of the string is described in OpenSSL ciphers(1). This option sets cipher suites for TLSv1.3. Use \fI\%\-\-ciphers\fP for TLSv1.2. .sp Default: \fBTLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256\fP .UNINDENT .INDENT 0.0 .TP .B \-\-client\-ciphers= Set allowed cipher list for backend connection. The format of the string is described in OpenSSL ciphers(1). This option sets cipher suites for TLSv1.2. Use \fI\%\-\-tls13\-client\-ciphers\fP for TLSv1.3. .sp Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:DHE\-RSA\-AES128\-GCM\-SHA256:DHE\-RSA\-AES256\-GCM\-SHA384\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls13\-client\-ciphers= Set allowed cipher list for backend connection. The format of the string is described in OpenSSL ciphers(1). This option sets cipher suites for TLSv1.3. Use \fI\%\-\-client\-ciphers\fP for TLSv1.2. .sp Default: \fBTLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256\fP .UNINDENT .INDENT 0.0 .TP .B \-\-groups= Set the supported group list for frontend connections. is a colon separated list of group NID or names in the preference order. The supported curves depend on the linked OpenSSL library. This function requires OpenSSL >= 1.0.2. .sp Default: \fBX25519:P\-256:P\-384:P\-521\fP .UNINDENT .INDENT 0.0 .TP .B \-k, \-\-insecure Don\(aqt verify backend server\(aqs certificate if TLS is enabled for backend connections. .UNINDENT .INDENT 0.0 .TP .B \-\-cacert= Set path to trusted CA certificate file. It is used in backend TLS connections to verify peer\(aqs certificate. The file must be in PEM format. It can contain multiple certificates. If the linked OpenSSL is configured to load system wide certificates, they are loaded at startup regardless of this option. .UNINDENT .INDENT 0.0 .TP .B \-\-private\-key\-passwd\-file= Path to file that contains password for the server\(aqs private key. If none is given and the private key is password protected it\(aqll be requested interactively. .UNINDENT .INDENT 0.0 .TP .B \-\-subcert=:[[;]...] Specify additional certificate and private key file. nghttpx will choose certificates based on the hostname indicated by client using TLS SNI extension. If nghttpx is built with OpenSSL >= 1.0.2, the signature algorithms (e.g., ECDSA+SHA256) presented by client are also taken into consideration. This allows nghttpx to send ML\-DSA or ECDSA certificate to modern clients, while sending RSA based certificate to older clients. This option can be used multiple times. .sp Additional parameter can be specified in . The available is \(dqsct\-dir=\(dq. .sp \(dqsct\-dir=\(dq specifies the path to directory which contains *.sct files for TLS signed_certificate_timestamp extension (RFC 6962). This feature requires OpenSSL >= 1.0.2. See also \fI\%\-\-tls\-sct\-dir\fP option. .UNINDENT .INDENT 0.0 .TP .B \-\-dh\-param\-file= Path to file that contains DH parameters in PEM format. Without this option, DHE cipher suites are not available. .UNINDENT .INDENT 0.0 .TP .B \-\-alpn\-list= Comma delimited list of ALPN protocol identifier sorted in the order of preference. That means most desirable protocol comes first. The parameter must be delimited by a single comma only and any white spaces are treated as a part of protocol string. .sp Default: \fBh2,http/1.1\fP .UNINDENT .INDENT 0.0 .TP .B \-\-verify\-client Require and verify client certificate. .UNINDENT .INDENT 0.0 .TP .B \-\-verify\-client\-cacert= Path to file that contains CA certificates to verify client certificate. The file must be in PEM format. It can contain multiple certificates. .UNINDENT .INDENT 0.0 .TP .B \-\-verify\-client\-tolerate\-expired Accept expired client certificate. Operator should handle the expired client certificate by some means (e.g., mruby script). Otherwise, this option might cause a security risk. .UNINDENT .INDENT 0.0 .TP .B \-\-client\-private\-key\-file= Path to file that contains client private key used in backend client authentication. .UNINDENT .INDENT 0.0 .TP .B \-\-client\-cert\-file= Path to file that contains client certificate used in backend client authentication. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-min\-proto\-version= Specify minimum SSL/TLS protocol. The name matching is done in case\-insensitive manner. The versions between \fI\%\-\-tls\-min\-proto\-version\fP and \fI\%\-\-tls\-max\-proto\-version\fP are enabled. If the protocol list advertised by client does not overlap this range, you will receive the error message \(dqunknown protocol\(dq. The available versions are: TLSv1.3 and TLSv1.2 .sp Default: \fBTLSv1.2\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-max\-proto\-version= Specify maximum SSL/TLS protocol. The name matching is done in case\-insensitive manner. The versions between \fI\%\-\-tls\-min\-proto\-version\fP and \fI\%\-\-tls\-max\-proto\-version\fP are enabled. If the protocol list advertised by client does not overlap this range, you will receive the error message \(dqunknown protocol\(dq. The available versions are: TLSv1.3 and TLSv1.2 .sp Default: \fBTLSv1.3\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-file= Path to file that contains random data to construct TLS session ticket parameters. If aes\-128\-cbc is given in \fI\%\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly 48 bytes. If aes\-256\-cbc is given in \fI\%\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly 80 bytes. This options can be used repeatedly to specify multiple ticket parameters. If several files are given, only the first key is used to encrypt TLS session tickets. Other keys are accepted but server will issue new session ticket with first key. This allows session key rotation. Please note that key rotation does not occur automatically. User should rearrange files or change options values and restart nghttpx gracefully. If opening or reading given file fails, all loaded keys are discarded and it is treated as if none of this option is given. If this option is not given or an error occurred while opening or reading a file, key is generated every 1 hour internally and they are valid for 12 hours. This is recommended if ticket key sharing between nghttpx instances is not required. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached=,[;tls] Specify address of memcached server to get TLS ticket keys for session resumption. This enables shared TLS ticket key between multiple nghttpx instances. nghttpx does not set TLS ticket key to memcached. The external ticket key generator is required. nghttpx just gets TLS ticket keys from memcached, and use them, possibly replacing current set of keys. It is up to extern TLS ticket key generator to rotate keys frequently. See \(dqTLS SESSION TICKET RESUMPTION\(dq section in manual page to know the data format in memcached entry. Optionally, memcached connection can be encrypted with TLS by specifying \(dqtls\(dq parameter. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached\-address\-family=(auto|IPv4|IPv6) Specify address family of memcached connections to get TLS ticket keys. If \(dqauto\(dq is given, both IPv4 and IPv6 are considered. If \(dqIPv4\(dq is given, only IPv4 address is considered. If \(dqIPv6\(dq is given, only IPv6 address is considered. .sp Default: \fBauto\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached\-interval= Set interval to get TLS ticket keys from memcached. .sp Default: \fB10m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached\-max\-retry= Set maximum number of consecutive retries before abandoning TLS ticket key retrieval. If this number is reached, the attempt is considered as failure, and \(dqfailure\(dq count is incremented by 1, which contributed to the value controlled \fI\%\-\-tls\-ticket\-key\-memcached\-max\-fail\fP option. .sp Default: \fB3\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached\-max\-fail= Set maximum number of consecutive failure before disabling TLS ticket until next scheduled key retrieval. .sp Default: \fB2\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-cipher= Specify cipher to encrypt TLS session ticket. Specify either aes\-128\-cbc or aes\-256\-cbc. By default, aes\-128\-cbc is used. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached\-cert\-file= Path to client certificate for memcached connections to get TLS ticket keys. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ticket\-key\-memcached\-private\-key\-file= Path to client private key for memcached connections to get TLS ticket keys. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-dyn\-rec\-warmup\-threshold= Specify the threshold size for TLS dynamic record size behaviour. During a TLS session, after the threshold number of bytes have been written, the TLS record size will be increased to the maximum allowed (16K). The max record size will continue to be used on the active TLS session. After \fI\%\-\-tls\-dyn\-rec\-idle\-timeout\fP has elapsed, the record size is reduced to 1300 bytes. Specify 0 to always use the maximum record size, regardless of idle period. This behaviour applies to all TLS based frontends, and TLS HTTP/2 backends. .sp Default: \fB1M\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-dyn\-rec\-idle\-timeout= Specify TLS dynamic record size behaviour timeout. See \fI\%\-\-tls\-dyn\-rec\-warmup\-threshold\fP for more information. This behaviour applies to all TLS based frontends, and TLS HTTP/2 backends. .sp Default: \fB1s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-http2\-cipher\-block\-list Allow block listed cipher suite on frontend HTTP/2 connection. See \X'tty: link https://tools.ietf.org/html/rfc7540#appendix-A'\fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP\X'tty: link' for the complete HTTP/2 cipher suites block list. .UNINDENT .INDENT 0.0 .TP .B \-\-client\-no\-http2\-cipher\-block\-list Allow block listed cipher suite on backend HTTP/2 connection. See \X'tty: link https://tools.ietf.org/html/rfc7540#appendix-A'\fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP\X'tty: link' for the complete HTTP/2 cipher suites block list. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-sct\-dir= Specifies the directory where *.sct files exist. All *.sct files in are read, and sent as extension_data of TLS signed_certificate_timestamp (RFC 6962) to client. These *.sct files are for the certificate specified in positional command\-line argument , or certificate option in configuration file. For additional certificates, use \fI\%\-\-subcert\fP option. This option requires OpenSSL >= 1.0.2. .UNINDENT .INDENT 0.0 .TP .B \-\-psk\-secrets= Read list of PSK identity and secrets from . This is used for frontend connection. The each line of input file is formatted as :, where is PSK identity, and is secret in hex. An empty line, and line which starts with \(aq#\(aq are skipped. The default enabled cipher list might not contain any PSK cipher suite. In that case, desired PSK cipher suites must be enabled using \fI\%\-\-ciphers\fP option. The desired PSK cipher suite may be block listed by HTTP/2. To use those cipher suites with HTTP/2, consider to use \fI\%\-\-no\-http2\-cipher\-block\-list\fP option. But be aware its implications. .UNINDENT .INDENT 0.0 .TP .B \-\-client\-psk\-secrets= Read PSK identity and secrets from . This is used for backend connection. The each line of input file is formatted as :, where is PSK identity, and is secret in hex. An empty line, and line which starts with \(aq#\(aq are skipped. The first identity and secret pair encountered is used. The default enabled cipher list might not contain any PSK cipher suite. In that case, desired PSK cipher suites must be enabled using \fI\%\-\-client\-ciphers\fP option. The desired PSK cipher suite may be block listed by HTTP/2. To use those cipher suites with HTTP/2, consider to use \fI\%\-\-client\-no\-http2\-cipher\-block\-list\fP option. But be aware its implications. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-no\-postpone\-early\-data By default, except for QUIC connections, nghttpx postpones forwarding HTTP requests sent in early data, including those sent in partially in it, until TLS handshake finishes. If all backend server recognizes \(dqEarly\-Data\(dq header field, using this option makes nghttpx not postpone forwarding request and get full potential of 0\-RTT data. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-max\-early\-data= Sets the maximum amount of 0\-RTT data that server accepts. .sp Default: \fB16K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-ktls Enable ktls. .UNINDENT .SS HTTP/2 .INDENT 0.0 .TP .B \-c, \-\-frontend\-http2\-max\-concurrent\-streams= Set the maximum number of the concurrent streams in one frontend HTTP/2 session. .sp Default: \fB100\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http2\-max\-concurrent\-streams= Set the maximum number of the concurrent streams in one backend HTTP/2 session. This sets maximum number of concurrent opened pushed streams. The maximum number of concurrent requests are set by a remote server. .sp Default: \fB100\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-window\-size= Sets the per\-stream initial window size of HTTP/2 frontend connection. .sp Default: \fB65535\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-connection\-window\-size= Sets the per\-connection window size of HTTP/2 frontend connection. .sp Default: \fB65535\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http2\-window\-size= Sets the initial window size of HTTP/2 backend connection. .sp Default: \fB65535\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http2\-connection\-window\-size= Sets the per\-connection window size of HTTP/2 backend connection. .sp Default: \fB2147483647\fP .UNINDENT .INDENT 0.0 .TP .B \-\-http2\-no\-cookie\-crumbling Don\(aqt crumble cookie header field. .UNINDENT .INDENT 0.0 .TP .B \-\-padding= Add at most bytes to a HTTP/2 frame payload as padding. Specify 0 to disable padding. This option is meant for debugging purpose and not intended to enhance protocol security. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-server\-push Disable HTTP/2 server push. Server push is supported by default mode and HTTP/2 frontend via Link header field. It is also supported if both frontend and backend are HTTP/2 in default mode. In this case, server push from backend session is relayed to frontend, and server push via Link header field is also supported. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-optimize\-write\-buffer\-size (Experimental) Enable write buffer size optimization in frontend HTTP/2 TLS connection. This optimization aims to reduce write buffer size so that it only contains bytes which can send immediately. This makes server more responsive to prioritized HTTP/2 stream because the buffering of lower priority stream is reduced. This option is only effective on recent Linux platform. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-optimize\-window\-size (Experimental) Automatically tune connection level window size of frontend HTTP/2 TLS connection. If this feature is enabled, connection window size starts with the default window size, 65535 bytes. nghttpx automatically adjusts connection window size based on TCP receiving window size. The maximum window size is capped by the value specified by \fI\%\-\-frontend\-http2\-connection\-window\-size\fP\&. Since the stream is subject to stream level window size, it should be adjusted using \fI\%\-\-frontend\-http2\-window\-size\fP option as well. This option is only effective on recent Linux platform. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-encoder\-dynamic\-table\-size= Specify the maximum dynamic table size of HPACK encoder in the frontend HTTP/2 connection. The decoder (client) specifies the maximum dynamic table size it accepts. Then the negotiated dynamic table size is the minimum of this option value and the value which client specified. .sp Default: \fB4K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-decoder\-dynamic\-table\-size= Specify the maximum dynamic table size of HPACK decoder in the frontend HTTP/2 connection. .sp Default: \fB4K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http2\-encoder\-dynamic\-table\-size= Specify the maximum dynamic table size of HPACK encoder in the backend HTTP/2 connection. The decoder (backend) specifies the maximum dynamic table size it accepts. Then the negotiated dynamic table size is the minimum of this option value and the value which backend specified. .sp Default: \fB4K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-http2\-decoder\-dynamic\-table\-size= Specify the maximum dynamic table size of HPACK decoder in the backend HTTP/2 connection. .sp Default: \fB4K\fP .UNINDENT .SS Mode .INDENT 0.0 .TP .B (default mode) Accept HTTP/2, and HTTP/1.1 over SSL/TLS. \(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option, accept HTTP/2 and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1 connection can be upgraded to HTTP/2 through HTTP Upgrade. .UNINDENT .INDENT 0.0 .TP .B \-s, \-\-http2\-proxy Like default mode, but enable forward proxy. This is so called HTTP/2 proxy mode. .UNINDENT .SS Logging .INDENT 0.0 .TP .B \-L, \-\-log\-level= Set the severity level of log output. must be one of INFO, NOTICE, WARN, ERROR and FATAL. .sp Default: \fBNOTICE\fP .UNINDENT .INDENT 0.0 .TP .B \-\-accesslog\-file= Set path to write access log. To reopen file, send USR1 signal to nghttpx. .UNINDENT .INDENT 0.0 .TP .B \-\-accesslog\-syslog Send access log to syslog. If this option is used, \fI\%\-\-accesslog\-file\fP option is ignored. .UNINDENT .INDENT 0.0 .TP .B \-\-accesslog\-format= Specify format string for access log. The default format is combined format. The following variables are available: .INDENT 7.0 .IP \(bu 2 $remote_addr: client IP address. .IP \(bu 2 $time_local: local time in Common Log format. .IP \(bu 2 $time_iso8601: local time in ISO 8601 format. .IP \(bu 2 $request: HTTP request line. .IP \(bu 2 $status: HTTP response status code. .IP \(bu 2 $body_bytes_sent: the number of bytes sent to client as response body. .IP \(bu 2 $http_: value of HTTP request header where \(aq_\(aq in is replaced with \(aq\-\(aq. .IP \(bu 2 $remote_port: client port. .IP \(bu 2 $server_port: server port. .IP \(bu 2 $request_time: request processing time in seconds with milliseconds resolution. .IP \(bu 2 $pid: PID of the running process. .IP \(bu 2 $alpn: ALPN identifier of the protocol which generates the response. For HTTP/1, ALPN is always http/1.1, regardless of minor version. .IP \(bu 2 $tls_cipher: cipher used for SSL/TLS connection. .IP \(bu 2 $tls_client_fingerprint_sha256: SHA\-256 fingerprint of client certificate. .IP \(bu 2 $tls_client_fingerprint_sha1: SHA\-1 fingerprint of client certificate. .IP \(bu 2 $tls_client_subject_name: subject name in client certificate. .IP \(bu 2 $tls_client_issuer_name: issuer name in client certificate. .IP \(bu 2 $tls_client_serial: serial number in client certificate. .IP \(bu 2 $tls_protocol: protocol for SSL/TLS connection. .IP \(bu 2 $tls_session_id: session ID for SSL/TLS connection. .IP \(bu 2 $tls_session_reused: \(dqr\(dq if SSL/TLS session was reused. Otherwise, \(dq.\(dq .IP \(bu 2 $tls_sni: SNI server name for SSL/TLS connection. .IP \(bu 2 $backend_host: backend host used to fulfill the request. \(dq\-\(dq if backend host is not available. .IP \(bu 2 $backend_port: backend port used to fulfill the request. \(dq\-\(dq if backend host is not available. .IP \(bu 2 $method: HTTP method .IP \(bu 2 $path: Request path including query. For CONNECT request, authority is recorded. .IP \(bu 2 $path_without_query: $path up to the first \(aq?\(aq character. For CONNECT request, authority is recorded. .IP \(bu 2 $protocol_version: HTTP version (e.g., HTTP/1.1, HTTP/2) .UNINDENT .sp The variable can be enclosed by \(dq{\(dq and \(dq}\(dq for disambiguation (e.g., ${remote_addr}). .sp Default: \fB$remote_addr \- \- [$time_local] \(dq$request\(dq $status $body_bytes_sent \(dq$http_referer\(dq \(dq$http_user_agent\(dq\fP .UNINDENT .INDENT 0.0 .TP .B \-\-accesslog\-write\-early Write access log when response header fields are received from backend rather than when request transaction finishes. .UNINDENT .INDENT 0.0 .TP .B \-\-errorlog\-file= Set path to write error log. To reopen file, send USR1 signal to nghttpx. stderr will be redirected to the error log file unless \fI\%\-\-errorlog\-syslog\fP is used. .sp Default: \fB/dev/stderr\fP .UNINDENT .INDENT 0.0 .TP .B \-\-errorlog\-syslog Send error log to syslog. If this option is used, \fI\%\-\-errorlog\-file\fP option is ignored. .UNINDENT .INDENT 0.0 .TP .B \-\-syslog\-facility= Set syslog facility to . .sp Default: \fBdaemon\fP .UNINDENT .SS HTTP .INDENT 0.0 .TP .B \-\-add\-x\-forwarded\-for Append X\-Forwarded\-For header field to the downstream request. .UNINDENT .INDENT 0.0 .TP .B \-\-strip\-incoming\-x\-forwarded\-for Strip X\-Forwarded\-For header field from inbound client requests. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-add\-x\-forwarded\-proto Don\(aqt append additional X\-Forwarded\-Proto header field to the backend request. If inbound client sets X\-Forwarded\-Proto, and \fI\%\-\-no\-strip\-incoming\-x\-forwarded\-proto\fP option is used, they are passed to the backend. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-strip\-incoming\-x\-forwarded\-proto Don\(aqt strip X\-Forwarded\-Proto header field from inbound client requests. .UNINDENT .INDENT 0.0 .TP .B \-\-add\-forwarded= Append RFC 7239 Forwarded header field with parameters specified in comma delimited list . The supported parameters are \(dqby\(dq, \(dqfor\(dq, \(dqhost\(dq, and \(dqproto\(dq. By default, the value of \(dqby\(dq and \(dqfor\(dq parameters are obfuscated string. See \fI\%\-\-forwarded\-by\fP and \fI\%\-\-forwarded\-for\fP options respectively. Note that nghttpx does not translate non\-standard X\-Forwarded\-* header fields into Forwarded header field, and vice versa. .UNINDENT .INDENT 0.0 .TP .B \-\-strip\-incoming\-forwarded Strip Forwarded header field from inbound client requests. .UNINDENT .INDENT 0.0 .TP .B \-\-forwarded\-by=(obfuscated|ip|) Specify the parameter value sent out with \(dqby\(dq parameter of Forwarded header field. If \(dqobfuscated\(dq is given, the string is randomly generated at startup. If \(dqip\(dq is given, the interface address of the connection, including port number, is sent with \(dqby\(dq parameter. In case of UNIX domain socket, \(dqlocalhost\(dq is used instead of address and port. User can also specify the static obfuscated string. The limitation is that it must start with \(dq_\(dq, and only consists of character set [A\-Za\-z0\-9._\-], as described in RFC 7239. .sp Default: \fBobfuscated\fP .UNINDENT .INDENT 0.0 .TP .B \-\-forwarded\-for=(obfuscated|ip) Specify the parameter value sent out with \(dqfor\(dq parameter of Forwarded header field. If \(dqobfuscated\(dq is given, the string is randomly generated for each client connection. If \(dqip\(dq is given, the remote client address of the connection, without port number, is sent with \(dqfor\(dq parameter. In case of UNIX domain socket, \(dqlocalhost\(dq is used instead of address. .sp Default: \fBobfuscated\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-via Don\(aqt append to Via header field. If Via header field is received, it is left unaltered. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-strip\-incoming\-early\-data Don\(aqt strip Early\-Data header field from inbound client requests. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-location\-rewrite Don\(aqt rewrite location header field in default mode. When \fI\%\-\-http2\-proxy\fP is used, location header field will not be altered regardless of this option. .UNINDENT .INDENT 0.0 .TP .B \-\-host\-rewrite Rewrite host and :authority header fields in default mode. When \fI\%\-\-http2\-proxy\fP is used, these headers will not be altered regardless of this option. .UNINDENT .INDENT 0.0 .TP .B \-\-altsvc= Specify protocol ID, port, host and origin of alternative service. , and are optional. Empty and are allowed and they are treated as nothing is specified. They are advertised in alt\-svc header field only in HTTP/1.1 frontend. This option can be used multiple times to specify multiple alternative services. Example: \fI\%\-\-altsvc\fP=\(dqh2,443,,,ma=3600; persist=1\(dq .UNINDENT .INDENT 0.0 .TP .B \-\-http2\-altsvc= Just like \fI\%\-\-altsvc\fP option, but this altsvc is only sent in HTTP/2 frontend. .UNINDENT .INDENT 0.0 .TP .B \-\-add\-request\-header=
    Specify additional header field to add to request header set. The field name must be lowercase. This option just appends header field and won\(aqt replace anything already set. This option can be used several times to specify multiple header fields. Example: \fI\%\-\-add\-request\-header\fP=\(dqfoo: bar\(dq .UNINDENT .INDENT 0.0 .TP .B \-\-add\-response\-header=
    Specify additional header field to add to response header set. The field name must be lowercase. This option just appends header field and won\(aqt replace anything already set. This option can be used several times to specify multiple header fields. Example: \fI\%\-\-add\-response\-header\fP=\(dqfoo: bar\(dq .UNINDENT .INDENT 0.0 .TP .B \-\-request\-header\-field\-buffer= Set maximum buffer size for incoming HTTP request header field list. This is the sum of header name and value in bytes. If trailer fields exist, they are counted towards this number. .sp Default: \fB64K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-max\-request\-header\-fields= Set maximum number of incoming HTTP request header fields. If trailer fields exist, they are counted towards this number. .sp Default: \fB100\fP .UNINDENT .INDENT 0.0 .TP .B \-\-response\-header\-field\-buffer= Set maximum buffer size for incoming HTTP response header field list. This is the sum of header name and value in bytes. If trailer fields exist, they are counted towards this number. .sp Default: \fB64K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-max\-response\-header\-fields= Set maximum number of incoming HTTP response header fields. If trailer fields exist, they are counted towards this number. .sp Default: \fB500\fP .UNINDENT .INDENT 0.0 .TP .B \-\-error\-page=(|*)= Set file path to custom error page served when nghttpx originally generates HTTP error status code . must be greater than or equal to 400, and at most 599. If \(dq*\(dq is used instead of , it matches all HTTP status code. If error status code comes from backend server, the custom error pages are not used. .UNINDENT .INDENT 0.0 .TP .B \-\-server\-name= Change server response header field value to . .sp Default: \fBnghttpx\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-server\-rewrite Don\(aqt rewrite server header field in default mode. When \fI\%\-\-http2\-proxy\fP is used, these headers will not be altered regardless of this option. .UNINDENT .INDENT 0.0 .TP .B \-\-redirect\-https\-port= Specify the port number which appears in Location header field when redirect to HTTPS URI is made due to \(dqredirect\-if\-not\-tls\(dq parameter in \fI\%\-\-backend\fP option. .sp Default: \fB443\fP .UNINDENT .INDENT 0.0 .TP .B \-\-require\-http\-scheme Always require http or https scheme in HTTP request. It also requires that https scheme must be used for an encrypted connection. Otherwise, http scheme must be used. This option is recommended for a server deployment which directly faces clients and the services it provides only require http or https scheme. .UNINDENT .SS API .INDENT 0.0 .TP .B \-\-api\-max\-request\-body= Set the maximum size of request body for API request. .sp Default: \fB32M\fP .UNINDENT .SS DNS .INDENT 0.0 .TP .B \-\-dns\-cache\-timeout= Set duration that cached DNS results remain valid. Note that nghttpx caches the unsuccessful results as well. .sp Default: \fB10s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-dns\-lookup\-timeout= Set timeout that DNS server is given to respond to the initial DNS query. For the 2nd and later queries, server is given time based on this timeout, and it is scaled linearly. .sp Default: \fB250ms\fP .UNINDENT .INDENT 0.0 .TP .B \-\-dns\-max\-try= Set the number of DNS query before nghttpx gives up name lookup. .sp Default: \fB3\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-max\-requests= The number of requests that single frontend connection can process. For HTTP/2, this is the number of streams in one HTTP/2 connection. For HTTP/1, this is the number of keep alive requests. This is hint to nghttpx, and it may allow additional few requests. The default value is unlimited. .UNINDENT .SS Debug .INDENT 0.0 .TP .B \-\-frontend\-http2\-dump\-request\-header= Dumps request headers received by HTTP/2 frontend to the file denoted in . The output is done in HTTP/1 header field format and each header block is followed by an empty line. This option is not thread safe and MUST NOT be used with option \fI\%\-n\fP, where >= 2. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http2\-dump\-response\-header= Dumps response headers sent from HTTP/2 frontend to the file denoted in . The output is done in HTTP/1 header field format and each header block is followed by an empty line. This option is not thread safe and MUST NOT be used with option \fI\%\-n\fP, where >= 2. .UNINDENT .INDENT 0.0 .TP .B \-o, \-\-frontend\-frame\-debug Print HTTP/2 frames in frontend to stderr. This option is not thread safe and MUST NOT be used with option \fI\%\-n\fP=N, where N >= 2. .UNINDENT .SS Process .INDENT 0.0 .TP .B \-D, \-\-daemon Run in a background. If \fI\%\-D\fP is used, the current working directory is changed to \(aq\fI/\fP\(aq. .UNINDENT .INDENT 0.0 .TP .B \-\-pid\-file= Set path to save PID of this program. .UNINDENT .INDENT 0.0 .TP .B \-\-user= Run this program as . This option is intended to be used to drop root privileges. .UNINDENT .INDENT 0.0 .TP .B \-\-single\-process Run this program in a single process mode for debugging purpose. Without this option, nghttpx creates at least 2 processes: main and worker processes. If this option is used, main and worker are unified into a single process. nghttpx still spawns additional process if neverbleed is used. In the single process mode, the signal handling feature is disabled. .UNINDENT .INDENT 0.0 .TP .B \-\-max\-worker\-processes= The maximum number of worker processes. nghttpx spawns new worker process when it reloads its configuration. The previous worker process enters graceful termination period and will terminate when it finishes handling the existing connections. However, if reloading configurations happen very frequently, the worker processes might be piled up if they take a bit long time to finish the existing connections. With this option, if the number of worker processes exceeds the given value, the oldest worker process is terminated immediately. Specifying 0 means no limit and it is the default behaviour. .UNINDENT .INDENT 0.0 .TP .B \-\-worker\-process\-grace\-shutdown\-period= Maximum period for a worker process to terminate gracefully. When a worker process enters in graceful shutdown period (e.g., when nghttpx reloads its configuration) and it does not finish handling the existing connections in the given period of time, it is immediately terminated. Specifying 0 means no limit and it is the default behaviour. .UNINDENT .SS Scripting .INDENT 0.0 .TP .B \-\-mruby\-file= Set mruby script file .UNINDENT .INDENT 0.0 .TP .B \-\-ignore\-per\-pattern\-mruby\-error Ignore mruby compile error for per\-pattern mruby script file. If error occurred, it is treated as if no mruby file were specified for the pattern. .UNINDENT .SS HTTP/3 and QUIC .INDENT 0.0 .TP .B \-\-frontend\-quic\-idle\-timeout= Specify an idle timeout for QUIC connection. .sp Default: \fB30s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-debug\-log Output QUIC debug log to \fI/dev/stderr.\fP .UNINDENT .INDENT 0.0 .TP .B \-\-quic\-bpf\-program\-file= Specify a path to eBPF program file reuseport_kern.o to direct an incoming QUIC UDP datagram to a correct socket. .sp Default: \fB/usr/local/lib/nghttp2/reuseport_kern.o\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-early\-data Enable early data on frontend QUIC connections. nghttpx sends \(dqEarly\-Data\(dq header field to a backend server if a request is received in early data and handshake has not finished. All backend servers should deal with possibly replayed requests. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-qlog\-dir= Specify a directory where a qlog file is written for frontend QUIC connections. A qlog file is created per each QUIC connection. The file name is ISO8601 basic format, followed by \(dq\-\(dq, server Source Connection ID and \(dq.sqlog\(dq. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-require\-token Require an address validation token for a frontend QUIC connection. Server sends a token in Retry packet or NEW_TOKEN frame in the previous connection. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-congestion\-controller= Specify a congestion controller algorithm for a frontend QUIC connection. should be either \(dqcubic\(dq or \(dqbbr\(dq. .sp Default: \fBcubic\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-secret\-file= Path to file that contains secure random data to be used as QUIC keying materials. It is used to derive keys for encrypting tokens and Connection IDs. It is not used to encrypt QUIC packets. Each line of this file must contain exactly 136 bytes hex\-encoded string (when decoded the byte string is 68 bytes long). The first 3 bits of decoded byte string are used to identify the keying material. An empty line or a line which starts \(aq#\(aq is ignored. The file can contain more than one keying materials. Because the identifier is 3 bits, at most 8 keying materials are read and the remaining data is discarded. The first keying material in the file is primarily used for encryption and decryption for new connection. The other ones are used to decrypt data for the existing connections. Specifying multiple keying materials enables key rotation. Please note that key rotation does not occur automatically. User should update files or change options values and restart nghttpx gracefully. If opening or reading given file fails, all loaded keying materials are discarded and it is treated as if none of this option is given. If this option is not given or an error occurred while opening or reading a file, a keying material is generated internally on startup and reload. .UNINDENT .INDENT 0.0 .TP .B \-\-quic\-server\-id= Specify server ID encoded in Connection ID to identify this particular server instance. Connection ID is encrypted and this part is not visible in public. It must be 4 bytes long and must be encoded in hex string (which is 8 bytes long). If this option is omitted, a random server ID is generated on startup and configuration reload. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-quic\-initial\-rtt= Specify the initial RTT of the frontend QUIC connection. .sp Default: \fB333ms\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-quic\-bpf Disable eBPF. .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http3\-window\-size= Sets the per\-stream initial window size of HTTP/3 frontend connection. .sp Default: \fB256K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http3\-connection\-window\-size= Sets the per\-connection window size of HTTP/3 frontend connection. .sp Default: \fB1M\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http3\-max\-window\-size= Sets the maximum per\-stream window size of HTTP/3 frontend connection. The window size is adjusted based on the receiving rate of stream data. The initial value is the value specified by \fI\%\-\-frontend\-http3\-window\-size\fP and the window size grows up to bytes. .sp Default: \fB6M\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http3\-max\-connection\-window\-size= Sets the maximum per\-connection window size of HTTP/3 frontend connection. The window size is adjusted based on the receiving rate of stream data. The initial value is the value specified by \fI\%\-\-frontend\-http3\-connection\-window\-size\fP and the window size grows up to bytes. .sp Default: \fB8M\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-http3\-max\-concurrent\-streams= Set the maximum number of the concurrent streams in one frontend HTTP/3 connection. .sp Default: \fB100\fP .UNINDENT .SS Misc .INDENT 0.0 .TP .B \-\-conf= Load configuration from . Please note that nghttpx always tries to read the default configuration file if \fI\%\-\-conf\fP is not given. .sp Default: \fB/etc/nghttpx/nghttpx.conf\fP .UNINDENT .INDENT 0.0 .TP .B \-\-include= Load additional configurations from . File is read when configuration parser encountered this option. This option can be used multiple times, or even recursively. .UNINDENT .INDENT 0.0 .TP .B \-v, \-\-version Print version and exit. .UNINDENT .INDENT 0.0 .TP .B \-h, \-\-help Print this help and exit. .UNINDENT .sp The argument is an integer and an optional unit (e.g., 10K is 10 * 1024). Units are K, M and G (powers of 1024). .sp The argument is an integer and an optional unit (e.g., 1s is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms (hours, minutes, seconds and milliseconds, respectively). If a unit is omitted, a second is used as unit. .SH FILES .INDENT 0.0 .TP .B \fI/etc/nghttpx/nghttpx.conf\fP The default configuration file path nghttpx searches at startup. The configuration file path can be changed using \fI\%\-\-conf\fP option. .sp Those lines which are staring \fB#\fP are treated as comment. .sp The option name in the configuration file is the long command\-line option name with leading \fB\-\-\fP stripped (e.g., \fBfrontend\fP). Put \fB=\fP between option name and value. Don\(aqt put extra leading or trailing spaces. .sp When specifying arguments including characters which have special meaning to a shell, we usually use quotes so that shell does not interpret them. When writing this configuration file, quotes for this purpose must not be used. For example, specify additional request header field, do this: .INDENT 7.0 .INDENT 3.5 .sp .EX add\-request\-header=foo: bar .EE .UNINDENT .UNINDENT .sp instead of: .INDENT 7.0 .INDENT 3.5 .sp .EX add\-request\-header=\(dqfoo: bar\(dq .EE .UNINDENT .UNINDENT .sp The options which do not take argument in the command\-line \fItake\fP argument in the configuration file. Specify \fByes\fP as an argument (e.g., \fBhttp2\-proxy=yes\fP). If other string is given, it is ignored. .sp To specify private key and certificate file which are given as positional arguments in command\-line, use \fBprivate\-key\-file\fP and \fBcertificate\-file\fP\&. .sp \fI\%\-\-conf\fP option cannot be used in the configuration file and will be ignored if specified. .TP .B Error log Error log is written to stderr by default. It can be configured using \fI\%\-\-errorlog\-file\fP\&. The format of log message is as follows: .sp (:) .INDENT 7.0 .TP .B It is a combination of date and time when the log is written. It is in ISO 8601 format. .TP .B It is a main process ID. .TP .B It is a process ID which writes this log. .TP .B It is a thread ID which writes this log. It would be unique within . .TP .B and They are source file name, and line number which produce this log. .TP .B It is a log message body. .UNINDENT .UNINDENT .SH SIGNALS .INDENT 0.0 .TP .B SIGQUIT Shutdown gracefully. First accept pending connections and stop accepting connection. After all connections are handled, nghttpx exits. .TP .B SIGHUP Reload configuration file given in \fI\%\-\-conf\fP\&. .TP .B SIGUSR1 Reopen log files. .UNINDENT .sp SIGUSR2 .INDENT 0.0 .INDENT 3.5 Fork and execute nghttpx. It will execute the binary in the same path with same command\-line arguments and environment variables. As of nghttpx version 1.20.0, the new main process sends SIGQUIT to the original main process when it is ready to serve requests. For the earlier versions of nghttpx, user has to send SIGQUIT to the original main process. .sp The difference between SIGUSR2 (+ SIGQUIT) and SIGHUP is that former is usually used to execute new binary, and the main process is newly spawned. On the other hand, the latter just reloads configuration file, and the same main process continues to exist. .UNINDENT .UNINDENT .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 nghttpx consists of multiple processes: one process for processing these signals, and another one for processing requests. The former spawns the latter. The former is called main process, and the latter is called worker process. If neverbleed is enabled, the worker process spawns neverbleed daemon process which does RSA key processing. The above signal must be sent to the main process. If the other processes received one of them, it is ignored. This behaviour of these processes may change in the future release. In other words, in the future release, the processes other than main process may terminate upon the reception of these signals. Therefore these signals should not be sent to the processes other than main process. .UNINDENT .UNINDENT .SH SERVER PUSH .sp nghttpx supports HTTP/2 server push in default mode with Link header field. nghttpx looks for Link header field (\X'tty: link http://tools.ietf.org/html/rfc5988'\fI\%RFC 5988\fP\X'tty: link') in response headers from backend server and extracts URI\-reference with parameter \fBrel=preload\fP (see \X'tty: link http://w3c.github.io/preload/#interoperability-with-http-link-header'\fI\%preload\fP\X'tty: link') and pushes those URIs to the frontend client. Here is a sample Link header field to initiate server push: .INDENT 0.0 .INDENT 3.5 .sp .EX Link: ; rel=preload Link: ; rel=preload .EE .UNINDENT .UNINDENT .sp Currently, the following restriction is applied for server push: .INDENT 0.0 .IP 1. 3 The associated stream must have method \(dqGET\(dq or \(dqPOST\(dq. The associated stream\(aqs status code must be 200. .UNINDENT .sp This limitation may be loosened in the future release. .sp nghttpx also supports server push if both frontend and backend are HTTP/2 in default mode. In this case, in addition to server push via Link header field, server push from backend is forwarded to frontend HTTP/2 session. .sp HTTP/2 server push will be disabled if \fI\%\-\-http2\-proxy\fP is used. .SH UNIX DOMAIN SOCKET .sp nghttpx supports UNIX domain socket with a filename for both frontend and backend connections. .sp Please note that current nghttpx implementation does not delete a socket with a filename. And on start up, if nghttpx detects that the specified socket already exists in the file system, nghttpx first deletes it. However, if SIGUSR2 is used to execute new binary and both old and new configurations use same filename, new binary does not delete the socket and continues to use it. .SH TLS SESSION RESUMPTION .sp nghttpx supports TLS session resumption through both session ID and session ticket. .SS SESSION ID RESUMPTION .sp By default, session ID is shared by all worker threads. .SS TLS SESSION TICKET RESUMPTION .sp By default, session ticket is shared by all worker threads. The automatic key rotation is also enabled by default. Every an hour, new encryption key is generated, and previous encryption key becomes decryption only key. We set session timeout to 12 hours, and thus we keep at most 12 keys. .sp If \fI\%\-\-tls\-ticket\-key\-memcached\fP is given, encryption keys are retrieved from memcached. nghttpx just reads keys from memcached; one has to deploy key generator program to update keys frequently (e.g., every 1 hour). The example key generator tlsticketupdate.go is available under contrib directory in nghttp2 archive. The memcached entry key is \fBnghttpx:tls\-ticket\-key\fP\&. The data format stored in memcached is the binary format described below: .INDENT 0.0 .INDENT 3.5 .sp .EX +\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ | VERSION (4) |LEN (2)|KEY(48 or 80) ... +\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ ^ | | | +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ (LEN, KEY) pair can be repeated .EE .UNINDENT .UNINDENT .sp All numbers in the above figure is bytes. All integer fields are network byte order. .sp First 4 bytes integer VERSION field, which must be 1. The 2 bytes integer LEN field gives the length of following KEY field, which contains key. If \fI\%\-\-tls\-ticket\-key\-cipher\fP=aes\-128\-cbc is used, LEN must be 48. If \fI\%\-\-tls\-ticket\-key\-cipher\fP=aes\-256\-cbc is used, LEN must be 80. LEN and KEY pair can be repeated multiple times to store multiple keys. The key appeared first is used as encryption key. All the remaining keys are used as decryption only. .sp By default, connections to memcached server are not encrypted. To enable encryption, use \fBtls\fP keyword in \fI\%\-\-tls\-ticket\-key\-memcached\fP option. .sp If \fI\%\-\-tls\-ticket\-key\-file\fP is given, encryption key is read from the given file. In this case, nghttpx does not rotate key automatically. To rotate key, one has to restart nghttpx (see SIGNALS). .SH CERTIFICATE TRANSPARENCY .sp nghttpx supports TLS \fBsigned_certificate_timestamp\fP extension (\X'tty: link https://tools.ietf.org/html/rfc6962'\fI\%RFC 6962\fP\X'tty: link'). The relevant options are \fI\%\-\-tls\-sct\-dir\fP and \fBsct\-dir\fP parameter in \fI\%\-\-subcert\fP\&. They takes a directory, and nghttpx reads all files whose extension is \fB\&.sct\fP under the directory. The \fB*.sct\fP files are encoded as \fBSignedCertificateTimestamp\fP struct described in \X'tty: link https://tools.ietf.org/html/rfc6962#section-3.2'\fI\%section 3.2 of RFC 69662\fP\X'tty: link'\&. This format is the same one used by \X'tty: link https://github.com/grahamedgecombe/nginx-ct'\fI\%nginx\-ct\fP\X'tty: link' and \X'tty: link https://httpd.apache.org/docs/trunk/mod/mod_ssl_ct.html'\fI\%mod_ssl_ct\fP\X'tty: link'\&. \X'tty: link https://github.com/grahamedgecombe/ct-submit'\fI\%ct\-submit\fP\X'tty: link' can be used to submit certificates to log servers, and obtain the \fBSignedCertificateTimestamp\fP struct which can be used with nghttpx. .SH MRUBY SCRIPTING .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 The current mruby extension API is experimental and not frozen. The API is subject to change in the future release. .UNINDENT .UNINDENT .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 Almost all string value returned from method, or attribute is a fresh new mruby string, which involves memory allocation, and copies. Therefore, it is strongly recommended to store a return value in a local variable, and use it, instead of calling method or accessing attribute repeatedly. .UNINDENT .UNINDENT .sp nghttpx allows users to extend its capability using mruby scripts. nghttpx has 2 hook points to execute mruby script: request phase and response phase. The request phase hook is invoked after all request header fields are received from client. The response phase hook is invoked after all response header fields are received from backend server. These hooks allows users to modify header fields, or common HTTP variables, like authority or request path, and even return custom response without forwarding request to backend servers. .sp There are 2 levels of mruby script invocations: global and per\-pattern. The global mruby script is set by \fI\%\-\-mruby\-file\fP option and is called for all requests. The per\-pattern mruby script is set by \(dqmruby\(dq parameter in \fI\%\-b\fP option. It is invoked for a request which matches the particular pattern. The order of hook invocation is: global request phase hook, per\-pattern request phase hook, per\-pattern response phase hook, and finally global response phase hook. If a hook returns a response, any later hooks are not invoked. The global request hook is invoked before the pattern matching is made and changing request path may affect the pattern matching. .sp Please note that request and response hooks of per\-pattern mruby script for a single request might not come from the same script. This might happen after a request hook is executed, backend failed for some reason, and at the same time, backend configuration is replaced by API request, and then the request uses new configuration on retry. The response hook from new configuration, if it is specified, will be invoked. .sp The all mruby script will be evaluated once per thread on startup, and it must instantiate object and evaluate it as the return value (e.g., \fBApp.new\fP). This object is called app object. If app object defines \fBon_req\fP method, it is called with \fI\%Nghttpx::Env\fP object on request hook. Similarly, if app object defines \fBon_resp\fP method, it is called with \fI\%Nghttpx::Env\fP object on response hook. For each method invocation, user can can access \fI\%Nghttpx::Request\fP and \fI\%Nghttpx::Response\fP objects via \fI\%Nghttpx::Env#req\fP and \fI\%Nghttpx::Env#resp\fP respectively. .INDENT 0.0 .TP .B Nghttpx::REQUEST_PHASE Constant to represent request phase. .UNINDENT .INDENT 0.0 .TP .B Nghttpx::RESPONSE_PHASE Constant to represent response phase. .UNINDENT .INDENT 0.0 .TP .B class Nghttpx::Env Object to represent current request specific context. .INDENT 7.0 .TP .B attribute [R] req Return \fI\%Request\fP object. .UNINDENT .INDENT 7.0 .TP .B attribute [R] resp Return \fI\%Response\fP object. .UNINDENT .INDENT 7.0 .TP .B attribute [R] ctx Return Ruby hash object. It persists until request finishes. So values set in request phase hook can be retrieved in response phase hook. .UNINDENT .INDENT 7.0 .TP .B attribute [R] phase Return the current phase. .UNINDENT .INDENT 7.0 .TP .B attribute [R] remote_addr Return IP address of a remote client. If connection is made via UNIX domain socket, this returns the string \(dqlocalhost\(dq. .UNINDENT .INDENT 7.0 .TP .B attribute [R] server_addr Return address of server that accepted the connection. This is a string which specified in \fI\%\-\-frontend\fP option, excluding port number, and not a resolved IP address. For UNIX domain socket, this is a path to UNIX domain socket. .UNINDENT .INDENT 7.0 .TP .B attribute [R] server_port Return port number of the server frontend which accepted the connection from client. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_used Return true if TLS is used on the connection. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_sni Return the TLS SNI value which client sent in this connection. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_fingerprint_sha256 Return the SHA\-256 fingerprint of a client certificate. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_fingerprint_sha1 Return the SHA\-1 fingerprint of a client certificate. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_issuer_name Return the issuer name of a client certificate. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_subject_name Return the subject name of a client certificate. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_serial Return the serial number of a client certificate. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_not_before Return the start date of a client certificate in seconds since the epoch. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_client_not_after Return the end date of a client certificate in seconds since the epoch. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_cipher Return a TLS cipher negotiated in this connection. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_protocol Return a TLS protocol version negotiated in this connection. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_session_id Return a session ID for this connection in hex string. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_session_reused Return true if, and only if a SSL/TLS session is reused. .UNINDENT .INDENT 7.0 .TP .B attribute [R] alpn Return ALPN identifier negotiated in this connection. .UNINDENT .INDENT 7.0 .TP .B attribute [R] tls_handshake_finished Return true if SSL/TLS handshake has finished. If it returns false in the request phase hook, the request is received in TLSv1.3 early data (0\-RTT) and might be vulnerable to the replay attack. nghttpx will send Early\-Data header field to backend servers to indicate this. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B class Nghttpx::Request Object to represent request from client. The modification to Request object is allowed only in request phase hook. .INDENT 7.0 .TP .B attribute [R] http_version_major Return HTTP major version. .UNINDENT .INDENT 7.0 .TP .B attribute [R] http_version_minor Return HTTP minor version. .UNINDENT .INDENT 7.0 .TP .B attribute [R/W] method HTTP method. On assignment, copy of given value is assigned. We don\(aqt accept arbitrary method name. We will document them later, but well known methods, like GET, PUT and POST, are all supported. .UNINDENT .INDENT 7.0 .TP .B attribute [R/W] authority Authority (i.e., example.org), including optional port component . On assignment, copy of given value is assigned. .UNINDENT .INDENT 7.0 .TP .B attribute [R/W] scheme Scheme (i.e., http, https). On assignment, copy of given value is assigned. .UNINDENT .INDENT 7.0 .TP .B attribute [R/W] path Request path, including query component (i.e., /index.html). On assignment, copy of given value is assigned. The path does not include authority component of URI. This may include query component. nghttpx makes certain normalization for path. It decodes percent\-encoding for unreserved characters (see \X'tty: link https://tools.ietf.org/html/rfc3986#section-2.3'\fI\%https://tools.ietf.org/html/rfc3986#section\-2.3\fP\X'tty: link'), and resolves \(dq..\(dq and \(dq.\(dq. But it may leave characters which should be percent\-encoded as is. So be careful when comparing path against desired string. .UNINDENT .INDENT 7.0 .TP .B attribute [R] headers Return Ruby hash containing copy of request header fields. Changing values in returned hash does not change request header fields actually used in request processing. Use \fI\%Nghttpx::Request#add_header\fP or \fI\%Nghttpx::Request#set_header\fP to change request header fields. .UNINDENT .INDENT 7.0 .TP .B add_header(key, value) Add header entry associated with key. The value can be single string or array of string. It does not replace any existing values associated with key. .UNINDENT .INDENT 7.0 .TP .B set_header(key, value) Set header entry associated with key. The value can be single string or array of string. It replaces any existing values associated with key. .UNINDENT .INDENT 7.0 .TP .B clear_headers() Clear all existing request header fields. .UNINDENT .INDENT 7.0 .TP .B push(uri) Initiate to push resource identified by \fIuri\fP\&. Only HTTP/2 protocol supports this feature. For the other protocols, this method is noop. \fIuri\fP can be absolute URI, absolute path or relative path to the current request. For absolute or relative path, scheme and authority are inherited from the current request. Currently, method is always GET. nghttpx will issue request to backend servers to fulfill this request. The request and response phase hooks will be called for pushed resource as well. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B class Nghttpx::Response Object to represent response from backend server. .INDENT 7.0 .TP .B attribute [R] http_version_major Return HTTP major version. .UNINDENT .INDENT 7.0 .TP .B attribute [R] http_version_minor Return HTTP minor version. .UNINDENT .INDENT 7.0 .TP .B attribute [R/W] status HTTP status code. It must be in the range [200, 999], inclusive. The non\-final status code is not supported in mruby scripting at the moment. .UNINDENT .INDENT 7.0 .TP .B attribute [R] headers Return Ruby hash containing copy of response header fields. Changing values in returned hash does not change response header fields actually used in response processing. Use \fI\%Nghttpx::Response#add_header\fP or \fI\%Nghttpx::Response#set_header\fP to change response header fields. .UNINDENT .INDENT 7.0 .TP .B add_header(key, value) Add header entry associated with key. The value can be single string or array of string. It does not replace any existing values associated with key. .UNINDENT .INDENT 7.0 .TP .B set_header(key, value) Set header entry associated with key. The value can be single string or array of string. It replaces any existing values associated with key. .UNINDENT .INDENT 7.0 .TP .B clear_headers() Clear all existing response header fields. .UNINDENT .INDENT 7.0 .TP .B return(body) Return custom response \fIbody\fP to a client. When this method is called in request phase hook, the request is not forwarded to the backend, and response phase hook for this request will not be invoked. When this method is called in response phase hook, response from backend server is canceled and discarded. The status code and response header fields should be set before using this method. To set status code, use \fI\%Nghttpx::Response#status\fP\&. If status code is not set, 200 is used. To set response header fields, \fI\%Nghttpx::Response#add_header\fP and \fI\%Nghttpx::Response#set_header\fP\&. When this method is invoked in response phase hook, the response headers are filled with the ones received from backend server. To send completely custom header fields, first call \fI\%Nghttpx::Response#clear_headers\fP to erase all existing header fields, and then add required header fields. It is an error to call this method twice for a given request. .UNINDENT .INDENT 7.0 .TP .B send_info(status, headers) Send non\-final (informational) response to a client. \fIstatus\fP must be in the range [100, 199], inclusive. \fIheaders\fP is a hash containing response header fields. Its key must be a string, and the associated value must be either string or array of strings. Since this is not a final response, even if this method is invoked, request is still forwarded to a backend unless \fI\%Nghttpx::Response#return\fP is called. This method can be called multiple times. It cannot be called after \fI\%Nghttpx::Response#return\fP is called. .UNINDENT .UNINDENT .SS MRUBY EXAMPLES .sp Modify request path: .INDENT 0.0 .INDENT 3.5 .sp .EX class App def on_req(env) env.req.path = \(dq/apps#{env.req.path}\(dq end end App.new .EE .UNINDENT .UNINDENT .sp Don\(aqt forget to instantiate and evaluate object at the last line. .sp Restrict permission of viewing a content to a specific client addresses: .INDENT 0.0 .INDENT 3.5 .sp .EX class App def on_req(env) allowed_clients = [\(dq127.0.0.1\(dq, \(dq::1\(dq] if env.req.path.start_with?(\(dq/log/\(dq) && !allowed_clients.include?(env.remote_addr) then env.resp.status = 404 env.resp.return \(dqpermission denied\(dq end end end App.new .EE .UNINDENT .UNINDENT .SH API ENDPOINTS .sp nghttpx exposes API endpoints to manipulate it via HTTP based API. By default, API endpoint is disabled. To enable it, add a dedicated frontend for API using \fI\%\-\-frontend\fP option with \(dqapi\(dq parameter. All requests which come from this frontend address, will be treated as API request. .sp The response is normally JSON dictionary, and at least includes the following keys: .INDENT 0.0 .TP .B status The status of the request processing. The following values are defined: .INDENT 7.0 .TP .B Success The request was successful. .TP .B Failure The request was failed. No change has been made. .UNINDENT .TP .B code HTTP status code .UNINDENT .sp Additionally, depending on the API endpoint, \fBdata\fP key may be present, and its value contains the API endpoint specific data. .sp We wrote \(dqnormally\(dq, since nghttpx may return ordinal HTML response in some cases where the error has occurred before reaching API endpoint (e.g., header field is too large). .sp The following section describes available API endpoints. .SS POST /api/v1beta1/backendconfig .sp This API replaces the current backend server settings with the requested ones. The request method should be POST, but PUT is also acceptable. The request body must be nghttpx configuration file format. For configuration file format, see \fI\%FILES\fP section. The line separator inside the request body must be single LF (0x0A). Currently, only \fI\%backend\fP option is parsed, the others are simply ignored. The semantics of this API is replace the current backend with the backend options in request body. Describe the desired set of backend severs, and nghttpx makes it happen. If there is no \fI\%backend\fP option is found in request body, the current set of backend is replaced with the \fI\%backend\fP option\(aqs default value, which is \fB127.0.0.1,80\fP\&. .sp The replacement is done instantly without breaking existing connections or requests. It also avoids any process creation as is the case with hot swapping with signals. .sp The one limitation is that only numeric IP address is allowed in \fI\%backend\fP in request body unless \(dqdns\(dq parameter is used while non numeric hostname is allowed in command\-line or configuration file is read using \fI\%\-\-conf\fP\&. .SS GET /api/v1beta1/configrevision .sp This API returns configuration revision of the current nghttpx. The configuration revision is opaque string, and it changes after each reloading by SIGHUP. With this API, an external application knows that whether nghttpx has finished reloading its configuration by comparing the configuration revisions between before and after reloading. It is recommended to disable persistent (keep\-alive) connection for this purpose in order to avoid to send a request using the reused connection which may bound to an old process. .sp This API returns response including \fBdata\fP key. Its value is JSON object, and it contains at least the following key: .INDENT 0.0 .TP .B configRevision The configuration revision of the current nghttpx .UNINDENT .SH SEE ALSO .sp \fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBh2load(1)\fP .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT 2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . man/man1/nghttp.1000064400000015336152464121240007552 0ustar00.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "NGHTTP" "1" "Oct 25, 2025" "1.68.0" "nghttp2" .SH NAME nghttp \- HTTP/2 client .SH SYNOPSIS .sp \fBnghttp\fP [OPTIONS]... ... .SH DESCRIPTION .sp HTTP/2 client .INDENT 0.0 .TP .B Specify URI to access. .UNINDENT .SH OPTIONS .INDENT 0.0 .TP .B \-v, \-\-verbose Print debug information such as reception and transmission of frames and name/value pairs. Specifying this option multiple times increases verbosity. .UNINDENT .INDENT 0.0 .TP .B \-n, \-\-null\-out Discard downloaded data. .UNINDENT .INDENT 0.0 .TP .B \-O, \-\-remote\-name Save download data in the current directory. The filename is derived from URI. If URI ends with \(aq\fI/\fP\(aq, \(aqindex.html\(aq is used as a filename. Not implemented yet. .UNINDENT .INDENT 0.0 .TP .B \-t, \-\-timeout= Timeout each request after . Set 0 to disable timeout. .UNINDENT .INDENT 0.0 .TP .B \-w, \-\-window\-bits= Sets the stream level initial window size to 2**\-1. .UNINDENT .INDENT 0.0 .TP .B \-W, \-\-connection\-window\-bits= Sets the connection level initial window size to 2**\-1. .UNINDENT .INDENT 0.0 .TP .B \-a, \-\-get\-assets Download assets such as stylesheets, images and script files linked from the downloaded resource. Only links whose origins are the same with the linking resource will be downloaded. nghttp prioritizes resources using HTTP/2 dependency based priority. The priority order, from highest to lowest, is html itself, css, javascript and images. .UNINDENT .INDENT 0.0 .TP .B \-s, \-\-stat Print statistics. .UNINDENT .INDENT 0.0 .TP .B \-H, \-\-header=
    Add a header to the requests. Example: \fI\%\-H\fP\(aq:method: PUT\(aq .UNINDENT .INDENT 0.0 .TP .B \-\-trailer=
    Add a trailer header to the requests.
    must not include pseudo header field (header field name starting with \(aq:\(aq). To send trailer, one must use \fI\%\-d\fP option to send request body. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq. .UNINDENT .INDENT 0.0 .TP .B \-\-cert= Use the specified client certificate file. The file must be in PEM format. .UNINDENT .INDENT 0.0 .TP .B \-\-key= Use the client private key file. The file must be in PEM format. .UNINDENT .INDENT 0.0 .TP .B \-d, \-\-data= Post FILE to server. If \(aq\-\(aq is given, data will be read from stdin. .UNINDENT .INDENT 0.0 .TP .B \-m, \-\-multiply= Request each URI times. By default, same URI is not requested twice. This option disables it too. .UNINDENT .INDENT 0.0 .TP .B \-u, \-\-upgrade Perform HTTP Upgrade for HTTP/2. This option is ignored if the request URI has https scheme. If \fI\%\-d\fP is used, the HTTP upgrade request is performed with OPTIONS method. .UNINDENT .INDENT 0.0 .TP .B \-\-extpri= Sets RFC 9218 priority of given URI. must be the wire format of priority header field (e.g., \(dqu=3,i\(dq). This option can be used multiple times, and N\-th \fI\%\-\-extpri\fP option sets priority of N\-th URI in the command line. If the number of this option is less than the number of URI, the last option value is repeated. If there is no \fI\%\-\-extpri\fP option, urgency is 3, and incremental is false. .UNINDENT .INDENT 0.0 .TP .B \-M, \-\-peer\-max\-concurrent\-streams= Use as SETTINGS_MAX_CONCURRENT_STREAMS value of remote endpoint as if it is received in SETTINGS frame. .sp Default: \fB100\fP .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-header\-table\-size= Specify decoder header table size. If this option is used multiple times, and the minimum value among the given values except for last one is strictly less than the last value, that minimum value is set in SETTINGS frame payload before the last value, to simulate multiple header table size change. .UNINDENT .INDENT 0.0 .TP .B \-\-encoder\-header\-table\-size= Specify encoder header table size. The decoder (server) specifies the maximum dynamic table size it accepts. Then the negotiated dynamic table size is the minimum of this option value and the value which server specified. .UNINDENT .INDENT 0.0 .TP .B \-b, \-\-padding= Add at most bytes to a frame payload as padding. Specify 0 to disable padding. .UNINDENT .INDENT 0.0 .TP .B \-r, \-\-har= Output HTTP transactions in HAR format. If \(aq\-\(aq is given, data is written to stdout. .UNINDENT .INDENT 0.0 .TP .B \-\-color Force colored log output. .UNINDENT .INDENT 0.0 .TP .B \-\-continuation Send large header to test CONTINUATION. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-content\-length Don\(aqt send content\-length header field. .UNINDENT .INDENT 0.0 .TP .B \-\-hexdump Display the incoming traffic in hexadecimal (Canonical hex+ASCII display). If SSL/TLS is used, decrypted data are used. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-push Disable server push. .UNINDENT .INDENT 0.0 .TP .B \-\-max\-concurrent\-streams= The number of concurrent pushed streams this client accepts. .UNINDENT .INDENT 0.0 .TP .B \-\-expect\-continue Perform an Expect/Continue handshake: wait to send DATA (up to a short timeout) until the server sends a 100 Continue interim response. This option is ignored unless combined with the \fI\%\-d\fP option. .UNINDENT .INDENT 0.0 .TP .B \-y, \-\-no\-verify\-peer Suppress warning on server certificate verification failure. .UNINDENT .INDENT 0.0 .TP .B \-\-ktls Enable ktls. .UNINDENT .INDENT 0.0 .TP .B \-\-version Display version information and exit. .UNINDENT .INDENT 0.0 .TP .B \-h, \-\-help Display this help and exit. .UNINDENT .sp The argument is an integer and an optional unit (e.g., 10K is 10 * 1024). Units are K, M and G (powers of 1024). .sp The argument is an integer and an optional unit (e.g., 1s is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms (hours, minutes, seconds and milliseconds, respectively). If a unit is omitted, a second is used as unit. .SH SEE ALSO .sp \fBnghttpd(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT 2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . man/man1/h2load.1000064400000036731152464121240007421 0ustar00.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "H2LOAD" "1" "Oct 25, 2025" "1.68.0" "nghttp2" .SH NAME h2load \- HTTP/2 benchmarking tool .SH SYNOPSIS .sp \fBh2load\fP [OPTIONS]... [URI]... .SH DESCRIPTION .sp benchmarking tool for HTTP/2 server .INDENT 0.0 .TP .B Specify URI to access. Multiple URIs can be specified. URIs are used in this order for each client. All URIs are used, then first URI is used and then 2nd URI, and so on. The scheme, host and port in the subsequent URIs, if present, are ignored. Those in the first URI are used solely. Definition of a base URI overrides all scheme, host or port values. .UNINDENT .SH OPTIONS .INDENT 0.0 .TP .B \-n, \-\-requests= Number of requests across all clients. If it is used with \fI\%\-\-timing\-script\-file\fP option, this option specifies the number of requests each client performs rather than the number of requests across all clients. This option is ignored if timing\-based benchmarking is enabled (see \fI\%\-\-duration\fP option). .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-clients= Number of concurrent clients. With \fI\%\-r\fP option, this specifies the maximum number of connections to be made. .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-t, \-\-threads= Number of native threads. .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-i, \-\-input\-file= Path of a file with multiple URIs are separated by EOLs. This option will disable URIs getting from command\-line. If \(aq\-\(aq is given as , URIs will be read from stdin. URIs are used in this order for each client. All URIs are used, then first URI is used and then 2nd URI, and so on. The scheme, host and port in the subsequent URIs, if present, are ignored. Those in the first URI are used solely. Definition of a base URI overrides all scheme, host or port values. .UNINDENT .INDENT 0.0 .TP .B \-m, \-\-max\-concurrent\-streams= Max concurrent streams to issue per session. When http/1.1 is used, this specifies the number of HTTP pipelining requests in\-flight. .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-f, \-\-max\-frame\-size= Maximum frame size that the local endpoint is willing to receive. .sp Default: \fB16K\fP .UNINDENT .INDENT 0.0 .TP .B \-w, \-\-window\-bits= Sets the stream level initial window size to (2**)\-1. For QUIC, is capped to 26 (roughly 64MiB). It defaults to 24 (16MiB) for QUIC, and 30 for other protocols. .UNINDENT .INDENT 0.0 .TP .B \-W, \-\-connection\-window\-bits= Sets the connection level initial window size to (2**)\-1. .sp Default: \fB30\fP .UNINDENT .INDENT 0.0 .TP .B \-H, \-\-header=
    Add/Override a header to the requests. .UNINDENT .INDENT 0.0 .TP .B \-\-ciphers= Set allowed cipher list for TLSv1.2 or earlier. The format of the string is described in OpenSSL ciphers(1). .sp Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:DHE\-RSA\-AES128\-GCM\-SHA256:DHE\-RSA\-AES256\-GCM\-SHA384\fP .UNINDENT .INDENT 0.0 .TP .B \-\-tls13\-ciphers= Set allowed cipher list for TLSv1.3. The format of the string is described in OpenSSL ciphers(1). .sp Default: \fBTLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256\fP .UNINDENT .INDENT 0.0 .TP .B \-p, \-\-no\-tls\-proto= Specify ALPN identifier of the protocol to be used when accessing http URI without SSL/TLS. Available protocols: h2c and http/1.1 .sp Default: \fBh2c\fP .UNINDENT .INDENT 0.0 .TP .B \-d, \-\-data= Post FILE to server. The request method is changed to POST. For http/1.1 connection, if \fI\%\-d\fP is used, the maximum number of in\-flight pipelined requests is set to 1. .UNINDENT .INDENT 0.0 .TP .B \-r, \-\-rate= Specifies the fixed rate at which connections are created. The rate must be a positive integer, representing the number of connections to be made per rate period. The maximum number of connections to be made is given in \fI\%\-c\fP option. This rate will be distributed among threads as evenly as possible. For example, with \fI\%\-t\fP2 and \fI\%\-r\fP4, each thread gets 2 connections per period. When the rate is 0, the program will run as it normally does, creating connections at whatever variable rate it wants. The default value for this option is 0. \fI\%\-r\fP and \fI\%\-D\fP are mutually exclusive. .UNINDENT .INDENT 0.0 .TP .B \-\-rate\-period= Specifies the time period between creating connections. The period must be a positive number, representing the length of the period in time. This option is ignored if the rate option is not used. The default value for this option is 1s. .UNINDENT .INDENT 0.0 .TP .B \-D, \-\-duration= Specifies the main duration for the measurements in case of timing\-based benchmarking. \fI\%\-D\fP and \fI\%\-r\fP are mutually exclusive. .UNINDENT .INDENT 0.0 .TP .B \-\-warm\-up\-time= Specifies the time period before starting the actual measurements, in case of timing\-based benchmarking. Needs to provided along with \fI\%\-D\fP option. .UNINDENT .INDENT 0.0 .TP .B \-T, \-\-connection\-active\-timeout= Specifies the maximum time that h2load is willing to keep a connection open, regardless of the activity on said connection. must be a positive integer, specifying the amount of time to wait. When no timeout value is set (either active or inactive), h2load will keep a connection open indefinitely, waiting for a response. .UNINDENT .INDENT 0.0 .TP .B \-N, \-\-connection\-inactivity\-timeout= Specifies the amount of time that h2load is willing to wait to see activity on a given connection. must be a positive integer, specifying the amount of time to wait. When no timeout value is set (either active or inactive), h2load will keep a connection open indefinitely, waiting for a response. .UNINDENT .INDENT 0.0 .TP .B \-\-timing\-script\-file= Path of a file containing one or more lines separated by EOLs. Each script line is composed of two tab\-separated fields. The first field represents the time offset from the start of execution, expressed as a positive value of milliseconds with microsecond resolution. The second field represents the URI. This option will disable URIs getting from command\-line. If \(aq\-\(aq is given as , script lines will be read from stdin. Script lines are used in order for each client. If \fI\%\-n\fP is given, it must be less than or equal to the number of script lines, larger values are clamped to the number of script lines. If \fI\%\-n\fP is not given, the number of requests will default to the number of script lines. The scheme, host and port defined in the first URI are used solely. Values contained in other URIs, if present, are ignored. Definition of a base URI overrides all scheme, host or port values. \fI\%\-\-timing\-script\-file\fP and \fI\%\-\-rps\fP are mutually exclusive. .UNINDENT .INDENT 0.0 .TP .B \-B, \-\-base\-uri=(|unix:) Specify URI from which the scheme, host and port will be used for all requests. The base URI overrides all values defined either at the command line or inside input files. If argument starts with \(dqunix:\(dq, then the rest of the argument will be treated as UNIX domain socket path. The connection is made through that path instead of TCP. In this case, scheme is inferred from the first URI appeared in the command line or inside input files as usual. .UNINDENT .INDENT 0.0 .TP .B \-\-alpn\-list= Comma delimited list of ALPN protocol identifier sorted in the order of preference. That means most desirable protocol comes first. The parameter must be delimited by a single comma only and any white spaces are treated as a part of protocol string. .sp Default: \fBh2,http/1.1\fP .UNINDENT .INDENT 0.0 .TP .B \-\-h1 Short hand for \fI\%\-\-alpn\-list\fP=http/1.1 \fI\%\-\-no\-tls\-proto\fP=http/1.1, which effectively force http/1.1 for both http and https URI. .UNINDENT .INDENT 0.0 .TP .B \-\-header\-table\-size= Specify decoder header table size. .sp Default: \fB4K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-encoder\-header\-table\-size= Specify encoder header table size. The decoder (server) specifies the maximum dynamic table size it accepts. Then the negotiated dynamic table size is the minimum of this option value and the value which server specified. .sp Default: \fB4K\fP .UNINDENT .INDENT 0.0 .TP .B \-\-log\-file= Write per\-request information to a file as tab\-separated columns: start time as microseconds since epoch; HTTP status code; microseconds until end of response. More columns may be added later. Rows are ordered by end\-of\- response time when using one worker thread, but may appear slightly out of order with multiple threads due to buffering. Status code is \-1 for failed streams. .UNINDENT .INDENT 0.0 .TP .B \-\-qlog\-file\-base= Enable qlog output and specify base file name for qlogs. Qlog is emitted for each connection. For a given base name \(dqbase\(dq, each output file name becomes \(dqbase.M.N.sqlog\(dq where M is worker ID and N is client ID (e.g. \(dqbase.0.3.sqlog\(dq). Only effective in QUIC runs. .UNINDENT .INDENT 0.0 .TP .B \-\-connect\-to=[:] Host and port to connect instead of using the authority in . .UNINDENT .INDENT 0.0 .TP .B \-\-rps= Specify request per second for each client. \fI\%\-\-rps\fP and \fI\%\-\-timing\-script\-file\fP are mutually exclusive. .UNINDENT .INDENT 0.0 .TP .B \-\-groups= Specify the supported groups. .sp Default: \fBX25519:P\-256:P\-384:P\-521\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-udp\-gso Disable UDP GSO. .UNINDENT .INDENT 0.0 .TP .B \-\-max\-udp\-payload\-size= Specify the maximum outgoing UDP datagram payload size. .UNINDENT .INDENT 0.0 .TP .B \-\-ktls Enable ktls. .UNINDENT .INDENT 0.0 .TP .B \-\-sni= Send in TLS SNI, overriding the host name specified in URI. .UNINDENT .INDENT 0.0 .TP .B \-v, \-\-verbose Output debug information. .UNINDENT .INDENT 0.0 .TP .B \-\-version Display version information and exit. .UNINDENT .INDENT 0.0 .TP .B \-h, \-\-help Display this help and exit. .UNINDENT .sp The argument is an integer and an optional unit (e.g., 10K is 10 * 1024). Units are K, M and G (powers of 1024). .sp The argument is an integer and an optional unit (e.g., 1s is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms (hours, minutes, seconds and milliseconds, respectively). If a unit is omitted, a second is used as unit. .SH OUTPUT .INDENT 0.0 .TP .B requests .INDENT 7.0 .TP .B total The number of requests h2load was instructed to make. .TP .B started The number of requests h2load has started. .TP .B done The number of requests completed. .TP .B succeeded The number of requests completed successfully. Only HTTP status code 2xx or 3xx are considered as success. .TP .B failed The number of requests failed, including HTTP level failures (non\-successful HTTP status code). .TP .B errored The number of requests failed, except for HTTP level failures. This is the subset of the number reported in \fBfailed\fP and most likely the network level failures or stream was reset by RST_STREAM. .TP .B timeout The number of requests whose connection timed out before they were completed. This is the subset of the number reported in \fBerrored\fP\&. .UNINDENT .TP .B status codes The number of status code h2load received. .TP .B traffic .INDENT 7.0 .TP .B total The number of bytes received from the server \(dqon the wire\(dq. If requests were made via TLS, this value is the number of decrypted bytes. .TP .B headers The number of response header bytes from the server without decompression. The \fBspace savings\fP shows efficiency of header compression. Let \fBdecompressed(headers)\fP to the number of bytes used for header fields after decompression. The \fBspace savings\fP is calculated by (1 \- \fBheaders\fP / \fBdecompressed(headers)\fP) * 100. For HTTP/1.1, this is usually 0.00%, since it does not have header compression. For HTTP/2, it shows some insightful numbers. .TP .B data The number of response body bytes received from the server. .UNINDENT .TP .B time for request .INDENT 7.0 .TP .B min The minimum time taken for request and response. .TP .B max The maximum time taken for request and response. .TP .B mean The mean time taken for request and response. .TP .B sd The standard deviation of the time taken for request and response. .TP .B +/\- sd The fraction of the number of requests within standard deviation range (mean +/\- sd) against total number of successful requests. .UNINDENT .TP .B time for connect .INDENT 7.0 .TP .B min The minimum time taken to connect to a server including TLS handshake. .TP .B max The maximum time taken to connect to a server including TLS handshake. .TP .B mean The mean time taken to connect to a server including TLS handshake. .TP .B sd The standard deviation of the time taken to connect to a server. .TP .B +/\- sd The fraction of the number of connections within standard deviation range (mean +/\- sd) against total number of successful connections. .UNINDENT .TP .B time for 1st byte (of (decrypted in case of TLS) application data) .INDENT 7.0 .TP .B min The minimum time taken to get 1st byte from a server. .TP .B max The maximum time taken to get 1st byte from a server. .TP .B mean The mean time taken to get 1st byte from a server. .TP .B sd The standard deviation of the time taken to get 1st byte from a server. .TP .B +/\- sd The fraction of the number of connections within standard deviation range (mean +/\- sd) against total number of successful connections. .UNINDENT .TP .B req/s .INDENT 7.0 .TP .B min The minimum request per second among all clients. .TP .B max The maximum request per second among all clients. .TP .B mean The mean request per second among all clients. .TP .B sd The standard deviation of request per second among all clients. server. .TP .B +/\- sd The fraction of the number of connections within standard deviation range (mean +/\- sd) against total number of successful connections. .UNINDENT .UNINDENT .SH FLOW CONTROL .sp h2load sets large flow control window by default, and effectively disables flow control to avoid under utilization of server performance. To set smaller flow control window, use \fI\%\-w\fP and \fI\%\-W\fP options. For example, use \fB\-w16 \-W16\fP to set default window size described in HTTP/2 protocol specification. .SH SEE ALSO .sp \fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT 2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . man/man1/nghttpd.1000064400000012707152464121240007715 0ustar00.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "NGHTTPD" "1" "Oct 25, 2025" "1.68.0" "nghttp2" .SH NAME nghttpd \- HTTP/2 server .SH SYNOPSIS .sp \fBnghttpd\fP [OPTION]... [ ] .SH DESCRIPTION .sp HTTP/2 server .INDENT 0.0 .TP .B Specify listening port number. .UNINDENT .INDENT 0.0 .TP .B Set path to server\(aqs private key. Required unless \fI\%\-\-no\-tls\fP is specified. .UNINDENT .INDENT 0.0 .TP .B Set path to server\(aqs certificate. Required unless \fI\%\-\-no\-tls\fP is specified. .UNINDENT .SH OPTIONS .INDENT 0.0 .TP .B \-a, \-\-address= The address to bind to. If not specified the default IP address determined by getaddrinfo is used. .UNINDENT .INDENT 0.0 .TP .B \-D, \-\-daemon Run in a background. If \fI\%\-D\fP is used, the current working directory is changed to \(aq\fI/\fP\(aq. Therefore if this option is used, \fI\%\-d\fP option must be specified. .UNINDENT .INDENT 0.0 .TP .B \-V, \-\-verify\-client The server sends a client certificate request. If the client did not return a certificate, the handshake is terminated. Currently, this option just requests a client certificate and does not verify it. .UNINDENT .INDENT 0.0 .TP .B \-d, \-\-htdocs= Specify document root. If this option is not specified, the document root is the current working directory. .UNINDENT .INDENT 0.0 .TP .B \-v, \-\-verbose Print debug information such as reception/ transmission of frames and name/value pairs. .UNINDENT .INDENT 0.0 .TP .B \-\-no\-tls Disable SSL/TLS. .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-header\-table\-size= Specify decoder header table size. .UNINDENT .INDENT 0.0 .TP .B \-\-encoder\-header\-table\-size= Specify encoder header table size. The decoder (client) specifies the maximum dynamic table size it accepts. Then the negotiated dynamic table size is the minimum of this option value and the value which client specified. .UNINDENT .INDENT 0.0 .TP .B \-\-color Force colored log output. .UNINDENT .INDENT 0.0 .TP .B \-p, \-\-push== Push resources s when is requested. This option can be used repeatedly to specify multiple push configurations. and s are relative to document root. See \fI\%\-\-htdocs\fP option. Example: \fI\%\-p\fP/=/foo.png \fI\%\-p\fP/doc=/bar.css .UNINDENT .INDENT 0.0 .TP .B \-b, \-\-padding= Add at most bytes to a frame payload as padding. Specify 0 to disable padding. .UNINDENT .INDENT 0.0 .TP .B \-m, \-\-max\-concurrent\-streams= Set the maximum number of the concurrent streams in one HTTP/2 session. .sp Default: \fB100\fP .UNINDENT .INDENT 0.0 .TP .B \-n, \-\-workers= Set the number of worker threads. .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-e, \-\-error\-gzip Make error response gzipped. .UNINDENT .INDENT 0.0 .TP .B \-w, \-\-window\-bits= Sets the stream level initial window size to 2**\-1. .UNINDENT .INDENT 0.0 .TP .B \-W, \-\-connection\-window\-bits= Sets the connection level initial window size to 2**\-1. .UNINDENT .INDENT 0.0 .TP .B \-\-dh\-param\-file= Path to file that contains DH parameters in PEM format. Without this option, DHE cipher suites are not available. .UNINDENT .INDENT 0.0 .TP .B \-\-early\-response Start sending response when request HEADERS is received, rather than complete request is received. .UNINDENT .INDENT 0.0 .TP .B \-\-trailer=
    Add a trailer header to a response.
    must not include pseudo header field (header field name starting with \(aq:\(aq). The trailer is sent only if a response has body part. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq. .UNINDENT .INDENT 0.0 .TP .B \-\-hexdump Display the incoming traffic in hexadecimal (Canonical hex+ASCII display). If SSL/TLS is used, decrypted data are used. .UNINDENT .INDENT 0.0 .TP .B \-\-echo\-upload Send back uploaded content if method is POST or PUT. .UNINDENT .INDENT 0.0 .TP .B \-\-mime\-types\-file= Path to file that contains MIME media types and the extensions that represent them. .sp Default: \fB/etc/mime.types\fP .UNINDENT .INDENT 0.0 .TP .B \-\-no\-content\-length Don\(aqt send content\-length header field. .UNINDENT .INDENT 0.0 .TP .B \-\-groups= Specify the supported groups. .sp Default: \fBX25519:P\-256:P\-384:P\-521\fP .UNINDENT .INDENT 0.0 .TP .B \-\-ktls Enable ktls. .UNINDENT .INDENT 0.0 .TP .B \-\-version Display version information and exit. .UNINDENT .INDENT 0.0 .TP .B \-h, \-\-help Display this help and exit. .UNINDENT .sp The argument is an integer and an optional unit (e.g., 10K is 10 * 1024). Units are K, M and G (powers of 1024). .SH SEE ALSO .sp \fBnghttp(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT 2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. .