�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!doc/ea-libmemcached/AUTHORS000064400000000724152526507750011362 0ustar00Brian Aker, brian@tangent.org -- Client Library, Tools Mark Atwood, -- Tools, Docs Patrick Galbraith, -- C++ Interface Padraig O'Sullivan, -- C++ Interface (current one) Tim Bunce, -- Docs Trond Norbye, trond.norbye@gmail.com -- Binary protocol, Misc Yin Chen, -- Ketama Work Toru Maesaka, dev@torum.net -- Stats analysis Eric Lambert, -- UDP work Monty Taylor, -- Build Releated (Pandora) Mingqiang Zhuang, Schooner Information Technology, Inc. -- Rewrite of memslap doc/ea-libmemcached/THANKS000064400000001166152526507750011226 0ustar00(This is not complete, please send email if I have missed someone.) Eirik A. Nygaard - IO Patch Cal Heldenbrand - Awesome feedback on performance Dustin Sallings - Insight into protocol Tobias Luetke - Performance Feedback Andre Cruz - Help with getting the CRC Hash function to match other connectors Brian Pontz - Hsieh hash Tim Bunce - Perl Driver work and feedback on API Kevin Dalley - Bug Fixes Patrick Galbraith - work on C++ interface Ross McFarland - Idea for sorting servers. Marcelo Fernandez - TCP/IP timeout pieces Yin Chen - Ketama support/weighted support Monty Taylor - Debian Packages, Cleanup work for configure doc/ea-libmemcached/COPYING000064400000003027152526507750011344 0ustar00Software License Agreement (BSD License) Copyright (c) 2012, Data Differential (http://datadifferential.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of TangentOrg nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. doc/ea-libmemcached/README000064400000002665152526507750011200 0ustar00Hi! So what is this? It is a library in C for connecting to memcached servers (http://danga.com/memcached/). It is also a collection of utilities designed to work with memcached. memcat - Copy the value of a key to standard output memflush - Flush the contents of your servers. memrm - Remove a key(s) from the server. memstat - Dump the stats of your servers to standard output memslap - Load generation utility (benchmark!) The library is in production in many locations (upwards to 1000+ nodes). The project has information here: http://libmemcached.org/ Documentation can be found here: http://docs.libmemcached.org/ Want to contribute? If you write more then three good patches, then I will just ask you to commit directly to the tree. I am happy to have additional people work on this project. Please checkout README.FIRST. You will need a C99 compiler in order to compile this library. Currently we actively support Linux, MacOSX, FreeBSD, and Solaris. A Windows port is currently not supported, but one is listed on the homepage that is supported by someone in the community. If you are looking for answers to your questions please check out the mailing list at: http://lists.libmemcached.org/ Subscription information for the libmemcached mailing list can be found there. Please report bugs here: https://bugs.launchpad.net/libmemcached/ You can purchase support from: http://datadifferential.com/ Cheers, -Brian Aker Seattle, WA. doc/ea-libmemcached/TODO000064400000000640152526507750010777 0ustar00- Write a shell application (?) - Fix version in command line tools - Write (more) test cases for all command line tools (!!!) - Write some sort of "default" options bit for tools - More examples using libraries - Doxygen? - implement more connection/hash algo - implement compression - Revisit get() code (look for performance enhancements) - Add support for managing servers for clusters. - Build embedded version doc/ea-libmemcached/NEWS000064400000000016152526507750011003 0ustar00See Changelog man/man1/memstat.1000064400000004514152526507750007731 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMSTAT" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memstat \- libmemcached Documentation . .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 .. . .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 .. .sp memstat \- Display the operating status of a single or group of memcached servers .SH SYNOPSIS .sp memstat [options] .SH DESCRIPTION .sp \fBmemstat\fP dumps the state of memcached(1) servers. It displays all data to stdout. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(aqMEMCACHED_SERVERS, \-\-args\(aq .UNINDENT .sp which can be used to specify the "argument" sent to the stats command (ie slab, size, items, etc..). .sp For a full list of operations run the tool with: .INDENT 0.0 .TP .B \-\-help .UNINDENT .INDENT 0.0 .TP .B \-\-analyze .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memexist.1000064400000004375152526507750010117 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMEXIST" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memexist \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memexist [options] [key] .SH DESCRIPTION .sp \fBmemexist\fP checks for the existance of a key within a cluster. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp If you do not specify either these, the final value in the command line list is the name of a server(s). .sp For a full list of operations run the tool with the option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memflush.1000064400000004432152526507750010076 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMFLUSH" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memflush \- libmemcached Documentation . .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 .. . .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 .. .sp Reset a server or list of servers .SH SYNOPSIS .sp memflush [options] .SH DESCRIPTION .sp \fBmemflush\fP resets the contents of memcached(1) servers. This means that all data in the specified servers will be deleted. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp For a full list of operations run the tool with option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .sp Mark Atwood <\fI\%mark@fallenpegasus.com\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memtouch.1000064400000004354152526507750010102 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMTOUCH" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memtouch \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memtouch [options] key .SH DESCRIPTION .sp \fBmemtouch\fP does a "touch" on the specified key. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp If you do not specify either these, the final value in the command line list is the name of a server(s). .sp For a full list of operations run the tool with the option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memrm.1000064400000004373152526507750007377 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMRM" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memrm \- libmemcached Documentation . .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 .. . .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 .. .sp memrm \- Remove a key(s) from a collection of memcached servers .SH SYNOPSIS .sp memrm [options] [key] .SH DESCRIPTION .sp \fBmemrm\fP removes items, specified by key, from memcached(1) servers. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp For a full list of operations run the tool with the .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .sp Mark Atwood, <\fI\%mark@fallenpegasus.com\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memcp.1000064400000004743152526507750007364 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMCP" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memcp \- libmemcached Documentation . .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 .. . .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 .. .sp Copies files to a collection of memcached servers .SH SYNOPSIS .sp memcp [options] [file] [server] .SH DESCRIPTION .sp \fBmemcp\fP copies one or more files into memcached(1) servers. It is similar to the standard UNIX cp(1) command. .sp The key names will be the names of the files, without any directory path. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp If you do not specify either these, the final value in the command line list is the name of a server(s). .sp For a full list of operations run the tool with the option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .sp Mark Atwood, <\fI\%mark@fallenpegasus.com\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memping.1000064400000004423152526507750007712 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMPING" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memping \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memping [options] [server] .SH DESCRIPTION .sp \fBmemping\fP can be used to ping a memcached server to see if it is taking connections. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp If you do not specify either these, the final value in the command line list is the name of a server(s). .sp For a full list of operations run the tool with the option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memerror.1000064400000004061152526507750010104 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMERROR" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memerror \- libmemcached Documentation . .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 .. . .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 .. .sp Translates a memcached error code into a string .SH SYNOPSIS .sp memerror [options] [error code] .SH DESCRIPTION .sp \fBmemerror\fP translates an error code from libmemcached(3) into a human readable string. .SH OPTIONS .sp For a full list of operations run the tool with option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more infoerroration please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memaslap.1000064400000102443152526507750010056 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMASLAP" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memaslap \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memaslap [options] .INDENT 0.0 .TP .B \-\-help .UNINDENT .INDENT 0.0 .TP .B MEMCACHED_SERVERS .UNINDENT .SH DESCRIPTION .sp \fBmemaslap\fP is a load generation and benchmark tool for memcached servers. It generates configurable workload such as threads, concurrencies, connections, run time, overwrite, miss rate, key size, value size, get/set proportion, expected throughput, and so on. Furthermore, it also testss data verification, expire\-time verification, UDP, binary protocol, facebook test, replication test, multi\-get and reconnection, etc. .sp Memaslap manages network connections like memcached with libevent. Each thread of memaslap is bound with a CPU core, all the threads don\(aqt communicate with each other, and there are several socket connections in each thread. Each connection keeps key size distribution, value size distribution, and command distribution by itself. .sp You can specify servers via the \fImemslap \-\-servers\fP option or via the environment variable \fI\%MEMCACHED_SERVERS\fP\&. .SH FEATURES .sp Memslap is developed to for the following purposes: .sp Manages network connections with libevent asynchronously. .sp Set both TCP and UDP up to use non\-blocking IO. .sp Improves parallelism: higher performance in multi\-threads environments. .sp Improves time efficiency: faster processing speed. .sp Generates key and value more efficiently; key size distribution and value size distribution are configurable. .sp Supports get, multi\-get, and set commands; command distribution is configurable. .sp Supports controllable miss rate and overwrite rate. .sp Supports data and expire\-time verification. .sp Supports dumping statistic information periodically. .sp Supports thousands of TCP connections. .sp Supports binary protocol. .sp Supports facebook test (set with TCP and multi\-get with UDP) and replication test. .SH DETAILS .SS Effective implementation of network. .sp For memaslap, both TCP and UDP use non\-blocking network IO. All the network events are managed by libevent as memcached. The network module of memaslap is similar to memcached. Libevent can ensure memaslap can handle network very efficiently. .SS Effective implementation of multi\-threads and concurrency .sp Memslap has the similar implementation of multi\-threads to memcached. Memslap creates one or more self\-governed threads; each thread is bound with one CPU core if the system testss setting CPU core affinity. .sp In addition, each thread has a libevent to manage the events of the network; each thread has one or more self\-governed concurrencies; and each concurrency has one or more socket connections. All the concurrencies don’t communicate with each other even though they are in the same thread. .sp Memslap can create thousands of socket connections, and each concurrency has tens of socket connections. Each concurrency randomly or sequentially selects one socket connection from its socket connection pool to run, so memaslap can ensure each concurrency handles one socket connection at any given time. Users can specify the number of concurrency and socket connections of each concurrency according to their expected workload. .SS Effective implementation of generating key and value .sp In order to improve time efficiency and space efficiency, memaslap creates a random characters table with 10M characters. All the suffixes of keys and values are generated from this random characters table. .sp Memslap uses the offset in the character table and the length of the string to identify a string. It can save much memory. Each key contains two parts, a prefix and a suffix. The prefix is an uint64_t, 8 bytes. In order to verify the data set before, memaslap need to ensure each key is unique, so it uses the prefix to identify a key. The prefix cannot include illegal characters, such as ‘r’, ‘n’, ‘0’ and ‘ ‘. And memaslap has an algorithm to ensure that. .sp Memslap doesn’t generate all the objects (key\-value pairs) at the beginning. It only generates enough objects to fill the task window (default 10K objects) of each concurrency. Each object has the following basic information, key prefix, key suffix offset in the character table, key length, value offset in the character table, and value length. .sp In the work process, each concurrency sequentially or randomly selects an object from the window to do set operation or get operation. At the same time, each concurrency kicks objects out of its window and adds new object into it. .SS Simple but useful task scheduling .sp Memslap uses libevent to schedule all the concurrencies of threads, and each concurrency schedules tasks based on the local task window. Memslap assumes that if each concurrency keeps the same key distribution, value distribution and commands distribution, from outside, memaslap keeps all the distribution as a whole. Each task window includes a lot of objects, each object stores its basic information, such as key, value, expire time, and so on. At any time, all the objects in the window keep the same and fixed key and value distribution. If an object is overwritten, the value of the object will be updated. Memslap verifies the data or expire\-time according to the object information stored in the task window. .sp Libevent selects which concurrency to handle based on a specific network event. Then the concurrency selects which command (get or set) to operate based on the command distribution. If it needs to kick out an old object and add a new object, in order to keep the same key and value distribution, the new object must have the same key length and value length. .sp If memcached server has two cache layers (memory and SSD), running memaslap with different window sizes can get different cache miss rates. If memaslap adds enough objects into the windows at the beginning, and the cache of memcached cannot store all the objects initialized, then memaslap will get some objects from the second cache layer. It causes the first cache layer to miss. So the user can specify the window size to get the expected miss rate of the first cache layer. .SS Useful implementation of multi\-servers , UDP, TCP, multi\-get and binary protocol .sp Because each thread is self\-governed, memaslap can assign different threads to handle different memcached servers. This is just one of the ways in which memaslap tests multiple servers. The only limitation is that the number of servers cannot be greater than the number of threads. The other way to test multiple servers is for replication test. Each concurrency has one socket connection to each memcached server. For the implementation, memaslap can set some objects to one memcached server, and get these objects from the other servers. .sp By default, Memslap does single get. If the user specifies multi\-get option, memaslap will collect enough get commands and pack and send the commands together. .sp Memslap testss both the ASCII protocol and binary protocol, but it runs on the ASCII protocol by default. Memslap by default runs on the TCP protocol, but it also tests UDP. Because UDP is unreliable, dropped packages and out\-of\-order packages may occur. Memslap creates a memory buffer to handle these problems. Memslap tries to read all the response data of one command from the server and reorders the response data. If some packages get lost, the waiting timeout mechanism can ensure half\-baked packages will be discarded and the next command will be sent. .SH USAGE .sp Below are some usage samples: .sp memaslap \-s 127.0.0.1:11211 \-S 5s .sp memaslap \-s 127.0.0.1:11211 \-t 2m \-v 0.2 \-e 0.05 \-b .sp memaslap \-s 127.0.0.1:11211 \-F config \-t 2m \-w 40k \-S 20s \-o 0.2 .sp memaslap \-s 127.0.0.1:11211 \-F config \-t 2m \-T 4 \-c 128 \-d 20 \-P 40k .sp memaslap \-s 127.0.0.1:11211 \-F config \-t 2m \-d 50 \-a \-n 40 .sp memaslap \-s 127.0.0.1:11211,127.0.0.1:11212 \-F config \-t 2m .sp memaslap \-s 127.0.0.1:11211,127.0.0.1:11212 \-F config \-t 2m \-p 2 .sp The user must specify one server at least to run memaslap. The rest of the parameters have default values, as shown below: .sp Thread number = 1 Concurrency = 16 .sp Run time = 600 seconds Configuration file = NULL .sp Key size = 64 Value size = 1024 .sp Get/set = 9:1 Window size = 10k .sp Execute number = 0 Single get = true .sp Multi\-get = false Number of sockets of each concurrency = 1 .sp Reconnect = false Data verification = false .sp Expire\-time verification = false ASCII protocol = true .sp Binary protocol = false Dumping statistic information .sp periodically = false .sp Overwrite proportion = 0% UDP = false .sp TCP = true Limit throughput = false .sp Facebook test = false Replication test = false .SS Key size, value size and command distribution. .sp All the distributions are read from the configuration file specified by user with “—cfg_cmd” option. If the user does not specify a configuration file, memaslap will run with the default distribution (key size = 64, value size = 1024, get/set = 9:1). For information on how to edit the configuration file, refer to the “Configuration File” section. .sp The minimum key size is 16 bytes; the maximum key size is 250 bytes. The precision of proportion is 0.001. The proportion of distribution will be rounded to 3 decimal places. .sp The minimum value size is 1 bytes; the maximum value size is 1M bytes. The precision of proportion is 0.001. The proportion of distribution will be rounded to 3 decimal places. Currently, memaslap only testss set and get commands. And it testss 100% set and 100% get. For 100% get, it will preset some objects to the server. .SS Multi\-thread and concurrency .sp The high performance of memaslap benefits from the special schedule of thread and concurrency. It’s important to specify the proper number of them. The default number of threads is 1; the default number of concurrency is 16. The user can use “—threads” and “\-\-concurrency” to specify these variables. .sp If the system tests setting CPU affinity and the number of threads specified by the user is greater than 1, memaslap will try to bind each thread to a different CPU core. So if you want to get the best performance memaslap, it is better to specify the number of thread equal to the number of CPU cores. The number of threads specified by the user can also be less or greater than the number of CPU cores. Because of the limitation of implementation, the number of concurrencies could be the multiple of the number of threads. .INDENT 0.0 .IP 1. 3 For 8 CPU cores system .UNINDENT .sp For example: .sp \-\-threads=2 \-\-concurrency=128 .sp \-\-threads=8 \-\-concurrency=128 .sp \-\-threads=8 \-\-concurrency=256 .sp \-\-threads=12 \-\-concurrency=144 .INDENT 0.0 .IP 2. 3 For 16 CPU cores system .UNINDENT .sp For example: .sp \-\-threads=8 \-\-concurrency=128 .sp \-\-threads=16 \-\-concurrency=256 .sp \-\-threads=16 \-\-concurrency=512 .sp \-\-threads=24 \-\-concurrency=288 .sp The memaslap performs very well, when used to test the performance of memcached servers. Most of the time, the bottleneck is the network or the server. If for some reason the user wants to limit the performance of memaslap, there are two ways to do this: .sp Decrease the number of threads and concurrencies. Use the option “\-\-tps” that memaslap provides to limit the throughput. This option allows the user to get the expected throughput. For example, assume that the maximum throughput is 50 kops/s for a specific configuration, you can specify the throughput equal to or less than the maximum throughput using “\-\-tps” option. .SS Window size .sp Most of the time, the user does not need to specify the window size. The default window size is 10k. For Schooner Memcached, the user can specify different window sizes to get different cache miss rates based on the test case. Memslap testss cache miss rate between 0% and 100%. If you use this utility to test the performance of Schooner Memcached, you can specify a proper window size to get the expected cache miss rate. The formula for calculating window size is as follows: .sp Assume that the key size is 128 bytes, and the value size is 2048 bytes, and concurrency=128. .sp 1. Small cache cache_size=1M, 100% cache miss (all data get from SSD). win_size=10k .INDENT 0.0 .IP 2. 3 cache_size=4G .UNINDENT .sp (1). cache miss rate 0% .sp win_size=8k .sp (2). cache miss rate 5% .sp win_size=11k .INDENT 0.0 .IP 3. 3 cache_size=16G .UNINDENT .sp (1). cache miss rate 0% .sp win_size=32k .sp (2). cache miss .sp rate 5% .sp win_size=46k .sp The formula for calculating window size for cache miss rate 0%: .sp cache_size / concurrency / (key_size + value_size) * 0.5 .sp The formula for calculating window size for cache miss rate 5%: .sp cache_size / concurrency / (key_size + value_size) * 0.7 .SS Verification .sp Memslap testss both data verification and expire\-time verification. The user can use "\-\-verify=" or "\-v" to specify the proportion of data verification. In theory, it testss 100% data verification. The user can use "\-\-exp_verify=" or "\-e" to specify the proportion of expire\-time verification. In theory, it testss 100% expire\-time verification. Specify the "\-\-verbose" options to get more detailed error information. .sp For example: \-\-exp_verify=0.01 –verify=0.1 , it means that 1% of the objects set with expire\-time, 10% of the objects gotten will be verified. If the objects are gotten, memaslap will verify the expire\-time and value. .SS multi\-servers and multi\-config .sp Memslap testss multi\-servers based on self\-governed thread. There is a limitation that the number of servers cannot be greater than the number of threads. Memslap assigns one thread to handle one server at least. The user can use the "\-\-servers=" or "\-s" option to specify multi\-servers. .sp For example: .sp \-\-servers=10.1.1.1:11211,10.1.1.2:11212,10.1.1.3:11213 \-\-threads=6 \-\-concurrency=36 .sp The above command means that there are 6 threads, with each thread having 6 concurrencies and that threads 0 and 3 handle server 0 (10.1.1.1); threads 1 and 4 handle server 1 (10.1.1.2); and thread 2 and 5 handle server 2 (10.1.1.3). .sp All the threads and concurrencies in memaslap are self\-governed. .sp So is memaslap. The user can start up several memaslap instances. The user can run memaslap on different client machines to communicate with the same memcached server at the same. It is recommended that the user start different memaslap on different machines using the same configuration. .SS Run with execute number mode or time mode .sp The default memaslap runs with time mode. The default run time is 10 minutes. If it times out, memaslap will exit. Do not specify both execute number mode and time mode at the same time; just specify one instead. .sp For example: .sp \-\-time=30s (It means the test will run 30 seconds.) .sp \-\-execute_number=100000 (It means that after running 100000 commands, the test will exit.) .SS Dump statistic information periodically. .sp The user can use "\-\-stat_freq=" or "\-S" to specify the frequency. .sp For example: .sp \-\-stat_freq=20s .sp Memslap will dump the statistics of the commands (get and set) at the frequency of every 20 seconds. .sp For more information on the format of dumping statistic information, refer to “Format of Output” section. .SS Multi\-get .sp The user can use "\-\-division=" or "\-d" to specify multi\-get keys count. Memslap by default does single get with TCP. Memslap also testss data verification and expire\-time verification for multi\-get. .sp Memslap testss multi\-get with both TCP and UDP. Because of the different implementation of the ASCII protocol and binary protocol, there are some differences between the two. For the ASCII protocol, memaslap sends one “multi\-get” to the server once. For the binary protocol, memaslap sends several single get commands together as “multi\-get” to the server. .SS UDP and TCP .sp Memslap testss both UDP and TCP. For TCP, memaslap does not reconnect the memcached server if socket connections are lost. If all the socket connections are lost or memcached server crashes, memaslap will exit. If the user specifies the “\-\-reconnect” option when socket connections are lost, it will reconnect them. .sp User can use “\-\-udp” to enable the UDP feature, but UDP comes with some limitations: .sp UDP cannot set data more than 1400 bytes. .sp UDP is not testsed by the binary protocol because the binary protocol of memcached does not tests that. .sp UDP doesn’t tests reconnection. .SS Facebook test .sp Set data with TCP and multi\-get with UDP. Specify the following options: .sp "\-\-facebook \-\-division=50" .sp If you want to create thousands of TCP connections, specify the .sp "\-\-conn_sock=" option. .sp For example: \-\-facebook \-\-division=50 \-\-conn_sock=200 .sp The above command means that memaslap will do facebook test, each concurrency has 200 socket TCP connections and one UDP socket. .sp Memslap sets objects with the TCP socket, and multi\-gets 50 objects once with the UDP socket. .sp If you specify "\-\-division=50", the key size must be less that 25 bytes because the UDP packet size is 1400 bytes. .SS Replication test .sp For replication test, the user must specify at least two memcached servers. The user can use “—rep_write=” option to enable feature. .sp For example: .sp \-\-servers=10.1.1.1:11211,10.1.1.2:11212 –rep_write=2 .sp The above command means that there are 2 replication memcached servers, memaslap will set objects to both server 0 and server 1, get objects which are set to server 0 before from server 1, and also get objects which are set to server 1 before from server 0. If server 0 crashes, memaslap will only get objects from server 1. If server 0 comes back to life again, memaslap will reconnect server 0. If both server 0 and server 1 crash, memaslap will exit. .SS Supports thousands of TCP connections .sp Start memaslap with "\-\-conn_sock=" or "\-n" to enable this feature. Make sure that your system can tests opening thousands of files and creating thousands of sockets. However, this feature does not tests reconnection if sockets disconnect. .sp For example: .sp \-\-threads=8 \-\-concurrency=128 \-\-conn_sock=128 .sp The above command means that memaslap starts up 8 threads, each thread has 16 concurrencies, each concurrency has 128 TCP socket connections, and the total number of TCP socket connections is 128 * 128 = 16384. .SS Supports binary protocol .sp Start memaslap with "\-\-binary" or "\-B" options to enable this feature. It testss all the above features except UDP, because the latest memcached 1.3.3 does not implement binary UDP protocol. .sp For example: .sp \-\-binary .sp Since memcached 1.3.3 doesn\(aqt implement binary UDP protocol, memaslap does not tests UDP. In addition, memcached 1.3.3 does not tests multi\-get. If you specify "\-\-division=50" option, it just sends 50 get commands together as “mulit\-get” to the server. .SH CONFIGURATION FILE .sp This section describes the format of the configuration file. By default when no configuration file is specified memaslap reads the default one located at ~/.memaslap.cnf. .sp Below is a sample configuration file: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- #comments should start with \(aq#\(aq #key #start_len end_len proportion # #key length range from start_len to end_len #start_len must be equal to or greater than 16 #end_len must be equal to or less than 250 #start_len must be equal to or greater than end_len #memaslap will generate keys according to the key range #proportion: indicates keys generated from one range accounts for the total generated keys # #example1: key range 16~100 accounts for 80% # key range 101~200 accounts for 10% # key range 201~250 accounts for 10% # total should be 1 (0.8+0.1+0.1 = 1) # # 16 100 0.8 # 101 200 0.1 # 201 249 0.1 # #example2: all keys length are 128 bytes # # 128 128 1 key 128 128 1 #value #start_len end_len proportion # #value length range from start_len to end_len #start_len must be equal to or greater than 1 #end_len must be equal to or less than 1M #start_len must be equal to or greater than end_len #memaslap will generate values according to the value range #proportion: indicates values generated from one range accounts for the total generated values # #example1: value range 1~1000 accounts for 80% # value range 1001~10000 accounts for 10% # value range 10001~100000 accounts for 10% # total should be 1 (0.8+0.1+0.1 = 1) # # 1 1000 0.8 # 1001 10000 0.1 # 10001 100000 0.1 # #example2: all value length are 128 bytes # # 128 128 1 value 2048 2048 1 #cmd #cmd_type cmd_proportion # #currently memaslap only testss get and set command. # #cmd_type #set 0 #get 1 # #example: set command accounts for 50% # get command accounts for 50% # total should be 1 (0.5+0.5 = 1) # # cmd # 0 0.5 # 1 0.5 cmd 0 0.1 1.0 0.9 .ft P .fi .UNINDENT .UNINDENT .SH FORMAT OF OUTPUT .sp At the beginning, memaslap displays some configuration information as follows: .sp servers : 127.0.0.1:11211 .sp threads count: 1 .sp concurrency: 16 .sp run time: 20s .sp windows size: 10k .sp set proportion: set_prop=0.10 .sp get proportion: get_prop=0.90 .SS Where .sp servers : "servers" .INDENT 0.0 .INDENT 3.5 The servers used by memaslap. .UNINDENT .UNINDENT .sp threads count .INDENT 0.0 .INDENT 3.5 The number of threads memaslap runs with. .UNINDENT .UNINDENT .sp concurrency .INDENT 0.0 .INDENT 3.5 The number of concurrencies memaslap runs with. .UNINDENT .UNINDENT .sp run time .INDENT 0.0 .INDENT 3.5 How long to run memaslap. .UNINDENT .UNINDENT .sp windows size .INDENT 0.0 .INDENT 3.5 The task window size of each concurrency. .UNINDENT .UNINDENT .sp set proportion .INDENT 0.0 .INDENT 3.5 The proportion of set command. .UNINDENT .UNINDENT .sp get proportion .INDENT 0.0 .INDENT 3.5 The proportion of get command. .UNINDENT .UNINDENT .sp The output of dynamic statistics is something like this: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- Get Statistics Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) Avg(us) Std_dev Geo_dist Period 5 345826 69165 65.3 0 27 2198 203 95.43 177.29 Global 20 1257935 62896 71.8 0 26 3791 224 117.79 192.60 Set Statistics Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) Avg(us) Std_dev Geo_dist Period 5 38425 7685 7.3 0 42 628 240 88.05 220.21 Global 20 139780 6989 8.0 0 37 3790 253 117.93 224.83 Total Statistics Type Time(s) Ops TPS(ops/s) Net(M/s) Get_miss Min(us) Max(us) Avg(us) Std_dev Geo_dist Period 5 384252 76850 72.5 0 27 2198 207 94.72 181.18 Global 20 1397720 69886 79.7 0 26 3791 227 117.93 195.60 \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .ft P .fi .UNINDENT .UNINDENT .SS Where .sp Get Statistics .INDENT 0.0 .INDENT 3.5 Statistics information of get command .UNINDENT .UNINDENT .sp Set Statistics .INDENT 0.0 .INDENT 3.5 Statistics information of set command .UNINDENT .UNINDENT .sp Total Statistics .INDENT 0.0 .INDENT 3.5 Statistics information of both get and set command .UNINDENT .UNINDENT .sp Period .INDENT 0.0 .INDENT 3.5 Result within a period .UNINDENT .UNINDENT .sp Global .INDENT 0.0 .INDENT 3.5 Accumulated results .UNINDENT .UNINDENT .sp Ops .INDENT 0.0 .INDENT 3.5 Total operations .UNINDENT .UNINDENT .sp TPS .INDENT 0.0 .INDENT 3.5 Throughput, operations/second .UNINDENT .UNINDENT .sp Net .INDENT 0.0 .INDENT 3.5 The rate of network .UNINDENT .UNINDENT .sp Get_miss .INDENT 0.0 .INDENT 3.5 How many objects can’t be gotten .UNINDENT .UNINDENT .sp Min .INDENT 0.0 .INDENT 3.5 The minimum response time .UNINDENT .UNINDENT .sp Max .INDENT 0.0 .INDENT 3.5 The maximum response time .UNINDENT .UNINDENT .sp Avg: .INDENT 0.0 .INDENT 3.5 The average response time .UNINDENT .UNINDENT .sp Std_dev .INDENT 0.0 .INDENT 3.5 Standard deviation of response time .UNINDENT .UNINDENT .sp Geo_dist .INDENT 0.0 .INDENT 3.5 Geometric distribution based on natural exponential function .UNINDENT .UNINDENT .sp At the end, memaslap will output something like this: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- Get Statistics (1257956 events) Min: 26 Max: 3791 Avg: 224 Geo: 192.60 Std: 116.23 Log2 Dist: 4: 0 10 84490 215345 8: 484890 459823 12543 824 12: 31 Set Statistics (139782 events) Min: 37 Max: 3790 Avg: 253 Geo: 224.84 Std: 116.83 Log2 Dist: 4: 0 0 4200 16988 8: 50784 65574 2064 167 12: 5 Total Statistics (1397738 events) Min: 26 Max: 3791 Avg: 227 Geo: 195.60 Std: 116.60 Log2 Dist: 4: 0 10 88690 232333 8: 535674 525397 14607 991 12: 36 cmd_get: 1257969 cmd_set: 139785 get_misses: 0 verify_misses: 0 verify_failed: 0 expired_get: 0 unexpired_unget: 0 written_bytes: 242516030 read_bytes: 1003702556 object_bytes: 152086080 packet_disorder: 0 packet_drop: 0 udp_timeout: 0 Run time: 20.0s Ops: 1397754 TPS: 69817 Net_rate: 59.4M/s \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .ft P .fi .UNINDENT .UNINDENT .SS Where .sp Get Statistics .INDENT 0.0 .INDENT 3.5 Get statistics of response time .UNINDENT .UNINDENT .sp Set Statistics .INDENT 0.0 .INDENT 3.5 Set statistics of response time .UNINDENT .UNINDENT .sp Total Statistics .INDENT 0.0 .INDENT 3.5 Both get and set statistics of response time .UNINDENT .UNINDENT .sp Min .INDENT 0.0 .INDENT 3.5 The accumulated and minimum response time .UNINDENT .UNINDENT .sp Max .INDENT 0.0 .INDENT 3.5 The accumulated and maximum response time .UNINDENT .UNINDENT .sp Avg .INDENT 0.0 .INDENT 3.5 The accumulated and average response time .UNINDENT .UNINDENT .sp Std .INDENT 0.0 .INDENT 3.5 Standard deviation of response time .UNINDENT .UNINDENT .sp Log2 Dist .INDENT 0.0 .INDENT 3.5 Geometric distribution based on logarithm 2 .UNINDENT .UNINDENT .sp cmd_get .INDENT 0.0 .INDENT 3.5 Total get commands done .UNINDENT .UNINDENT .sp cmd_set .INDENT 0.0 .INDENT 3.5 Total set commands done .UNINDENT .UNINDENT .sp get_misses .INDENT 0.0 .INDENT 3.5 How many objects can’t be gotten from server .UNINDENT .UNINDENT .sp verify_misses .INDENT 0.0 .INDENT 3.5 How many objects need to verify but can’t get them .UNINDENT .UNINDENT .sp verify_failed .INDENT 0.0 .INDENT 3.5 How many objects with insistent value .UNINDENT .UNINDENT .sp expired_get .INDENT 0.0 .INDENT 3.5 How many objects are expired but we get them .UNINDENT .UNINDENT .sp unexpired_unget .INDENT 0.0 .INDENT 3.5 How many objects are unexpired but we can’t get them .UNINDENT .UNINDENT .sp written_bytes .INDENT 0.0 .INDENT 3.5 Total written bytes .UNINDENT .UNINDENT .sp read_bytes .INDENT 0.0 .INDENT 3.5 Total read bytes .UNINDENT .UNINDENT .sp object_bytes .INDENT 0.0 .INDENT 3.5 Total object bytes .UNINDENT .UNINDENT .sp packet_disorder .INDENT 0.0 .INDENT 3.5 How many UDP packages are disorder .UNINDENT .UNINDENT .sp packet_drop .INDENT 0.0 .INDENT 3.5 How many UDP packages are lost .UNINDENT .UNINDENT .sp udp_timeout .INDENT 0.0 .INDENT 3.5 How many times UDP time out happen .UNINDENT .UNINDENT .sp Run time .INDENT 0.0 .INDENT 3.5 Total run time .UNINDENT .UNINDENT .sp Ops .INDENT 0.0 .INDENT 3.5 Total operations .UNINDENT .UNINDENT .sp TPS .INDENT 0.0 .INDENT 3.5 Throughput, operations/second .UNINDENT .UNINDENT .sp Net_rate .INDENT 0.0 .INDENT 3.5 The average rate of network .UNINDENT .UNINDENT .SH OPTIONS .INDENT 0.0 .TP .B \-s, \-\-servers= List one or more servers to connect. Servers count must be less than threads count. e.g.: \-\-servers=localhost:1234,localhost:11211 .TP .B \-T, \-\-threads= Number of threads to startup, better equal to CPU numbers. Default 8. .TP .B \-c, \-\-concurrency= Number of concurrency to simulate with load. Default 128. .TP .B \-n, \-\-conn_sock= Number of TCP socks per concurrency. Default 1. .TP .B \-x, \-\-execute_number= Number of operations(get and set) to execute for the given test. Default 1000000. .TP .B \-t, \-\-time= How long the test to run, suffix: s\-seconds, m\-minutes, h\-hours, d\-days e.g.: \-\-time=2h. .TP .B \-F, \-\-cfg_cmd= Load the configure file to get command,key and value distribution list. .TP .B \-w, \-\-win_size= Task window size of each concurrency, suffix: K, M e.g.: \-\-win_size=10k. Default 10k. .TP .B \-X, \-\-fixed_size= Fixed length of value. .TP .B \-v, \-\-verify= The proportion of date verification, e.g.: \-\-verify=0.01 .TP .B \-d, \-\-division= Number of keys to multi\-get once. Default 1, means single get. .TP .B \-S, \-\-stat_freq= Frequency of dumping statistic information. suffix: s\-seconds, m\-minutes, e.g.: \-\-resp_freq=10s. .TP .B \-e, \-\-exp_verify= The proportion of objects with expire time, e.g.: \-\-exp_verify=0.01. Default no object with expire time .TP .B \-o, \-\-overwrite= The proportion of objects need overwrite, e.g.: \-\-overwrite=0.01. Default never overwrite object. .UNINDENT .INDENT 0.0 .TP .B \-R\fP,\fB \-\-reconnect Reconnect tests, when connection is closed it will be reconnected. .TP .B \-U\fP,\fB \-\-udp UDP tests, default memaslap uses TCP, TCP port and UDP port of server must be same. .TP .B \-a\fP,\fB \-\-facebook Whether it enables facebook test feature, set with TCP and multi\-get with UDP. .TP .B \-B\fP,\fB \-\-binary Whether it enables binary protocol. Default with ASCII protocol. .UNINDENT .INDENT 0.0 .TP .B \-P, \-\-tps= Expected throughput, suffix: K, e.g.: \-\-tps=10k. .TP .B \-p, \-\-rep_write= The first nth servers can write data, e.g.: \-\-rep_write=2. .UNINDENT .INDENT 0.0 .TP .B \-b\fP,\fB \-\-verbose Whether it outputs detailed information when verification fails. .TP .B \-h\fP,\fB \-\-help Display this message and then exit. .TP .B \-V\fP,\fB \-\-version Display the version of the application and then exit. .UNINDENT .SH EXAMPLES .sp memaslap \-s 127.0.0.1:11211 \-S 5s .sp memaslap \-s 127.0.0.1:11211 \-t 2m \-v 0.2 \-e 0.05 \-b .sp memaslap \-s 127.0.0.1:11211 \-F config \-t 2m \-w 40k \-S 20s \-o 0.2 .sp memaslap \-s 127.0.0.1:11211 \-F config \-t 2m \-T 4 \-c 128 \-d 20 \-P 40k .sp memaslap \-s 127.0.0.1:11211 \-F config \-t 2m \-d 50 \-a \-n 40 .sp memaslap \-s 127.0.0.1:11211,127.0.0.1:11212 \-F config \-t 2m .sp memaslap \-s 127.0.0.1:11211,127.0.0.1:11212 \-F config \-t 2m \-p 2 .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHORS .sp Mingqiang Zhuang <\fI\%mingqiangzhuang@hengtiansoft.com\fP> (Schooner Technolgy) Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memcat.1000064400000004547152526507750007533 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMCAT" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memcat \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memcat [options] key .sp Copy a set of keys to stdout .SH DESCRIPTION .sp \fBmemcat\fP outputs to stdout the value a single or multiple set of keys stored in a memcached(1) server. If any key is not found an error is returned. .sp It is similar to the standard UNIX cat(1) utility. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp For a full list of operations run the tool with the option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .sp Mark Atwood <\fI\%mark@fallenpegasus.com\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memcapable.1000064400000005124152526507750010343 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMCAPABLE" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memcapable \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memcapable [options] .SH DESCRIPTION .sp \fBmemcapable\fP connects to the specified memcached server and tries to determine its capabilities by running the various commands and verifying the response. .SH LIMITATIONS .sp The current version of memcapable will only verify the binary protocol. .SH OPTIONS .INDENT 0.0 .TP .B \-h hostname .UNINDENT .sp Specify the hostname to connect to. The default is \fIlocalhost\fP .INDENT 0.0 .TP .B \-p port .UNINDENT .sp Specify the port number to connect to. The default is \fI11211\fP .INDENT 0.0 .TP .B \-c .UNINDENT .sp Generate a coredump when it detects an error from the server. .INDENT 0.0 .TP .B \-v .UNINDENT .sp Print out the comparison when it detects an error from the server. .INDENT 0.0 .TP .B \-t n .UNINDENT .sp Set the timeout from an IO operation to/from the server to \fIn\fP seconds. .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Trond Norbye, <\fI\%trond.norbye@gmail.com\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memdump.1000064400000004162152526507750007722 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMDUMP" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memdump \- libmemcached Documentation . .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 .. . .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 .. .sp Dump a list of keys from a server. .SH SYNOPSIS .sp memdump [options] .SH DESCRIPTION .sp \fBmemdump\fP dumps a list of "keys" from all servers that it is told to fetch from. Because memcached does not guarentee to provide all keys it is not possible to get a complete "dump". .SH OPTIONS .sp For a full list of operations run the tool with option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memparse.1000064400000004025152526507750010065 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMPARSE" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memparse \- libmemcached Documentation . .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 .. . .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 .. .sp Copies files to a collection of memcached servers .SH SYNOPSIS .sp memparse [options] "option string" .SH DESCRIPTION .sp \fBmemparse\fP can be used to validate an option string. .SH OPTIONS .sp For a full list of operations run the tool with the option: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \fI\%http://libmemcached.org/\fP .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . man/man1/memslap.1000064400000004557152526507750007724 0ustar00.\" Man page generated from reStructuredText. . .TH "MEMSLAP" "1" "February 09, 2014" "1.0.18" "libmemcached" .SH NAME memslap \- libmemcached Documentation . .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 .. . .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 .. .SH SYNOPSIS .sp memslap [options] .SH DESCRIPTION .sp \fBmemslap\fP is a load generation and benchmark tool for memcached(1) servers. It generates configurable workload such as threads, concurrencies, connections, run time, overwrite, miss rate, key size, value size, get/set proportion, expected throughput, and so on. .SH OPTIONS .sp You can specify servers via the option: .INDENT 0.0 .TP .B \-\-servers .UNINDENT .sp or via the environment variable: .INDENT 0.0 .TP .B \(gaMEMCACHED_SERVERS\(ga .UNINDENT .sp For a full list of operations run the tool with: .INDENT 0.0 .TP .B \-\-help .UNINDENT .SH HOME .sp To find out more information please check: \(aq\fI\%http://libmemcached.org/\fP <\fI\%http://libmemcached.org/\fP>\(aq_ .SH AUTHOR .sp Brian Aker, <\fI\%brian@tangent.org\fP> .SH SEE ALSO .sp \fImemcached(1)\fP \fIlibmemcached(3)\fP .SH AUTHOR Brian Aker .SH COPYRIGHT 2011-2013, Brian Aker DataDifferential, http://datadifferential.com/ .\" Generated by docutils manpage writer. . doc/alt-krb5-libs/README000064400000037401152526542560010562 0ustar00 Kerberos Version 5, Release 1.17 Release Notes The MIT Kerberos Team Copyright and Other Notices --------------------------- Copyright (C) 1985-2019 by the Massachusetts Institute of Technology and its contributors. All rights reserved. Please see the file named NOTICE for additional notices. Documentation ------------- Unified documentation for Kerberos V5 is available in both HTML and PDF formats. The table of contents of the HTML format documentation is at doc/html/index.html, and the PDF format documentation is in the doc/pdf directory. Additionally, you may find copies of the HTML format documentation online at http://web.mit.edu/kerberos/krb5-latest/doc/ for the most recent supported release, or at http://web.mit.edu/kerberos/krb5-devel/doc/ for the release under development. More information about Kerberos may be found at http://web.mit.edu/kerberos/ and at the MIT Kerberos Consortium web site http://kerberos.org/ Building and Installing Kerberos 5 ---------------------------------- Build documentation is in doc/html/build/index.html or doc/pdf/build.pdf. The installation guide is in doc/html/admin/install.html or doc/pdf/install.pdf. If you are attempting to build under Windows, please see the src/windows/README file. Reporting Bugs -------------- Please report any problems/bugs/comments by sending email to krb5-bugs@mit.edu. You may view bug reports by visiting http://krbdev.mit.edu/rt/ and using the "Guest Login" button. Please note that the web interface to our bug database is read-only for guests, and the primary way to interact with our bug database is via email. DES transition -------------- The Data Encryption Standard (DES) is widely recognized as weak. The krb5-1.7 release contains measures to encourage sites to migrate away from using single-DES cryptosystems. Among these is a configuration variable that enables "weak" enctypes, which defaults to "false" beginning with krb5-1.8. Major changes in 1.17 (2019-01-08) ---------------------------------- Administrator experience: * A new Kerberos database module using the Lightning Memory-Mapped Database library (LMDB) has been added. The LMDB KDB module should be more performant and more robust than the DB2 module, and may become the default module for new databases in a future release. * "kdb5_util dump" will no longer dump policy entries when specific principal names are requested. Developer experience: * The new krb5_get_etype_info() API can be used to retrieve enctype, salt, and string-to-key parameters from the KDC for a client principal. * The new GSS_KRB5_NT_ENTERPRISE_NAME name type allows enterprise principal names to be used with GSS-API functions. * KDC and kadmind modules which call com_err() will now write to the log file in a format more consistent with other log messages. * Programs which use large numbers of memory credential caches should perform better. Protocol evolution: * The SPAKE pre-authentication mechanism is now supported. This mechanism protects against password dictionary attacks without requiring any additional infrastructure such as certificates. SPAKE is enabled by default on clients, but must be manually enabled on the KDC for this release. * PKINIT freshness tokens are now supported. Freshness tokens can protect against scenarios where an attacker uses temporary access to a smart card to generate authentication requests for the future. * Password change operations now prefer TCP over UDP, to avoid spurious error messages about replays when a response packet is dropped. * The KDC now supports cross-realm S4U2Self requests when used with a third-party KDB module such as Samba's. The client code for cross-realm S4U2Self requests is also now more robust. User experience: * The new ktutil addent -f flag can be used to fetch salt information from the KDC for password-based keys. * The new kdestroy -p option can be used to destroy a credential cache within a collection by client principal name. * The Kerberos man page has been restored, and documents the environment variables that affect programs using the Kerberos library. Code quality: * Python test scripts now use Python 3. * Python test scripts now display markers in verbose output, making it easier to find where a failure occurred within the scripts. * The Windows build system has been simplified and updated to work with more recent versions of Visual Studio. A large volume of unused Windows-specific code has been removed. Visual Studio 2013 or later is now required. krb5-1.17 changes by ticket ID ------------------------------ 7905 Password changes can result in replay error 8202 memory ccache cursors are invalidated by initialize 8270 No logging when a non-root ksu with command fails authorization 8587 ktutil addent should be able to fetch etype-info2 for principal 8629 etype-info not included in hint list for REQUIRES_HW_AUTH principals 8630 Logging from KDC/kadmind plugin modules 8634 Trace log on k5tls load failure 8635 Fix a few German translation prepositions 8636 PKINIT certid option cannot handle leading zero 8641 Make public headers work with gcc -Wundef 8642 etype-info conflated for initial, final reply key enctype 8647 Add SPAKE preauth support 8648 Implement PKINIT freshness tokens 8650 Exit with status 0 from kadmind 8651 profile library may try to reread from special device files 8652 Report extended errors in kinit -k -t KDB: 8653 Include preauth name in trace output if possible 8654 Prevent fallback from SPAKE to encrypted timestamp 8655 Need per-realm client configuration to deny encrypted timestamp 8657 SPAKE support for Windows build 8659 SPAKE client asks for password before checking second-factor support 8661 ksu segfaults when argc == 0 8662 Windows README does not document MFC requirement 8663 TLS is not free on library unload 8664 Avoid simultaneous KDB/ulog locks in ulog_replay 8665 Display more extended errors in kdb5_util 8673 Improve error for kadmind -proponly without iprop 8674 Add LMDB KDB module 8677 Escape curly braces in def-check.pl regexes 8678 Don't specify MFC library in Leash build 8679 Fix Leash build error with recent Visual Studio 8680 Update kfw installer for VS2017, WiX 3.11.1 8682 Stop building CNS for Windows 8684 Fix option parsing on Windows 8685 Make plugin auto-registration work on Windows 8686 Process profile includedir in sorted order 8687 Repeated lookups of local computer name on Windows 8689 t_path.c build failure with NDEBUG 8690 Fix Windows strerror_r() implementation 8691 Use pkg.m4 macros 8692 Make docs build python3-compatible 8693 Resource leak in domain_fallback_realm() 8694 Add documentation on dictionary attacks 8695 Resource leak in krb5_524_conv_principal() 8696 Resource leak in krb5_425_conv_principal() 8697 Resource leak in krb5_gss_inquire_cred() 8698 Resource leak in aname_replacer() 8699 Resource leak in k5_os_hostaddr() 8700 Resource leak in krb5int_get_fq_local_hostname() 8702 Resource leak in kdb5_purge_mkeys() 8703 Resource leak in RPC UDP cache code 8704 Resource leak in read_secret_file() 8707 Resource leak in ulog_map() 8708 Incorrect error handling in OTP plugin 8709 Explicitly look for python2 in configure.in 8710 Convert Python tests to Python 3 8711 Use SHA-256 instead of MD5 for audit ticket IDs 8713 Zap copy of secret in RC4 string-to-key 8715 Make krb5kdc -p affect TCP ports 8716 Remove outdated note in krb5kdc man page 8718 krb5_get_credentials incorrectly matches user to user ticket 8719 Extend gss-sample timeout from 10s to 300s 8720 Don't include all MEMORY ccaches in collection 8721 Don't tag S4U2Proxy result creds as user-to-user 8722 Use a hash table for MEMORY ccache resolution 8723 Use PTHREAD_CFLAGS when testing for getpwnam_r() 8724 Add kdestroy -p option 8725 Update many documentation links to https 8726 Null deref on some invalid PKINIT identities 8727 Check strdup return in kadm5_get_config_params() 8728 doc: kswitch manual "see also" subsection typo 8729 Memory leak in gss_add_cred() creation case 8730 Add kvno option for user-to-user 8731 Document that DESTDIR must be an absolute path 8732 Fix name of .pdb file in ccapi/test/Makefile.in 8733 Multiple pkinit_identities semantics are unclear and perhaps not useful 8734 gss_add_cred() aliases memory when creating extended cred 8736 Check mech cred in gss_inquire_cred_by_mech() 8737 gss_add_cred() ignores desired_name if creating a new credential 8738 Use the term "replica KDC" in source and docs 8741 S4U2Self client code fails with no default realm 8742 Use "replica" in iprop settings 8743 Fix incorrect TRACE usages to use {str} 8744 KDC/kadmind may not follow master key change before purge_mkeys 8745 libss without readline can interfere with reading passwords 8746 Fix 64-bit Windows socket write error handling 8747 Allow referrals for cross-realm S4U2Self requests 8748 Add more constraints to S4U2Self processing 8749 Add PAC APIs which can include a client realm 8750 Resource leak in ktutil_add() 8751 Fix up kdb5_util documentation 8752 Don't dump policies if principals are specified 8753 Prevent SIGPIPE from socket writes on UNIX-likes 8754 Correct kpasswd_server description in krb5.conf(5) 8755 Bring back general kerberos man page 8756 Add GSS_KRB5_NT_ENTERPRISE_NAME name type 8757 Start S4U2Self realm lookup at server realm 8759 Resource leak in kadm5_randkey_principal_3() 8760 Retry KCM writes once on remote hangup 8762 Fix spelling of auth_to_local example 8763 Ignore password attributes for S4U2Self requests 8767 Remove incorrect KDC assertion 8768 Fix double-close in ksu get_authorized_princ_names 8769 Fix build issues with Solaris native compiler Acknowledgements ---------------- Past Sponsors of the MIT Kerberos Consortium: Apple Carnegie Mellon University Centrify Corporation Columbia University Cornell University The Department of Defense of the United States of America (DoD) Fidelity Investments Google Iowa State University MIT Michigan State University Microsoft MITRE Corporation Morgan-Stanley The National Aeronautics and Space Administration of the United States of America (NASA) Network Appliance (NetApp) Nippon Telephone and Telegraph (NTT) US Government Office of the National Coordinator for Health Information Technology (ONC) Oracle Pennsylvania State University Red Hat Stanford University TeamF1, Inc. The University of Alaska The University of Michigan The University of Pennsylvania Past and present members of the Kerberos Team at MIT: Danilo Almeida Jeffrey Altman Justin Anderson Richard Basch Mitch Berger Jay Berkenbilt Andrew Boardman Bill Bryant Steve Buckley Joe Calzaretta John Carr Mark Colan Don Davis Sarah Day Alexandra Ellwood Carlos Garay Dan Geer Nancy Gilman Matt Hancher Thomas Hardjono Sam Hartman Paul Hill Marc Horowitz Eva Jacobus Miroslav Jurisic Barry Jaspan Benjamin Kaduk Geoffrey King Kevin Koch John Kohl HaoQi Li Jonathan Lin Peter Litwack Scott McGuire Steve Miller Kevin Mitchell Cliff Neuman Paul Park Ezra Peisach Chris Provenzano Ken Raeburn Jon Rochlis Jeff Schiller Jen Selby Robert Silk Bill Sommerfeld Jennifer Steiner Ralph Swick Brad Thompson Harry Tsai Zhanna Tsitkova Ted Ts'o Marshall Vale Taylor Yu The following external contributors have provided code, patches, bug reports, suggestions, and valuable resources: Ian Abbott Brandon Allbery Russell Allbery Brian Almeida Michael B Allen Pooja Anil Heinz-Ado Arnolds Derek Atkins Mark Bannister David Bantz Alex Baule David Benjamin Thomas Bernard Adam Bernstein Arlene Berry Jeff Blaine Radoslav Bodo Sumit Bose Emmanuel Bouillon Isaac Boukris Philip Brown Samuel Cabrero Michael Calmer Andrea Campi Julien Chaffraix Puran Chand Ravi Channavajhala Srinivas Cheruku Leonardo Chiquitto Seemant Choudhary Howard Chu Andrea Cirulli Christopher D. Clausen Kevin Coffman Simon Cooper Sylvain Cortes Ian Crowther Arran Cudbard-Bell Jeff D'Angelo Nalin Dahyabhai Mark Davies Dennis Davis Alex Dehnert Mark Deneen Günther Deschner John Devitofranceschi Marc Dionne Roland Dowdeswell Dorian Ducournau Viktor Dukhovni Jason Edgecombe Mark Eichin Shawn M. Emery Douglas E. Engert Peter Eriksson Juha Erkkilä Gilles Espinasse Ronni Feldt Bill Fellows JC Ferguson Remi Ferrand Paul Fertser Fabiano Fidêncio William Fiveash Jacques Florent Ákos Frohner Sebastian Galiano Marcus Granado Dylan Gray Scott Grizzard Helmut Grohne Steve Grubb Philip Guenther Timo Gurr Dominic Hargreaves Robbie Harwood John Hascall Jakob Haufe Matthieu Hautreux Jochen Hein Paul B. Henson Jeff Hodges Christopher Hogan Love Hörnquist Åstrand Ken Hornstein Henry B. Hotz Luke Howard Jakub Hrozek Shumon Huque Jeffrey Hutzelman Sergey Ilinykh Wyllys Ingersoll Holger Isenberg Spencer Jackson Diogenes S. Jesus Pavel Jindra Brian Johannesmeyer Joel Johnson Alexander Karaivanov Anders Kaseorg Bar Katz Zentaro Kavanagh Mubashir Kazia W. Trevor King Patrik Kis Martin Kittel Matthew Krupcale Mikkel Kruse Reinhard Kugler Tomas Kuthan Pierre Labastie Chris Leick Volker Lendecke Jan iankko Lieskovsky Todd Lipcon Oliver Loch Chris Long Kevin Longfellow Frank Lonigro Jon Looney Nuno Lopes Todd Lubin Ryan Lynch Roland Mainz Sorin Manolache Andrei Maslennikov Michael Mattioli Nathaniel McCallum Greg McClement Cameron Meadors Alexey Melnikov Franklyn Mendez Markus Moeller Kyle Moffett Paul Moore Keiichi Mori Michael Morony Zbysek Mraz Edward Murrell Nikos Nikoleris Felipe Ortega Michael Osipov Andrej Ota Dmitri Pal Javier Palacios Tom Parker Ezra Peisach Alejandro Perez Zoran Pericic W. Michael Petullo Mark Phalan Sharwan Ram Brett Randall Jonathan Reams Jonathan Reed Robert Relyea Tony Reix Martin Rex Pat Riehecky Jason Rogers Matt Rogers Nate Rosenblum Solly Ross Mike Roszkowski Guillaume Rousse Joshua Schaeffer Andreas Schneider Paul Seyfert Tom Shaw Jim Shi Peter Shoults Richard Silverman Cel Skeggs Simo Sorce Michael Spang Michael Ströder Bjørn Tore Sund Joe Travaglini Tim Uglow Rathor Vipin Denis Vlasenko Jorgen Wahlsten Stef Walter Max (Weijun) Wang John Washington Stef Walter Xi Wang Nehal J Wani Kevin Wasserman Margaret Wasserman Marcus Watts Andreas Wiese Simon Wilkinson Nicolas Williams Ross Wilper Augustin Wolf David Woodhouse Tsu-Phong Wu Xu Qiang Neng Xue Zhaomo Yang Nickolai Zeldovich Bean Zhang Hanz van Zijst Gertjan Zwartjes The above is not an exhaustive list; many others have contributed in various ways to the MIT Kerberos development effort over the years. Other acknowledgments (for bug reports and patches) are in the doc/CHANGES file. doc/alt-krb5-libs/NOTICE000064400000172611152526542560010611 0ustar00Copyright (C) 1985-2019 by the Massachusetts Institute of Technology. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. Downloading of this software may constitute an export of cryptographic software from the United States of America that is subject to the United States Export Administration Regulations (EAR), 15 CFR 730-774. Additional laws or regulations may apply. It is the responsibility of the person or entity contemplating export to comply with all applicable export laws and regulations, including obtaining any required license from the U.S. government. The U.S. government prohibits export of encryption source code to certain countries and individuals, including, but not limited to, the countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and nationals of those countries. Documentation components of this software distribution are licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. (https://creativecommons.org/licenses/by-sa/3.0/) Individual source code files are copyright MIT, Cygnus Support, Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, FundsXpress, and others. Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, and Zephyr are trademarks of the Massachusetts Institute of Technology (MIT). No commercial use of these trademarks may be made without prior written permission of MIT. "Commercial use" means use of a name in a product or other for-profit manner. It does NOT prevent a commercial firm from referring to the MIT trademarks in order to convey information (although in doing so, recognition of their trademark status should be given). ====================================================================== The following copyright and permission notice applies to the OpenVision Kerberos Administration system located in "kadmin/create", "kadmin/dbutil", "kadmin/passwd", "kadmin/server", "lib/kadm5", and portions of "lib/rpc": Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights Reserved WARNING: Retrieving the OpenVision Kerberos Administration system source code, as described below, indicates your acceptance of the following terms. If you do not agree to the following terms, do not retrieve the OpenVision Kerberos administration system. You may freely use and distribute the Source Code and Object Code compiled from it, with or without modification, but this Source Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY OTHER REASON. OpenVision retains all copyrights in the donated Source Code. OpenVision also retains copyright to derivative works of the Source Code, whether created by OpenVision or by a third party. The OpenVision copyright notice must be preserved if derivative works are made based on the donated Source Code. OpenVision Technologies, Inc. has donated this Kerberos Administration system to MIT for inclusion in the standard Kerberos 5 distribution. This donation underscores our commitment to continuing Kerberos technology development and our gratitude for the valuable work which has been performed by MIT and the Kerberos community. ====================================================================== Portions contributed by Matt Crawford "crawdad@fnal.gov" were work performed at Fermi National Accelerator Laboratory, which is operated by Universities Research Association, Inc., under contract DE-AC02-76CHO3000 with the U.S. Department of Energy. ====================================================================== Portions of "src/lib/crypto" have the following copyright: Copyright (C) 1998 by the FundsXpress, INC. All rights reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of FundsXpress. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. FundsXpress makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ====================================================================== The implementation of the AES encryption algorithm in "src/lib/crypto/builtin/aes" has the following copyright: Copyright (C) 2001, Dr Brian Gladman "brg@gladman.uk.net", Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. DISCLAIMER This software is provided 'as is' with no explcit or implied warranties in respect of any properties, including, but not limited to, correctness and fitness for purpose. ====================================================================== Portions contributed by Red Hat, including the pre-authentication plug-in framework and the NSS crypto implementation, contain the following copyright: Copyright (C) 2006 Red Hat, Inc. Portions copyright (C) 2006 Massachusetts Institute of Technology All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of Red Hat, Inc., nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== The bundled verto source code is subject to the following license: Copyright 2011 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== The MS-KKDCP client implementation has the following copyright: Copyright 2013,2014 Red Hat, Inc. 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in "src/lib/gssapi", including the following files: lib/gssapi/generic/gssapi_err_generic.et lib/gssapi/mechglue/g_accept_sec_context.c lib/gssapi/mechglue/g_acquire_cred.c lib/gssapi/mechglue/g_canon_name.c lib/gssapi/mechglue/g_compare_name.c lib/gssapi/mechglue/g_context_time.c lib/gssapi/mechglue/g_delete_sec_context.c lib/gssapi/mechglue/g_dsp_name.c lib/gssapi/mechglue/g_dsp_status.c lib/gssapi/mechglue/g_dup_name.c lib/gssapi/mechglue/g_exp_sec_context.c lib/gssapi/mechglue/g_export_name.c lib/gssapi/mechglue/g_glue.c lib/gssapi/mechglue/g_imp_name.c lib/gssapi/mechglue/g_imp_sec_context.c lib/gssapi/mechglue/g_init_sec_context.c lib/gssapi/mechglue/g_initialize.c lib/gssapi/mechglue/g_inquire_context.c lib/gssapi/mechglue/g_inquire_cred.c lib/gssapi/mechglue/g_inquire_names.c lib/gssapi/mechglue/g_process_context.c lib/gssapi/mechglue/g_rel_buffer.c lib/gssapi/mechglue/g_rel_cred.c lib/gssapi/mechglue/g_rel_name.c lib/gssapi/mechglue/g_rel_oid_set.c lib/gssapi/mechglue/g_seal.c lib/gssapi/mechglue/g_sign.c lib/gssapi/mechglue/g_store_cred.c lib/gssapi/mechglue/g_unseal.c lib/gssapi/mechglue/g_userok.c lib/gssapi/mechglue/g_utils.c lib/gssapi/mechglue/g_verify.c lib/gssapi/mechglue/gssd_pname_to_uid.c lib/gssapi/mechglue/mglueP.h lib/gssapi/mechglue/oid_ops.c lib/gssapi/spnego/gssapiP_spnego.h lib/gssapi/spnego/spnego_mech.c and the initial implementation of incremental propagation, including the following new or changed files: include/iprop_hdr.h kadmin/server/ipropd_svc.c lib/kdb/iprop.x lib/kdb/kdb_convert.c lib/kdb/kdb_log.c lib/kdb/kdb_log.h lib/krb5/error_tables/kdb5_err.et kprop/kpropd_rpc.c kprop/kproplog.c are subject to the following license: Copyright (C) 2004 Sun Microsystems, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== Kerberos V5 includes documentation and software developed at the University of California at Berkeley, which includes this copyright notice: Copyright (C) 1983 Regents of the University of California. 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. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "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 REGENTS OR CONTRIBUTORS 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. ====================================================================== Portions contributed by Novell, Inc., including the LDAP database backend, are subject to the following license: Copyright (C) 2004-2005, Novell, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The copyright holder's name is not used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== Portions funded by Sandia National Laboratory and developed by the University of Michigan's Center for Information Technology Integration, including the PKINIT implementation, are subject to the following license: COPYRIGHT (C) 2006-2007 THE REGENTS OF THE UNIVERSITY OF MICHIGAN ALL RIGHTS RESERVED Permission is granted to use, copy, create derivative works and redistribute this software and such derivative works for any purpose, so long as the name of The University of Michigan is not used in any advertising or publicity pertaining to the use of distribution of this software without specific, written prior authorization. If the above copyright notice or any other identification of the University of Michigan is included in any copy of any portion of this software, then the disclaimer below must also be included. THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ====================================================================== The pkcs11.h file included in the PKINIT code has the following license: Copyright 2006 g10 Code GmbH Copyright 2006 Andreas Jellinghaus This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without modifications, as long as this notice is preserved. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, to the extent permitted by law; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ====================================================================== Portions contributed by Apple Inc. are subject to the following license: Copyright 2004-2008 Apple Inc. All Rights Reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Apple Inc. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Apple Inc. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ====================================================================== The implementations of UTF-8 string handling in src/util/support and src/lib/krb5/unicode are subject to the following copyright and permission notice: The OpenLDAP Public License Version 2.8, 17 August 2003 Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source form must retain copyright statements and notices, 2. Redistributions in binary form must reproduce applicable copyright statements and notices, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution, and 3. Redistributions must contain a verbatim copy of this document. The OpenLDAP Foundation may revise this license from time to time. Each revision is distinguished by a version number. You may use this Software under terms of this license revision or under the terms of any subsequent revision of the license. THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE 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. The names of the authors and copyright holders must not be used in advertising or otherwise to promote the sale, use or other dealing in this Software without specific, written prior permission. Title to copyright in this Software shall at all times remain with copyright holders. OpenLDAP is a registered trademark of the OpenLDAP Foundation. Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, California, USA. All Rights Reserved. Permission to copy and distribute verbatim copies of this document is granted. ====================================================================== Marked test programs in src/lib/krb5/krb have the following copyright: Copyright (C) 2006 Kungliga Tekniska Högskola (Royal Institute of Technology, Stockholm, Sweden). 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. Neither the name of KTH nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS "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 KTH OR ITS CONTRIBUTORS 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. ====================================================================== The KCM Mach RPC definition file used on macOS has the following copyright: Copyright (C) 2009 Kungliga Tekniska Högskola (Royal Institute of Technology, Stockholm, Sweden). All rights reserved. Portions Copyright (C) 2009 Apple Inc. 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. Neither the name of the Institute nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "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 INSTITUTE OR CONTRIBUTORS 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. ====================================================================== Portions of the RPC implementation in src/lib/rpc and src/include/gssrpc have the following copyright and permission notice: Copyright (C) 2010, Oracle America, Inc. 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. Neither the name of the "Oracle America, Inc." nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. ====================================================================== Copyright (C) 2006,2007,2009 NTT (Nippon Telegraph and Telephone Corporation). 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 as the first lines of this file unmodified. 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. THIS SOFTWARE IS PROVIDED BY NTT "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 NTT 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. ====================================================================== Copyright 2000 by Carnegie Mellon University All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Carnegie Mellon University not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. 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. ====================================================================== Copyright (C) 2002 Naval Research Laboratory (NRL/CCS) Permission to use, copy, modify and distribute this software and its documentation is hereby granted, provided that both the copyright notice and this permission notice appear in all copies of the software, derivative works or modified versions, and any portions thereof. NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ====================================================================== Copyright (C) 1991, 1992, 1994 by Cygnus Support. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Cygnus Support makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ====================================================================== Copyright (C) 2006 Secure Endpoints Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== Portions of the implementation of the Fortuna-like PRNG are subject to the following notice: Copyright (C) 2005 Marko Kreen 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. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "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 AUTHOR OR CONTRIBUTORS 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. Copyright (C) 1994 by the University of Southern California EXPORT OF THIS SOFTWARE from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute this software and its documentation in source and binary forms is hereby granted, provided that any documentation or other materials related to such distribution or use acknowledge that the software was developed by the University of Southern California. DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The University of Southern California MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not limitation, the University of Southern California MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. The University of Southern California shall not be held liable for any liability nor for any direct, indirect, or consequential damages with respect to any claim by the user or distributor of the ksu software. ====================================================================== Copyright (C) 1995 The President and Fellows of Harvard University This code is derived from software contributed to Harvard by Jeremy Rassen. 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and its contributors. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "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 REGENTS OR CONTRIBUTORS 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. ====================================================================== Copyright (C) 2008 by the Massachusetts Institute of Technology. Copyright 1995 by Richard P. Basch. All Rights Reserved. Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Richard P. Basch, Lehman Brothers and M.I.T. make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ====================================================================== The following notice applies to "src/lib/krb5/krb/strptime.c" and "src/include/k5-queue.h". Copyright (C) 1997, 1998 The NetBSD Foundation, Inc. All rights reserved. This code was contributed to The NetBSD Foundation by Klaus Klein. 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the NetBSD Foundation, Inc. and its contributors. 4. Neither the name of The NetBSD Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS "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 FOUNDATION OR CONTRIBUTORS 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. ====================================================================== The following notice applies to Unicode library files in "src/lib/krb5/unicode": Copyright 1997, 1998, 1999 Computing Research Labs, New Mexico State University Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. ====================================================================== The following notice applies to "src/util/support/strlcpy.c": Copyright (C) 1998 Todd C. Miller "Todd.Miller@courtesan.com" Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 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. ====================================================================== The following notice applies to "src/util/profile/argv_parse.c" and "src/util/profile/argv_parse.h": Copyright 1999 by Theodore Ts'o. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 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. (Isn't it sick that the U.S. culture of lawsuit-happy lawyers requires this kind of disclaimer?) ====================================================================== The following notice applies to SWIG-generated code in "src/util/profile/profile_tcl.c": Copyright (C) 1999-2000, The University of Chicago This file may be freely redistributed without license or fee provided this copyright message remains intact. ====================================================================== The following notice applies to portiions of "src/lib/rpc" and "src/include/gssrpc": Copyright (C) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (C) 2000 Dug Song "dugsong@UMICH.EDU". All rights reserved, all wrongs reversed. 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. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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 REGENTS OR CONTRIBUTORS 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. ====================================================================== Implementations of the MD4 algorithm are subject to the following notice: Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD4 Message Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD4 Message Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. ====================================================================== Implementations of the MD5 algorithm are subject to the following notice: Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message- Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. ====================================================================== The following notice applies to "src/lib/crypto/crypto_tests/t_mddriver.c": Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. ====================================================================== Portions of "src/lib/krb5" are subject to the following notice: Copyright (C) 1994 CyberSAFE Corporation. Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. All Rights Reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Furthermore if you modify this software you must label your software as modified software and not distribute it in such a fashion that it might be confused with the original M.I.T. software. Neither M.I.T., the Open Computing Security Group, nor CyberSAFE Corporation make any representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ====================================================================== Portions contributed by PADL Software are subject to the following license: Copyright (c) 2011, PADL Software Pty Ltd. 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. Neither the name of PADL Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS "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 PADL SOFTWARE OR CONTRIBUTORS 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. ====================================================================== The bundled libev source code is subject to the following license: All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. Alternatively, the contents of this package may be used under the terms of the GNU General Public License ("GPL") version 2 or any later version, in which case the provisions of the GPL are applicable instead of the above. If you wish to allow the use of your version of this package only under the terms of the GPL and not to allow others to use your version of this file under the BSD license, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL in this and the other files of this package. If you do not delete the provisions above, a recipient may use your version of this file under either the BSD or the GPL. ====================================================================== Files copied from the Intel AESNI Sample Library are subject to the following license: Copyright (C) 2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== The following notice applies to "src/ccapi/common/win/OldCC/autolock.hxx": Copyright (C) 1998 by Danilo Almeida. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. ====================================================================== The following notice applies to portions of "src/plugins/preauth/spake/edwards25519.c" and "src/plugins/preauth/spake/edwards25519_tables.h": The MIT License (MIT) Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== The following notice applies to portions of "src/plugins/preauth/spake/edwards25519.c": Copyright (c) 2015-2016, Google Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 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. locale/en_US/LC_MESSAGES/mit-krb5.mo000064400000000632152526542560012605 0ustar00$,8`9Project-Id-Version: mit-krb5 1.10-prerelease Report-Msgid-Bugs-To: POT-Creation-Date: 2011-06-06 00:34-0400 PO-Revision-Date: 2011-06-06 00:35-0400 Last-Translator: Greg Hudson Language-Team: English MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); locale/de/LC_MESSAGES/mit-krb5.mo000064400000605313152526542560012173 0ustar0089 s()Ge23֚# .A Zfz ͛ "6Oh{  Ŝ|:#0+4`(r á Ρۡ) !.I` {&â(0Mc s*ʣ! @ N[o̤&= Vdyץ40H+y'ͦߦ 5M%@Z+uG8"@@A"é-*.Ykp٪ 7:r"Ϋ"6Yv ' ǬԬ,J-\)˭-2.?a !ڮm:j"!ȯB%-:S2)!($M=h#ʱ+CZw"!ɲ ! $.S+fdz!ܳ'&@[%lB%մ* &>G)+ε00+)\8A8I \fŷ).)>(h%Ҹ0(Ir,/0B*]4 ޺ =Ҽdpj!(Ⱦ-)I)d +#/!E1g. 2<',d'&9*.Y%p!*..#K1o&7';(>dF* *4'_" '(47:l/.C=J"/$B!^ !-"Or!)$+./*^3*0,*F1q*,2+.(Z1-)6 2D(w.,4.10`1)4'"&J&q++,*0H2y.+%0--^(1,*,?(l')!& (0*Y/-*6 'Dl56)42%g!OUU2t+*& Ef"+<)f1!'*%,Rm&)%4R/r# # ()CR)&"% %0(V'+<::9uB&/!H#j.4!()&R$y))$1*Kv%&& .26a%!!G1_($$7OXv#'"*'@]#x$6,5;b +*A%l('-(:/V0%0!Vx-%6*#Nm&*!1ShG-4"P"s '" / No %;J!] <LFLc##  # D!e 8#*0Nl">P![r; 07h}&C+1) [|-&/ :)C m$w#':W,t!4Mi0" ):J"#67;Vj./.)'-Q)()0$Z ()5)C@V% +^ $i2($15A w*0 76&T{!(,I g8*":V+k#,'Th 3/1$J o"|$&"%!4Vhx!$"6J^r&:Nbv)<Obu  3FYl4 % '0,X"$$) . )M &w  '   & B \ o  -    %* P :m ! '   *$ O  j   #    '# 'K  s , P M M%m".Fb~21"T,l2&<!\:~'$,38P " Y6E3= q!(-?m4*'QD+5$!F&X36519k'~(+1-2K~0"!< O ]kr!,5 D)R$|"!;Rq'$0'L$t%'(CLT)! &" I Y i   d!{!!!2!!* "*4"_"q""""/"/"&'#N#d#%#(#;#$ $6$&P$4w$"$ $)$%%@%]%w%%% % %%%&& &G&`&z&& &&&&'7'5P'"'.''3'9%("_("((B(P(,H)&u)')))")+*!=*)_*/*+**#*-#+Q+n++++++0,4,$O,t, ,,,2,-0-2K-3~-!-$-7-'1.Y.9v....O/UR/H/R/RD0=0?031FI1[1]15J2-2-2*2(3'03/X3'3+3(34#4=4Q4,d4*4*44&5"-5 P5\5#|5(5 5%5&55#6;Y6)696&6. 7O7`7z7777B7,848S8g8 8A8D8;.90j999(9)9)99(:4b:::$::/;B;(W;%;+;#;;?<4N<7<(<7<\=yy=b=cV>1>?>9,?"f?%?'?/?"@9*@Bd@@-@'@6ALAjA7AAA(A #BDB+aBB BB#BBC C$TZ$Z&Z2Z([;["O[Nr[1[[\%\I8\9\7\+\ ](],/]!\]~]"])]-]"^"8^7[^^8^!^(_$7_"\_'_?_5_`":` ]`+k`````` a3aSa ka a'aa2a1b#Lb$pb(b%bb2b#)c#Mc,qccccc!c d2)d\d?ld%d"d"de+eHeZezeeeeeee+f./f'^ff4ff f&f%g2>g*qg"gg1g2h6h%Ih&ohh'h!hh,i,Kixi6iiiij-jEjcj/wj/j=j$k:kUkok tkkkkk.k l*lHlfl&l5l&l m(m*Dm,om-m,mm n1nHn![n[}nnno#,oPo6cooo$o&op6/pfppNpp7p2qEq4cqq#q#q5qH-rvr,rrrr3r $s1sFsZszs sssss.s# t#Dtht&~tt t ttu u)uDAuuuuuuu-uv4vKv$`v0v0v/vw6wNwDmwJwwx#x3xOxcxvx*x x=x+y=3yqz)zWz {%+{+Q{!}{"{({#{|!|,?|@l|=|&|}.}E}X},x}+}}}~~/~8~ S~$t~~-~~~1!M'o32(J"s*6*#B$` !""2U#t!2҂#")FpӃ##%GmÄ%%D\tŅ 6So$Ć"( 'I)q,ׇ# ;\wƈ.$-Rj׉ ),=j   ۊ&/@Us/+Ӌ#"# Fg#Ì!!"@c"}%##A\o)% -D(`!Ǐߏ">a'|!Ɛ"/(Xvӑ$ &+!R"t-#Œ+'=V)lѓ!+"Mp!'є$"6 Vw  ȕ4T"q"%ݖ,$*(O'x,͗ &&?f*ʘ  #"C*f˙"#:%^"'Ԛ-)Jt!)Ǜ#,Jh:!*%L"r!+$$<!V)x#$ߞ !%!G#i%(ܟ -0N"Π:#5Y1w$ǡ+ #90])Т!1Skϣ %D`"}67פ6/F9v!˥!1Sm  Ҧ?ݦ#;ب71%iH<ة#)M+`( &)F^q  ܫ *06İB ><_3  *-61dɲ$- ?7$wBZ#M q8 ܴ&"5U4d ʵ2Jg~Ӷ;#T%x #( ?';g3׸-"#Pt*(Ϻ(-!gOT Y+e'0PD?ս)$7/\) !ľ)?+P|!.̿ ''1O " ,"+6 b;8)2<oC*J^C"M'?5<']dH@ 'L,t2)L0K!|(!% ?`1o$1K@DB#B'/$W|&5!";'LUt=7,@Nm2J<Y</?GC!  %*4_#8A8.W$,3$C1h%=AD@S;]+sxeH'&!610h0.#83P""B>>[3E,'.T -N)"L7bF$2C9&},D7CN-MLX[4NJ8/0 76'^!rAB<0VHF"0+S-C*,.Ix/(+&-Bp''%'7".Z03/8/W5106 /W670-'6U2.;7*-b319405e5.91:0l00060/g57309+j62-6.1e/1--'/U',./ 492n0<)19$k=`NBW7?~>P[2AE!=gC(G?Z8.N_Q>V2G5z>70'*X=?3/5ae-?@52v76NlgD:DTA1P $^9"BQ#NuL^0p=9G=a79&(,O.|).1(6_</#BB+3PN6*'+_ 1  / ) / =M  1 & 4 E& 3l D & + (8 0a 4 - 5 V+ ; Q )%:3`);?7:Br07.,MDz#-5Aw%#S5QP*+/M)f-- :4Z TJ JV*0/+5%aH%"%+/Q#82/!Q!j1*3Wsu"#(7(`%!4*&-Q)L09''a(9*(LSqjE}A8I.eS2@ '\ $ F * ;!JW! !+! !/!1"?I"^"5"8#?W#>#Q#8($ a$!$/$$;$A/%*q%%@%)%"&!;&-]&4&[&4'&Q'Bx'A','*(H((e(2(3(6(2,)=_),))))*0*H*2Z*&*$*<*=+DT++!+R+/(,'X,@,,<E-G-,-0-8(.Ia.+.:.2/ E/DP/!/2//0#0):0d080300 1..1L]1191!1*!2L28g222$2 23763n3333*33: 4/H4 x4(4 4-4,42)5(\5+5)555( 6,56+b6(6666677/7C7W7k77777777 8838G8[8o88888888 9929E9X9k9~9999999::):<:O:b:u:?: :6:8 ;CB;);4;3;$<><(Q<.z<*<!<5<,=H=)b=4="=$=4 >B>>(>->)>-?&0?RW?2?=?@7;@4s@@ @@A*AJA _A!A0A3A B9BoOBlB,,C+YC%C)C%C#CD?:D"zD(DDDE!EAEA\E@EEAE0AFrF"FFF:F+ G?LG*G'GTG-4HRbHHH3HIbJ{JTqKEK. L;L SL_L&xLLL2LBM&QM!xM*MEM; N(GN|pN@N;.O jO6vOAO)O:P$TPMyPKPOQHcQQ=Q<RE@RDR(RPRES`SCS-SSTT4TOTcTtT|T*TT(T0T-UVHU UU7U7V+IV uV$V.V V W-'W-UW-W,W:WX.8X!gXX#X!X&XWYWmY8Y YZ2Z/FZ2vZZZZZ[$[\\0\1E\w\0\B\]]8]N]_]Cw]4]*]^5^@M^3^E^_'_ @_7a_=_)_2`84`+m`$`"```(aAaUa!ga#a!a-aa"b!igOg)g"h0?hNph(h'h)i:iZi>oiai.j8?j&xj j"jjFj"/kFRkAkAk7l=UlJl8l.mMFmmm$mrmgnvnqoxo[vpAp5q]Jqbq` r@lrLr8r83s0ls3s<s.tC=t3t tttu9u2Xu4u7u9u22v ev2qv%v8v w/wB@wLw?w7x?Hx3xPx y! yBy#YyH}ySyzK"znz1z/zUzZA{M{J{5|>|IE|(|0|G|C1}u}-}*}}B ~M~-b~(~)~&~ U&?|?,I)lseoiՁ>?Z~Kق)%0O07+QEg;̄4Y=%B݅ &=*d-)6 0/=%m$/҇=@Ws'b͈008ac594'n)G*?3Gsw03(d,3ڌM;\l9?X!v+)Ď$ 4"Lqo5 -!LO)@Ɛ-M59/ۑ 3#!W(y%/ȒUN'4Εpt->yŞU?*!,2VB%*0762n R`jtQߢQ1f,H`[hĤ6F:}G526Gi8,=UQ!7YrY?;(/d /'֩**)?T3)Ȫ(<*XO?ӫ:5N1+MC0 t" Aŭ&1.6`0-Ȯ;72-j16ʯ<$>ac\Ű#",F9s+ٱ:'-GUB#!2.T@![A^B3!0R+jʵ۵ (!;JF4Ͷ2+R ~<EƷ: IG 4Ǹ2/3C1w"0̹7'5?]9#׺NJ&[(!ͻ!&+8RT%") GSf'#ǽ7/#/S*%9Ծ?0N/<46!7X6#  --Awo@@(Bi6(M ,Z10R"rYJ- x'N 41=f;fG>_1J <Jh5$.#8P5o+)52P' U%{ +$C^8tHGU>1$0]Sz":S i-K,H+b#(*, '()P"z.MBL-!5+:a",!1@G-g06:%8-^'#,:?@!!8:*U8P+ 63V(((#A=]=8=#P&t83/'Wt%(#92])!.#$.H'w#+))I#s$% !A)^/*,/+@0l#'2'D6a""%(&-T2m%$%);&e&23:8s'!+??%]0/&&B#i4(),H"u#'%# 0.!_&%' #(;>d-%!/6(f$'(+"3N!3'#2$-W;1#/%GmB%4)%.O:~),++<h-"#!$F1_1'6*=-h6$$&>)[)#& &4&[(A8-&4T0+-'!<^|0%6*J$c% "*-1K}'::.T)6$'=3e)761$h$"+KE"8%-S3r ' #*2N('')&$*K'v/7,,3#`):');Qq<11 O.p0&.6&-]296p+!$8=5v;8A!%cEFL:cC!$ ) %H n ( + 5 ' 4 P  i Tv smBagIqYz*A fpOt/3OO`\ /R>opQ2_Y/C-WDJUMtKeD[>+Hl3# VeZM4'I y,"Tqp#ygN?hS&D+v(] ""   >Dz_d 0"B'|l<}bT8cn b%,x0/3B }S!{ok%1!^-' d{d[@I9  #7]G kZzC)[<Czo(oxs^a.91"!af3[QUL+;W!{rP xVF+*,`m&6WA|cDw+W.fj:_=SGo= b_ )RB~7-p40Zfaq~`nM am iu6'4z89;GGvJ  t> 6YtPjgcS/, Q4q=$wUs[Cz2\6(Eghek# -pBuA.9c7bDe8o   \j"?i IK($,dcHZ/~h*0/Cq%3`+hq!V&-]PA;|<Tv:MH *%.O61PtF-NG|5+h:X&XtTLi!0mR -irXG&&'NHb;l^}SD+Y66nVFw9L s)NYyi 'f'o}dK4lJ9]56`|,TXLR2E75cH1U&1U&#Mw \$Q\a v(LKEkm1f($?W$C@tr}IFV_{?L~<X2Wj "5y0yEJu~Z@je}MgwFneVkl8u!_Oghe#r@258u.v{GvAN,7sx]Kxld3z)w!uS8bi@^)I;%;(s/ X%LcJW:?.[~#k@ nnIvT_.^:*3COxr;*43\Yf%)E*=,:YpZEA5K|{R SEP*Q^`8l?n TjJU }7 H9X'Zpy(`<|=q4$>NA=5^a]1B>2 74~ wN) mi02rk{U8bFj<>y#? FrHRuh=J"$-0P)O[]Ksxdg\BmVRQP7@M 125:< %Q$. -n do not reverse-resolve -K shows keytab entry keys -a displays the address list -d shows the submitted authorization data types -f shows credentials flags -s sets exit status based on valid tgt existence -t shows keytab entry timestamps Attribute flags Failed passwd attempt Key data Last failed auth Last successful auth Length Maximum renewable life Maximum ticket life Modification time Modified where Modifying principal Password expiration Password history Password history KVNO Password last changed Password policy Password policy switch Principal Principal expiration TL data [-lockoutduration time] [-maxlife time] [-minlife time] [-minlength length] [-minclasses number] [-history number] [-maxfailure number] [-failurecountinterval time] [-allowedkeysalts keysalts] [-randkey|-nokey] [-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife] [-kvno kvno] [-policy policy] [-clearpolicy] [-pw password] [-maxrenewlife maxrenewlife] [-e keysaltlist] [{+|-}attribute] [-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife maxtixlife] [-kvno kvno] [-policy policy] [-clearpolicy] [-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute] allow_postdated allow_forwardable allow_tgs_req allow_renewable allow_proxiable allow_dup_skey allow_tix requires_preauth requires_hwauth needchange allow_svr password_changing_service ok_as_delegate ok_to_auth_as_delegate no_auth_data_required where, [-x db_princ_args]* - any number of database specific arguments. Look at each database documentation for supported arguments (Default is credentials cache) -A destroy all credential caches in collection -A do not include addresses -A shows content of all credential caches -C canonicalize -E client is enterprise principal name -F not forwardable -P not proxiable -R renew -S service -T armor credential cache -V shows the Kerberos version and exits -V verbose -X [=] -a include addresses -c Kerberos 5 cache name -c specifies credentials cache -c specify name of credentials cache -e shows the encryption type -f forwardable -i use default client keytab (with -k) -i uses default client keytab if no name given -k specifies keytab -k use keytab -l lifetime -l lists credential caches in collection -n anonymous -p proxiable -p specify name of principal -q quiet mode -r renewable lifetime -s start time -t filename of keytab to use -v validate Addresses: Addresses: (none) Attributes changed : %d Entry block size : %u First serial # : First serial # : None First time stamp : %s First time stamp : None Last serial # : Last serial # : None Last time stamp : %s Last time stamp : None Log state : Log version # : %u Number of entries : %u Update committed : %s Update operation : Update principal : %s Update serial # : %u Update size : %u Update time stamp : %s Update time stamp : None [-A admin_server] [-F kerberos_db_file ] [-p kdb5_util_pathname] [-k keytab] [-S sname] [-U for_user [-P]] [-x db_args]* [-P port] [-a acl_file] attributes are: for client %s options are: options for credential caches: options for keytabs: service1 service2 ... update_princ_encryption [-f] [-n] [-v] [princ-pattern] purge_mkeys [-f] [-n] [-v] where, [-x db_args]* - any number of database specific arguments. Look at each database documentation for supported arguments (type 'yes' to confirm)? Couldn't allocate memory Kerberos update log (%s) Usage: %s [-h] [-v] [-v] [-e num] %s -R Usage: %s [-r realm] [-f file] [-d] [-P port] [-s srvtab] slave_host Usage: %s [-r realm] [-s srvtab] [-dS] [-f slave_file] %s successful in remotely using an unsecure (non-encrypted) channel. in remotely using an unsecure (non-encrypted) channel. GSS-API error strings complete. %s while unparsing name Full resync, error returned from master KDC. KDC cannot initialize. Not enough memory [does not exist]$Id$%.*s%s%s. Please try again. %d is an invalid KVNO value%d key(s) purged. %d key(s) would be purged. %s Cannot decode status %d%s changed %s constructing AP-REQ armor%s contains invalid filename%s does not have correct permissions for %s, %s aborted%s is an invalid enctype%s load terminated%s option not supported%s option value missing%s returned a bad exit status (%d)%s version %s %s while %s, aborting %s while decrypting FAST reply%s while handling ap-request armor%s while opening ACL file %s%s while storing credentials%s(%d): %s %s(%d): ignoring trash at end of line: %s, aborting%s. Please try again.%s: %s restore failed %s: %s while %s, aborting %s: %s while initializing context, aborting %s: %s, aborting %s: %s, attempting to retrieve default realm %s: Cannot initialize. Not enough memory %s: Could not map log %s: Invalid password %s: KDC cannot initialize. Not enough memory %s: Keytab %s does not exist. %s: No entry for principal %s exists in keytab %s %s: No entry for principal %s with kvno %d exists in keytab %s %s: Password incorrect %s: Password incorrect while %s %s: Principal %s does not exist. %s: Standard input does not appear to be a network socket. (Not run from inetd, and missing the -S option?) %s: There is only one entry for principal %s in keytab %s %s: Unknown iprop dump version %d %s: can't read dump header in %s %s: cannot construct kdb5 util dump string too long; out of memory%s: cannot get memory for realm list %s: cannot initialize realm %s - see log file for details %s: cannot initialize realm %s. Not enough memory %s: cannot initialize. Not enough memory %s: cannot parse <%s> %s: constrained delegation failed%s: create IPROP svc (PROG=%d, VERS=%d) %s: dump header bad in %s %s: dump version %s can only be loaded with the -update flag %s: error processing line %d of %s %s: error writing to %s %s: error writing to %s device %s: exec failed: %s%s: fork failed: %s%s: getclhoststr failed%s: invalid arguments %s: invalid restrictions: %s%s: kvno = %d %s: kvno = %d, keytab entry valid %s: line %d too long, truncated%s: must specify entry to delete %s: must specify keytab to read %s: must specify keytab to write %s: must specify the srvtab to read %s: out of memory %s: out of memory recording principal names%s: parser lost count! %s: pclose(popen) failed: %s%s: popen failed: %s%s: regular expression error: %s %s: regular expression match error: %s %s: server handle is NULL%s: setup_gss_names failed%s: starting... %s: syntax error at line %d <%10s...>%s: tagged data list inconsistency for %s (counted %d, stored %d) %s: unable to canonicalize principal %s: unable to figure out a principal name %s: unable to get default realm %s: unable to get kiprop host based service name for realm %s %s: usage: %s [-t] [-k] [-e] %s: warning - logging entry syntax error %s: writing srvtabs is no longer supported %s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A%spreauth required but hint list is empty%u principals processed: %u updated, %u already current %u principals processed: %u would be updated, %u already current '%s' is an invalid option '%s' more recent than '%s'.'%s' not found: '%s' value missing(Expired)(No string attributes.) (principal %s)(type 'yes' to confirm)? ** Database '%s' destroyed. ** Database of '%s' destroyed. -Z option is mutually exclusive with -z. -norandkey option only valid for kadmin.local -z option is mutually exclusive with -Z. ... CONSTRAINED-DELEGATION s4u-client=%s... PROTOCOL-TRANSITION s4u-client=%s0 is an invalid KVNO value: %s is an invalid enctype: %s is an invalid mkeyVNOA credential was invalidA later token has already been processedA parameter was malformedA required input parameter could not be readA required input parameter could not be writtenA required output parameter could not be writtenA service is not available that is required to process the requestA supplied name was of an unsupported typeA token had an invalid Message Integrity Check (MIC)A token had an invalid signatureA token was invalidAD types: ALERTAPI structure version specified by application is no longer supported (to fix, recompile application against current KADM5 API header files and libraries)API structure version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)API version specified by application is no longer supported by libraries (to fix, update application to adhere to current API version and recompile)API version specified by application is no longer supported by server (to fix, update application to adhere to current API version and recompile)API version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)API version specified by application is unknown to server (to fix, obtain and install newest KADM5 Admin Server)ASN.1 bad return from gmtimeASN.1 badly-formatted encodingASN.1 encoding ended unexpectedlyASN.1 failed call to system time libraryASN.1 identifier doesn't match expected valueASN.1 length doesn't match expected valueASN.1 missing expected EOCASN.1 non-constructed indefinite encodingASN.1 object omitted in sequenceASN.1 parse errorASN.1 structure is missing a required fieldASN.1 type numbers are inconsistentASN.1 unexpected field numberASN.1 value too largeAS_REQ (%s) %s: %s: %s for %s%s%sAS_REQ (%s) %s: ISSUE: authtime %d, %s, %s for %sAS_REQ : handle_authdata (%d)Acceptor and Initiator share no checksum typesAccess deniedAccount %s: authorization for %s for execution of Account %s: authorization for %s for execution of %s failed Account %s: authorization for %s successful Account %s: authorization of %s failed Add Additional pre-authentication requiredAdmin ServicesAdmin server does not support -nokey while creating "%s" Administration credentials NOT DESTROYED. All Tickets DisallowedAll keys for principal "%s" removed. All keys in use, nothing purged. Allowed key/salt types: %s Alternative authentication method requiredAn expected per-message token was not receivedAn invalid name was suppliedAn invalid status code was suppliedAn unsupported critical FAST option was requestedAn unsupported mechanism was requestedAnonymous pkinit without DH public value not supported.Ap-request armor not permitted with TGSAre you sure you want to delete the policy "%s"? (yes/no): Are you sure you want to delete the principal "%s"? (yes/no): Are you sure you want to rename the principal "%s" to "%s"? (yes/no): Attempt to lock database twiceAttempt to unlock database when not lockedAttempt to use incomplete security contextAttribute removed from principal "%s". Attribute set for principal "%s". Attributes:Auth context must contain local addressAuth context must contain remote addressAuthenticated %s Authenticated to Kerberos v5 Authenticating as principal %s with default keytab. Authenticating as principal %s with existing credentials. Authenticating as principal %s with keytab %s. Authenticating as principal %s with password. Authenticating as principal %s with password; anonymous requested. Authentication attempt failed: %s, GSS-API error strings are:Authentication errorAuthentication failed. Authenticator has no subkeyBad SAM flags in obtain_sam_padataBad application version was sent (via sendauth)Bad checksum in SAM challengeBad database creation flagsBad direction for converting keysBad encryption typeBad format in credentials cacheBad format in keytabBad krb5 admin server hostnameBad lifetime value %s Bad lifetime value (%s hours?) Bad lock modeBad magic number for FAST requestBad magic number for FAST responseBad magic number for GSSAPI OIDBad magic number for GSSAPI QUEUEBad magic number for fast armored requestBad magic number for iakerb_ctx_id_tBad magic number for krb5_address structureBad magic number for krb5_alt_method structureBad magic number for krb5_ap_rep structureBad magic number for krb5_ap_rep_enc_part structureBad magic number for krb5_ap_req structureBad magic number for krb5_auth_context structureBad magic number for krb5_authdata structureBad magic number for krb5_authdata_contextBad magic number for krb5_authenticator structureBad magic number for krb5_ccache structureBad magic number for krb5_checksum structureBad magic number for krb5_checksum_entry structureBad magic number for krb5_context structureBad magic number for krb5_cred structureBad magic number for krb5_cred_enc_part structureBad magic number for krb5_cred_info structureBad magic number for krb5_creds structureBad magic number for krb5_cryptosystem_entry structureBad magic number for krb5_cs_table_entry structureBad magic number for krb5_data structureBad magic number for krb5_db_context structureBad magic number for krb5_enc_data structureBad magic number for krb5_enc_kdc_rep_part structureBad magic number for krb5_enc_sam_response_encBad magic number for krb5_enc_tkt_part structureBad magic number for krb5_encrypt_block structureBad magic number for krb5_error structureBad magic number for krb5_etype_info_entry structureBad magic number for krb5_gss_cred_id_tBad magic number for krb5_gss_ctx_id_tBad magic number for krb5_gss_enc_descBad magic number for krb5_kdc_rep structureBad magic number for krb5_kdc_req structureBad magic number for krb5_keyblock structureBad magic number for krb5_keytab structureBad magic number for krb5_keytab_entry structureBad magic number for krb5_last_req_entry structureBad magic number for krb5_os_context structureBad magic number for krb5_pa_data structureBad magic number for krb5_preauth_opsBad magic number for krb5_predicted_sam_responseBad magic number for krb5_principal structureBad magic number for krb5_priv structureBad magic number for krb5_priv_enc_part structureBad magic number for krb5_pwd_data structureBad magic number for krb5_rcache structureBad magic number for krb5_response structureBad magic number for krb5_safe structureBad magic number for krb5_sam_challengeBad magic number for krb5_sam_challenge_2Bad magic number for krb5_sam_keyBad magic number for krb5_sam_responseBad magic number for krb5_sam_response 2Bad magic number for krb5_ticket structureBad magic number for krb5_tkt_authent structureBad magic number for krb5_transited structureBad magic number for passwd_phrase_elementBad principal name while trying to forward credentialsBad response (during sendauth exchange)Bad sendauth version was sentBad start time value %s Bind DN entry '%s' missing in LDAP password file '%s'Buffer is the wrong sizeBusy signal received from master, backoff for %d secs CRITICALCalling iprop_get_updates_1 (sno=%u sec=%u usec=%u) Can not fetch master key (error: %s).Can't create new subsidiary cacheCan't create new subsidiary cache because default cache is already a subsidiaryCan't create new subsidiary cache because default cache is not a directory collectionCan't destroy replay cache: %sCan't find client principal %s in cache collectionCan't find username for uid %luCan't open/find Kerberos configuration fileCan't open/find lname translation databaseCan't open/find realm translation fileCan't read from replay cache: %sCan't verify certificateCan't write to replay cache: %sCannot %s replay cache file %s: %sCannot %s replay cache: %sCannot bind server socket on %sCannot bind to LDAP server '%s' as '%s': %sCannot bind to LDAP server '%s' with SASL mechanism '%s': %sCannot build GSSAPI auth namesCannot change keytab with keytab iterators activeCannot change protected principalCannot contact any KDC for realm '%.*s'Cannot contact any KDC for requested realmCannot convert V5 address informationCannot convert V5 keyblockCannot convert V5 principalCannot create LDAP handle for '%s': %sCannot create RPC service: %s; continuingCannot create TCP server socket on %sCannot create cert chain: %sCannot decrypt ticket for %s using keytab key for %sCannot determine realm for hostCannot determine realm for numeric host addressCannot enable SO_REUSEADDR on fd %dCannot find KDC for realm "%.*s"Cannot find KDC for requested realmCannot find active master keyCannot find key for %s kvno %d in keytabCannot find key for %s kvno %d in keytab (request ticket server %s)Cannot find master key record in databaseCannot find ticket for requested realmCannot find/read stored master keyCannot fstat replay cache file %s: %sCannot initialize GSSAPI service nameCannot listen on TCP server socket on %sCannot lock databaseCannot open LDAP password file '%s': %sCannot read passwordCannot register RPC service: %s; continuingCannot request packet info for udp socket address %s port %dCannot resolve address of admin server "%s" for realm "%s"Cannot resolve network address for KDC in requested realmCannot resolve network address for admin server in requested realmCannot reuse passwordCannot set GSSAPI authentication namesCannot set up KDB keytabCannot sync replay cache file: %sCannot write to specified key tableCcache function not supported: not implementedCcache function not supported: read-only ccache typeCertificate mismatchChallenge for Activcard mechanismChallenge for Digital Pathways mechanismChallenge for Enhanced S/Key mechanismChallenge for Enigma Logic mechanismChallenge for Security Dynamics mechanismChallenge for Traditional S/Key mechanismChallenge from authentication serverChanging uid to %s (%ld) Checksum must be includedClient '%s' not found in Kerberos databaseClient name mismatchClient not found in Kerberos databaseClient not trustedClient not yet valid - try again laterClient or server has a null keyClient's entry in database has expiredClient's key is encrypted in an old master keyClient/server realm mismatch in initial ticket requestClients credentials have been revokedClock skew too greatClock skew too great in KDC replyCommunication failure with serverConditional dump is an undocumented option for use only for iprop dumpsConfiguration file does not specify default realmConnection from %sConnection to server already initializedConnection to server not initializedContext is already fully establishedConversion to service principal undefined for name typeCorrupt Corrupt header log, exiting Corrupt update entry Could not allocate principal name Could not create temp keytab file name.Could not dup the inetd socket: %sCould not find %s plugin module named '%s'Could not get a tgt for Could not open /dev/null: %sCould not open iprop ulog Couldn't allocate gss_buffer_t dataCouldn't open log file %s: %s Couldn't read database_name Couldn't reinitialize ulog file %s Creating new master key for master key principal '%s' Credential cache directory %s does not existCredential cache directory %s exists but is not a directoryCredential cache has no TGTCredential cache is emptyCredential cache name malformedCredential usage type is unknownCredentials cache I/O operation failed (%s)Credentials cache I/O operation failed XXXCredentials cache file '%s' not foundCredentials cache keyring '%s' not foundCredentials cache permissions incorrectCredentials cache type is already registered.Credentials for server have been revokedCryptosystem internal errorCurrent password's minimum life has not expiredDES key has bad parityDES key is a weak keyDN information missingDN is out of the realm subtreeDatabase error! Required KADM5 principal missingDatabase format errorDatabase has already been initializedDatabase has not been initializedDatabase inconsistency detectedDatabase is locked or in use--try again laterDatabase library failed to initializeDatabase load process for full propagation completed. Database module does not match KDC versionDatabase not currently opened!Database not initializedDatabase not lockedDatabase propagation to %s: SUCCEEDED Database read errorDatabase record is incomplete or corruptedDatabase store errorDatabase type not supportedDatabase was modified during readDecoding out of dataDecrypt integrity check failedDefault realm not setDelete Delete Failed: One or more Principals associated with the Ticket PolicyDeleting KDC database of '%s', are you sure? Deleting KDC database stored in '%s', are you sure? Digest in certificate not acceptedDigest in signed-data not acceptedEMERGENCYERROR returned by master KDC, bailing. ERROR returned by master, bailing Empty passwords are not allowedEncoding too largeEncrypted Challenge used outside of FAST tunnelEncryption type %s not permittedEncryption type not permittedEnctype %d has no PRFEnd of credential cache reachedEnd of key table reachedEnd-of-file on replay cache I/OEnter #Enter DN of Kerberos container: Enter OTP Token ValueEnter it againEnter new passwordEnter password for principal "%s"Entry already exists in databaseEntry data decode failure Entry for principal %s with kvno %d removed from keytab %s. Entry for principal %s with kvno %d, encryption type %s added to keytab %s. ErrorError creating file %sError in krb5_auth_con_ini: %sError in krb5_auth_con_setaddrs: %sError in krb5_auth_con_setflags: %sError in krb5_copy_prinicpal: %sError in krb5_kt_resolve: %sError in krb5_recvauth: %sError processing LDAP DB params:Error reading '%s' attribute: %sError reading LDAP server params:Error reading container object: Error reading kerberos container location from krb5.confError reading password from stash: Error reading service object password fileError reading ticket policy. Error reading ticket policy: Error text from client: %s Error text from server: %s Error writing to credentials cacheError writing to key tableError: bad entry - %s in %s file, CMD_PATH contains no paths Error: bad entry - %s in %s file, must be either full path or just the cmd name Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH must be defined Error: bad path %s in CMD_PATH for %s must start with '/' Error: not found -> Etype (skey, tkt): %s, Expecting FX_ERROR pa-data inside FAST containerExpiration date: %s Exponential backoff Extra arguments (starting with "%s"). FAST protected pre-authentication required but not supported by KDCFAST req_checksum invalid; request modifiedFAST response missing finish message in KDC replyFailed getting object referencesFailed password attempts: %d Failed to convert the password to hexadecimalFailed to open file %s: %sFailed to reconfigure network, exitingFailed to write service object password to fileFailure!Field is too long for this implementationFlags: %sFull propagation transfer finished. Full propagation transfer started. Full resync error from master Full resync invalid result from master Full resync needed Full resync permission denied Full resync request granted Full resync request granted.Full resync, invalid return from master KDC.Full resync, permission denied.GSS-API (or Kerberos) errorGeneric error (see e-text)Generic preauthentication failureGeneric remote error: %s Generic unknown RC errorGeneric unknown RC/IO errorGeneric update log errorGoodbye Got incremental updates (sno=%u sec=%u usec=%u) Got signal to request exitGot signal to resetHW authentication requiredHistory entry contains no key dataHostname cannot be canonicalizedHostname in SERVICE-NAME string could not be canonicalizedI/O error in replay cache i/o codeIllegal character in component nameIllegal configuration parameter for local KADM5 clientIllegal configuration parameter for remote KADM5 clientIllegal cross-realm ticketIllegal policy nameIllegal principal nameIllegal use of wildcardIllegal version number for KRB5_TL_ACTKVNO %d Illegal version number for KRB5_TL_MKEY_AUX %d Improper format of Kerberos configuration fileImproper format of realm translation fileImproper format of translation database entryInappropriate type of checksum in messageInconsistent key purposeIncorrect channel bindings were suppliedIncorrect message directionIncorrect net addressIncorrect passwordIncorrect password in encrypted challengeIncorrect sequence number in messageIncremental propagation enabled Incremental updates: %d updates / %lu usIncremental updates: %d updates / %lu us Initial Ticket response appears to be Version 4 errorInitial password requiredInitialized cache Initializing database '%s' for realm '%s', master key name '%s' Initializing database for realm '%s' Initializing kadm5 as client %s Insecure file mode for replay cache file %sInsecure mkstemp() file mode for replay cache file %s; try running this program with umask 077Insufficient access to lock databaseInsufficient access to perform requested operationInsufficient authorization for operationInsufficient permission to lock fileInsufficient space to return complete informationInsufficient system space to store replay informationInternal credentials cache errorInternal error parsing X509_user_identity Internal error: command %s did not get resolved Invalid !Invalid KDC option combination (library internal error)Invalid Kerberos container DNInvalid UID in persistent keyring nameInvalid UTF-8 stringInvalid auxillary attributesInvalid certificateInvalid credential was suppliedInvalid date specification "%s". Invalid encryption type in SAM challengeInvalid enctype for setv4keyInvalid field length in tokenInvalid field mask for operationInvalid flag for file lock modeInvalid format of Kerberos lifetime or clock skew stringInvalid kdb lock modeInvalid key generation parameters from KDCInvalid key/salt tuplesInvalid keyring anchor nameInvalid message typeInvalid message type specified for encodingInvalid module specifierInvalid module specifier %sInvalid number of character classesInvalid password history countInvalid password lengthInvalid pkinit packet: octet string expectedInvalid policy nameInvalid principal nameInvalid signatureInvalid tokenInvalid token was suppliedIprop not enabled It is important that you NOT FORGET this password. KADM5 administration database lock file missingKCM daemon reply too bigKDB module requires -update argumentKDC ServicesKDC can't fulfill requested optionKDC has no support for checksum typeKDC has no support for encryption typeKDC has no support for padata typeKDC has no support for transited typeKDC is synchronized with master. KDC name mismatchKDC not trustedKDC policy rejects requestKDC policy rejects transited pathKDC reply did not match expectationsKDC returned error string: %.*sKRB5 error code 101KRB5 error code 102KRB5 error code 103KRB5 error code 104KRB5 error code 105KRB5 error code 106KRB5 error code 107KRB5 error code 108KRB5 error code 109KRB5 error code 110KRB5 error code 111KRB5 error code 112KRB5 error code 113KRB5 error code 114KRB5 error code 115KRB5 error code 116KRB5 error code 117KRB5 error code 118KRB5 error code 119KRB5 error code 120KRB5 error code 121KRB5 error code 122KRB5 error code 123KRB5 error code 124KRB5 error code 125KRB5 error code 126KRB5 error code 127KRB5 error code 30KRB5 error code 53KRB5 error code 54KRB5 error code 55KRB5 error code 56KRB5 error code 57KRB5 error code 58KRB5 error code 59KRB5 error code 82KRB5 error code 83KRB5 error code 84KRB5 error code 87KRB5 error code 88KRB5 error code 89KRB5 error code 90KRB5 error code 91KRB5 error code 92KRB5 error code 94KRB5 error code 95KRB5 error code 96KRB5 error code 97KRB5 error code 98KRB5 error code 99KVNO of new master key does not match expected valueKVNO: %d KVNO: %d, Enctype: %s, Active on: %s KVNO: %d, Enctype: %s, Active on: %s * KVNO: %d, Enctype: %s, No activate time set Kerberos 4 is no longer supported Kerberos Container create FAILED: %sKerberos Container delete FAILED: %sKerberos Container information is missingKerberos V4 errorKerberos V5 magic number tableKerberos container location not specifiedKerberos database constraints violatedKerberos database internal errorKerberos library initialization failureKerberos password for %s: Kerberos service unknownKerberos version 4 support is disabledKey for "%s" randomized. Key for %s (hex): Key parameters not acceptedKey size in database is invalidKey size is incompatible with encryption typeKey table entry not foundKey table file '%s' not foundKey table name malformedKey table type is already registered.Key version is not availableKey version number for principal in key table is incorrectKeytab %s is nonexistent or emptyKeytab contains no suitable keys for %sKeytab name too longKilling fullprop child (%d) Kpropd sent database size %d, expecting %dLDAP bind dn value missingLDAP bind password value missingLast modified: %s (%s) Last password change: %s Last successful authentication: %s Leaving uid as %s (%ld) Loading random dataLoading random data Local host name could not be determinedLooping detected inside krb5_get_in_tktMKey: vno %d Mach RPC error communicating with KCM daemonMake sure that you have removed the old principal from all ACLs before reusing. Make sure that you have removed this principal from all ACLs before reusing. Malformed reply from KCM daemonMalformed representation of principalMalformed request errorMaster key does not match databaseMatching credential not foundMaximum Renewable LifeMaximum Ticket LifeMaximum password failures before lockout: %lu Maximum password life: %ld Maximum renewable life: %s Maximum ticket life: %s Mechanism is incorrectMessage context invalidMessage is a replayMessage out of orderMessage replay detection requires rcache parameterMessage size is incompatible with encryption typeMessage stream modifiedMinimum connections required per server is 2Minimum number of password character classes: %ld Minimum password length: %ld Minimum password life: %ld Miscellaneous RPC error: %s, %sMiscellaneous failureMismatched enctypes for setkey3Missing checksum in SAM challengeMissing parameters in krb5.conf required for kadmin clientMissing required ACL file configurationMissing required realm configurationMultiple values for single or folded enctypeMutual authentication failedNOTICE: no policy specified for %s; assigning "default" New passwordNew password (again)New password cannot be zero lengthNew password does not have enough character classes. The character classes are: - lower-case letters, - upper-case letters, - digits, - punctuation, and - all other characters (e.g., control characters). Please choose a password with at least %d character classes.New password is too short. Please choose a password which is at least %d characters long.New password was found in a dictionary of possible passwords and therefore may be easily guessed. Please choose another password. See the kpasswd man page for help in choosing a good password.New password was used previously. Please choose a different password.New passwords do not match - password not changed. No @ in SERVICE-NAME name stringNo DUP_SKEY requestsNo ErrorNo KCM server foundNo Kerberos credentials availableNo TGT-based requestsNo acceptable KDF offeredNo administration server found for realmNo armor key but FAST armored request presentNo authorization data requiredNo context has been establishedNo credentials cache foundNo credentials found with supported encryption typesNo credentials supplied to library routineNo credentials were suppliedNo credentials were supplied, or the credentials were unavailable or inaccessibleNo default realm set; cannot initialize KDBNo dictionary file specified, continuing without one.No errorNo key table entry found for %sNo key table entry found matching %sNo keys in keytabNo local name found for principal nameNo matching key in entryNo matching key in entry having a permitted enctypeNo more memory to allocate (in credentials cache code)No more memory to allocate (in replay cache I/O code)No more memory to allocate (in replay cache code)No password given No pkinit_anchors supplied for realm %sNo pkinit_identity supplied for realm %sNo principal in keytab matches desired nameNo realms configured correctly for pkinit supportNo such entry in the databaseNo supported encryption types (config file error?)No supported tokensNo ticket granting ticketNo translation available for requested principalNo user identity options specifiedNot ForwardableNot PostdateableNot a hexadecimal passwordNot enough memory Not proxiableNot renewableNoticeNumber of keys: %d Number of old keys kept: %ld OK as DelegateOK, deleting database '%s'... OK, deleting database of '%s'... OK, doing nothing. OK, purging unused master keys from '%s'... OTP Challenge:OTP Token PINOTP value doesn't match any token formatsOld keys for principal "%s" purged. One of -c or -p must be specified Only one -I option allowed Only one -c option allowed Only one -c or -p option allowed Only one -t option allowed. Only one armor_ccache Only one of -a and -A allowed Only one of -f and -F allowed Only one of -p and -P allowed Only one of -t and -i allowed Operation failed for unspecified reasonOperation requires ``add'' privilegeOperation requires ``change-password'' privilegeOperation requires ``delete'' privilegeOperation requires ``get'' privilegeOperation requires ``list'' privilegeOperation requires ``modify'' privilegeOperation requires ``set-key'' privilegeOption -P (constrained delegation) requires keytab to be specified Option -P (constrained delegation) requires option -U (protocol transition) Options -u and -S are mutually exclusive Out of memory PA Option %s = %s PRF input too longPROCESS_TGS: failed lineage checkPacket was replayed in wrong directionPass phrase forPasswd ServicesPassword Change requiredPassword Changing ServicePassword cannot be changed because it was changed too recently. Please wait until %s before you change it. If you need to change your password before then, contact your system security administrator.Password change failedPassword change rejectedPassword changed. Password corruptPassword does not contain enough character classesPassword expiration date: %s Password expired. You must change it now.Password failure count reset interval: %s Password for "%s"Password for "%s" changed. Password for %.1000sPassword for %sPassword has expiredPassword history principal key version mismatchPassword incorrect while getting initial ticketPassword is in the password dictionaryPassword is too shortPassword lockout duration: %s Password may not match principal namePassword may not match user information.Password minimum life is greater than password maximum lifePassword mismatchPassword not changed.Password read interruptedPermission denied in replay cache codePkinit request not signed, but client not anonymous.Please choose from the following: Please enter new master key.... Plugin does not support interface versionPlugin does not support the operationPlugin module name not foundPolicy "%s" not deleted. Policy does not existPolicy is in usePolicy rejects transited pathPolicy: %s Policy: %s%s Preauth module %s: %sPreauthentication failedPreauthentication requiredPremature EOF found for database file!Principal "%s" deleted. Principal "%s" modified. Principal "%s" not deleted Principal "%s" not renamed Principal "%s" renamed to "%s". Principal %s has realm presentPrincipal %s is missing required realmPrincipal Container ReferencePrincipal add failed: %sPrincipal delete failed (trying to replace entry): %sPrincipal does not belong to realmPrincipal does not belong to the default realmPrincipal does not existPrincipal has multiple entries in Kerberos databasePrincipal in credential cache does not match desired namePrincipal or policy already existsPrincipal or policy does not existPrincipal: %s Principals whose keys WOULD BE re-encrypted to master key vno %u: Principals whose keys are being re-encrypted to master key vno %u if necessary: Program called an obsolete, deleted functionProgram lacks support for address typeProgram lacks support for checksum typeProgram lacks support for encryption typeProgram lacks support for key typeProgrammer error! Bad API structure versionProgrammer error! Bad API versionProgrammer error! Bad Admin server handleProgrammer error! Illegal tagged data list typeProtocol transition with delegation allowedProtocol version mismatchPublic key encryption not supportedPurging the following master key(s) from %s: RPC svc_freeargs failed (%s)RPC svc_getargs failed (%s)RPC svc_sendreply failed (%s)RPC unknown request: %d (%s)RSA-MD5 supportedRandom number generator could not be seededRe-encrypt all keys not using master key vno %u?Re-enter password for "%s"Re-enter password for principal "%s"Realm Delete FAILED: %sRealm NameRealm information not availableRealm not local to KDCReceived token ID does not match expected token IDReinitialized the ulog. Reinitializing iprop because get updates failed Rejected connection from unauthorized principal %sRejected connection from unauthorized principal %s Replay cache I/O operation failedReplay cache name parse/format errorReplay cache type does not support non-volatile storageReplay cache type is already registeredReplay cache type is unknownReply has wrong form of session key for anonymous requestRequest did not supply a ticketRequest is a replayRequest missing second ticketRequest ticket server %s found in keytab but does not match server principal %sRequest ticket server %s kvno %d enctype %s found in keytab but cannot decrypt ticketRequest ticket server %s kvno %d found in keytab but not with enctype %sRequest ticket server %s kvno %d not found in keytab; keytab is likely out of dateRequest ticket server %s kvno %d not found in keytab; ticket is likely out of dateRequest ticket server %s not found in keytab (ticket kvno %d)Request: %s, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%sRequest: %s, %s, %s, client=%s, service=%s, addr=%sRequest: %s, spawned resync process %d, client=%s, service=%s, addr=%sRequest: kadm5_init, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s, vers=%d, flavor=%dRequest: kadm5_rename_principal, %.*s%s to %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%sRequested effective lifetime is negative or too shortRequested encryption type not used in messageRequested lucid context version not supportedRequested principal and ticket don't matchRequested protocol version not supportedRequested server and ticket don't matchRequesting ticket can't get forwardable ticketsRequired parameters in kdc.conf missingRequired preauthentication key not suppliedResponse too big for UDP, retry with TCPRevocation status unavailableRevocation status unknownRevoked certificateSAM AuthenticationSPNEGO acceptor did not return a valid tokenSPNEGO acceptor did not select a mechanismSPNEGO cannot find mechanisms to negotiateSPNEGO failed to acquire credsSPNEGO failed to negotiate a mechanismSTRING-UID-NAME contains nondigitsSearchScopeSeeding random number generatorSequence number in token is corruptServer %s not found in Kerberos databaseServer errorServer not found in Kerberos databaseServer not yet valid - try again laterServer principal %s does not match any keys in keytabServer principal %s does not match request ticket server %sServer principal valid for user2user onlyServer rejected authentication (during sendauth exchange)Server's entry in database has expiredServer's key is encrypted in an old master keyService DisabledService key not availableService not respondingService password length is zeroSleeping %d seconds to re-initialize kadm5 (RPC ERROR) Sleeping %d seconds to re-initialize kadm5 (krb5kdc not running?) Stable Still waiting for full resync Stored credentials Stored master key is corruptedStored master key is not currentStoring of acceptor credentials is not supported by the mechanismStoring of non-default credentials is not supported by the mechanismSubsidiary cache path %s filename does not begin with "tkt"Subsidiary cache path %s has no parent directorySubtreeSuccessSupplied data not handled by this pluginTCP client %s wants %lu bytes, cap is %luTCP socket fd number %d (for %s) too highTGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %sTGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%sTGS_REQ : handle_authdata (%d)TGS_REQ: SESSION KEY or MUTUALTGS_REQ: UNKNOWN SERVER: server='%s'TGS_REQ: issuing TGT %sTGS_REQ: issuing alternate TGTTGT has been revokedTemporary stash file already exists: %s.The IAKERB proxy could not find a KDCThe KDC did not respond to the IAKERB proxyThe KDC should discard this requestThe context has expiredThe given credential's usage does not match the requested usageThe operation is forbidden by local security policyThe operation is forbidden by the local security policyThe operation or option is not availableThe operation or option is not available or unsupportedThe password can only be changed once a day.The password can only be changed every %d days.The password must be different from the previous password.The password must be different from the previous %d passwords.The password must contain at least %d character.The password must contain at least %d characters.The password must include numbers or symbols. Don't include any part of your name in the password.The provided name was not mechanism specific (MN)The quality-of-protection (QOP) requested could not be providedThe quality-of-protection requested could not be providedThe referenced context has expiredThe referenced credential has expiredThe referenced credentials have expiredThe requested credential element already existsThe routine completed successfullyThe routine must be called again to complete its functionThe salt type of the specified principal does not support renamingThe ticket isn't for usThe token was a duplicate of an earlier tokenThe token's validity period has expiredThere is only one master key which can not be purged. This Krb5 library has expiredThis application has expiredThis will delete the policy object '%s', are you sure? Ticket Policy Name missingTicket Policy Object DN missingTicket Policy Object information missingTicket cache %cNOT%c destroyed! Ticket cache NOT destroyed! Ticket cache: %s:%s Default principal: %s Ticket expiredTicket flagsTicket has invalid flag setTicket is ineligible for postdatingTicket modified in KDC replyTicket not yet validTicket/authenticator don't matchToken header is malformed or corruptToken is missing dataToken was reflectedToo few argumentsToo much string mapping dataTracing unsupportedTry a more complex password, or contact your administrator.UID does not resolve to usernameUnable to access Kerberos databaseUnable to decrypt latest master key with the provided master key Unable to find requested database typeUnable to find requested database type: %sUnable to get default realmUnable to identify user Unable to identify user from password file Unable to initialize Kerberos Unable to initialize preauth contextUnable to initialize signal handlers in pid %dUnable to load requested database module '%s': plugin symbol 'kdb_function_table' not foundUnable to map log file %s Unable to map log! Unable to read Kerberos containerUnable to read RealmUnable to reinitialize main loopUnauthorized request: %s, %.*s%s, client=%.*s%s, service=%.*s%s, addr=%sUnauthorized request: %s, client=%s, service=%s, addr=%sUnauthorized request: kadm5_rename_principal, %.*s%s to %.*s%s, client=%.*s%s, service=%.*s%s, addr=%sUnkeyed checksum used in fast_reqUnknown %s (field = %d)Unknown FAST armor type %dUnknown Key table typeUnknown credential cache typeUnknown keyring collection versionUnknown quality of protection specifiedUnknown signature type in tokenUnknown state: %d Unrecognized ACL operation '%c' in %sUnspecified GSS failure. Minor code may provide more informationUnspecified password quality failureUnstable Unsupported argument "%s" for db2Unsupported credentials cache format version numberUnsupported encryption typeUnsupported key table format version numberUnsupported preauthentication typeUnsupported replay cache format version numberUnsupported salt typeUnsupported type while processing '%s' Unsupported version in database entryUpdate Entry Update log conversion errorUpdate log dump : Update log is corruptUpdate log is unstableUsage: %s [-A] [-q] [-c cache_name] Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-t] [-K]] [name] Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args] clnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]|[-n] local args: [-x db_args]* [-d dbname] [-e "enc:salt ..."] [-m] where, [-x db_args]* - any number of database specific arguments. Look at each database documentation for supported arguments Usage: %s [target user] [-n principal] [-c source cachename] [-k] [-D] [-r time] [-pf] [-l lifetime] [-zZ] [-q] [-e command [args... ] ] [-a [args... ] ] Usage: %s dbpathname realmnameUsage: %s {-c cache_name | -p principal} Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] [-port port-number] [-proponly] [-p path-to-kdb5_util] [-F dump-file] [-K path-to-kprop] [-P pid_file] where, [-x db_args]* - any number of database specific arguments. Look at each database documentation for supported arguments Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri] cmd [cmd_options] create [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn] [-m|-P password|-sf stashfilename] [-k mkeytype] [-kv mkeyVNO] [-s] [-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life] [ticket_flags] [-r realm] modify [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn] [-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life] [ticket_flags] [-r realm] view [-r realm] destroy [-f] [-r realm] list stashsrvpw [-f filename] service_dn create_policy [-r realm] [-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy modify_policy [-r realm] [-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy view_policy [-r realm] policy destroy_policy [-r realm] [-force] policy list_policy [-r realm] Usage: kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M mkeyname] [-kv mkeyVNO] [-sf stashfilename] [-m] cmd [cmd_options] create [-s] destroy [-f] stash [-f keyfile] dump [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-mkey_convert] [-new_mkey_file mkey_file] [-rev] [-recurse] [filename [princs...]] load [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-update] filename ark [-e etype_list] principal add_mkey [-e etype] [-s] use_mkey kvno [time] list_mkeys Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] [principal | -glob princ-exp] [...] Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob princ-exp] [...] Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|"all"|"old"] User modification failed: %sUser to user requiredUsing default cache: %s Using existing cache: %s Using existing stashed keys to update stash file. Using keytab: %s Using new cache: %s Using principal: %s Using specified cache: %s Using specified input cache: %s V5 realm name longer than V4 maximumValidation errorVendor:WARNING! Cannot find dictionary file %s, continuing without one.WARNING! Forged/garbled request: %d, claimed client = %.*s%s, server = %.*s%s, addr = %sWARNING! Forged/garbled request: %s, claimed client = %.*s%s, server = %.*s%s, addr = %sWARNING: Your password may be exposed if you enter it here and are logged WARNING: Your password may be exposed if you enter it here and are logged WARNING: no policy specified for %s; defaulting to no policy WARNING: policy "%s" does not exist Waiting for %d seconds before checking for updates again WarningWarning! Multiple DES-CBC-CRC keys for principal %s; skipping duplicates. Warning! No DES-CBC-CRC key for principal %s, cannot generate OV-compatible record; skipping Warning: Your password will expire in %d days on %sWarning: Your password will expire in %d hour%s on %sWarning: Your password will expire in less than one hour on %sWarning: couldn't stash master key. Warning: proceeding without master keyWhen determining client principal name from keytabWhen resolving the default client keytabWhen unparsing nameWhile converting enctype to stringWill purge all unused master keys stored in the '%s' principal, are you sure? Would purge the following master key(s) from %s: Wrong principal in requestWrong protocol versionXDR encoding errorYou must type a password. Passwords must be at least one character long. You will be prompted for a new database Master Password. You will be prompted for the database Master Password. Your uid doesn't match your passwd entry?! [never][none]accepted RPC connection on socket %d from %saccount %s: authorization failed addent: Error reading key. addent: Illegal character in key. adding new master key to master principalallocating buffer for new TCP session from %sallocating database file name '%s'allocating krb5_get_init_creds_optap-request armor for something other than the local TGSap-request armor without subkeyasprintf could not allocate enough memory to hold outputassuming IPv6 socket accepts IPv4audit plugin %s failed to open. error=%iauthdata %s failed to initialize: %sauthdata (%s) handling failure: %sauthenticated client: %s (etype == %s) authentication attempt failed: %s, RPC authentication flavor %dbad realm transit path from '%s' to '%s' via '%.*s%s'bad service principal %.*s%sbroken address (type %d length %d)calling errorcannot allocate storage for connection infocannot create io eventcannot match size tokenscannot parse policy (%d read) cannot read extra datacannot read key datacannot read key size and versioncannot read key type and lengthcannot read name stringcannot read principal attributescannot read tagged data contentscannot read tagged data type and lengthcannot save eventcannot set listening tcp socket on %s non-blockingcannot specify keysaltlist when not changing key change_password: Not enough memory change_password: missing db argumentchange_password: missing keysaltlist argchange_password: missing password argchanging passwordcheck_rpcsec_auth: failed inquire_context, stat=%uchpw request from %s for %.*s%s: %schpw: Couldn't open admin keytab %sclient and server principal names must matchclosing ccacheclosing down fd %dcommencing operationcomposing ccache namecomputing parameters for databasecontainer reference value: converting glob pattern '%s' to regular expressioncopying db argscould not complete roll-back, error deleting Kerberos Containercould not parse date-time string '%s'could not sync ulog header to diskcouldn't set up routing socket: %screated policy %s creating %d worker processescreating PID filecreating host service principalcreating invocationcreating worker processescurrent privileges:database lockeddebugdeleting database '%s'deleting database of '%s'descriptor %d closed but still in svc_fdsetdetermining master key used for principal '%s'disabling SO_LINGER on TCP socket on %sdo_iprop failed. does not have any appropriate tickets in the cache. dropping %s fd %d from %serror %lderror allocating tcp dispatch private!error compiling converted regexp '%s'error constructing KRB_ERR_FIELD_TOOLONG error! %serror re-encrypting key for principal '%s'file descriptor number %d too highfinished, exitingfor container reference while creating realm '%s'for container reference while modifying realm '%s'for local servicesfor subtree while creating realm '%s'for subtree while modifying realm '%s'get_updates error from master get_updates invalid result from master get_updates master busy; backoff get_updates permission denied get_updates, error returned from master KDC.get_updates, invalid return from master KDC.get_updates, permission denied.getaddrinfo(%s): Cannot determine canonical hostname. getaddrinfo: %s getting config parametersgetting initial credentialsgetting initial ticketgetting local addressesgetting principal from ccachegetting random seedgetting string representation of principal namegss_to_krb5_name: failed display_name status %dhome directory name `%s' too long, can't search for .k5login home directory path for %s too long host/domain name not foundin krb5_auth_con_setaddrsinfoinitializinginitializing ACL fileinitializing kerberos libraryinitializing networkinvalid enctype %sinvalid search scope while creating realm '%s'iprop_full_resync call failediprop_get_updates call failedkadm5 initialization failed! kadm5 initialization succeeded kadm5_hook %s failed postcommit %s: %skerberos principal is already linked to a ldap objectkeyfile (%s) is not a regular file: %skeytab specified, forcing -k kpropd: Full resync needed.ksu: couldn't set environment variable %s ksu: couldn't set environment variable HOME ksu: couldn't set environment variable SHELL ksu: couldn't set environment variable USER ksu: initgroups failed. ksu: permission denied (shell). ksu: unknown login %s ksu: who are you? ldap object is already kerberizedlink information can not be set/updated as the kerberos principal belongs to an ldap objectlistening on fd %d: rpc %slistening on fd %d: tcp %slistening on fd %d: udp %s%smalformed credential cache name %s mapping update logmaster key stash file needs updating, command abortingmaster keylist not initializedmissing principal nameno IPV6_V6ONLY socket option supportno data available for host/domain nameno sockets set up?nonce modified in FAST response: KDC response modifiednot checking transit pathopening default ccacheoperation can not continue, more than one entry with principal name "%s" foundparsing client namepassword quality module %s rejected password for %s: %sperforming %s dumppktinfo says local addr is %splugin symbol 'kdb_function_table' lookup failed: %splugin unavailable: %spreauth %s failed to initialize: %spreauth %s failed to setup loop: %sprincipal name %s too long for internal buffer space program name too long - quitting to avoid triggering system logging bugsrcache not owned by %dread %d from routing socket but msglen is %dreading update log headerready realm object value: rename of temporary keyfile (%s) to (%s) failed: %srenew until renewing credentialsresolving ccache %sresolving default client keytabresolving keytab %sroutine errorrouting socket is fd %dservice name unknownservice not availableset up %d socketssetpw request from %s by %.*s%s for %.*s%s: %ssetsockopt(%d,IPV6_V6ONLY,1) failedsetsockopt(%d,IPV6_V6ONLY,1) workedsetting up network...short read (%d/%d) from routing socketshort reply write %d vs %d shutting downsignal %d received in supervisorsignaled from serversignalled from serverskipping: %s spawning daemon processspecified for search scope while modifying information of realm '%s'standard inputstartingsubtree value: successsupplementary info codeterminal name %s too long there must be one master key currently activeticket policy object value: ticket policy object: too many connectionstrying to process principal databaseulog_replay failed (%s), updates not registered ulog_replay failed (%s), updates not registered.unable to decode stored principal key data (%s)unable to find plugin [%s]: %sunable to load DLL [%s]unable to load plugin [%s]: %sunexpected error checking transit from '%s' to '%s' via '%.*s%s': %sunhandled routing message type %d, will reconfigure just for the fun of itunknown addrtype %dunknown code 0x%xunknown failureunknown getaddrinfo failureunknown option '%s'unknown option: %sunknown record type "%s" unprintable address (type %d, error %d %s)updating: %s usage: %s (-key | -password) -p principal -k kvno -e enctype usage: %s [-C] [-u] [-c ccache] [-e etype] usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname] [-R replaycachename] [-m] [-k masterenctype] [-M masterkeyname] [-p port] [-P pid_file] [-n] [-w numworkers] [/] where, [-x db_args]* - Any number of database specific arguments. Look at each database module documentation for supported arguments usage: %s [principal] usage: add_principal [options] principal usage: change_password [-randkey] [-keepold] [-e keysaltlist] [-pw password] principal usage: del_string principal key usage: delete_policy [-force] policy usage: delete_principal [-force] principal usage: get_policies [expression] usage: get_policy [-terse] policy usage: get_principal [-terse] principal usage: get_principals [expression] usage: get_privs usage: get_strings principal usage: modify_principal [options] principal usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] principal usage: rename_principal [-force] old_principal new_principal usage: set_string principal key value usage; %s [options] policy validating credentialsvariable missing }waiting for a kprop connection waitpid() failed to wait for doit() (%d %s) when creating default server principal namewhen gathering parameterswhen initializing cache %swhen parsing name %swhen unparsing namewhile %swhile accepting connectionwhile adding entries to databasewhile adding entries to the databasewhile adding key to keytabwhile adding master key entry to the databasewhile adding new entrywhile adding new master keywhile adding preauth optionwhile allocating args.kvnoswhile allocating dump_ok filenamewhile allocating filename for temp filewhile allocating filename for update_last_prop_filewhile allocating i_vectorwhile allocating key_datawhile allocating memorywhile allocating memory for the target ccache namewhile allocating temporary filename dumpwhile appending realm to principalwhile attempting setsockopt (SO_KEEPALIVE)while attempting to connect to master KDC ... retryingwhile attempting to retrieve default realmwhile authenticating to serverwhile binding listener socketwhile building TGS name for realm %swhile building principalwhile calculated master key saltwhile calculating master key saltwhile calling cc_filterwhile calling waitpidwhile canonicalizing new principalwhile canonicalizing old principalwhile canonicalizing principalwhile canonicalizing principal namewhile changing %s's keywhile changing password for "%s".while changing to target uid for destroying ccachewhile checking authorizationwhile checking if stdin is a socketwhile clearing DISALLOW_ALL_TIX for "%s".while clearing the value of %swhile closing ccachewhile closing ccache %swhile closing databasewhile closing keytabwhile closing previous databasewhile connecting to serverwhile constructing my service realmwhile converting %s to new master keywhile converting etypewhile converting local addresswhile converting server addresswhile copying cache %s to %swhile copying client principalwhile creating 'last_prop' file, '%s'while creating 'ok' file, '%s'while creating PID filewhile creating databasewhile creating database '%s'while creating keytab namewhile creating main loopwhile creating new master keywhile creating new target ccachewhile creating policywhile creating policy "%s".while creating policy objectwhile creating principal %swhile creating realm '%s'while creating socketwhile creating sub-command argumentswhile creating temporary cachewhile creating tgt for local realmwhile creating update logwhile decoding database size from clientwhile decoding error packet from clientwhile decoding error response from serverwhile decoding ticket for %swhile decrypting ticket for %swhile deleting attribute from principal "%s"while deleting bad database %swhile deleting entry %dwhile deleting entry from keytabwhile deleting policy "%s"while deleting principal "%s"while destroying cachewhile destroying cache %swhile destroying policy objectwhile detaching from ttywhile determining local service principal namewhile determining target ccache namewhile dispatching (tcp)while dispatching (udp)while downgrading lock on '%s'while encoding database sizewhile ending keytab scanwhile erasing target cachewhile expanding expression "%s".while fetching master key %s for realm %swhile fetching master keys list for realm %swhile fetching principal %swhile finding master keys in usewhile finding mkeywhile finishing ticket retrievalwhile forkingwhile formatting master principal namewhile formatting parsed principal name for '%s'while freeing ktlistwhile freeing principal entrywhile generating new ccachewhile generating part of the target ccache namewhile getting "%s".while getting attributes for principal "%s"while getting client principal namewhile getting context for realm %swhile getting credentials for %swhile getting current timewhile getting default ccachewhile getting default client keytabwhile getting default keytabwhile getting default realmwhile getting enctype descriptionwhile getting initial credentialswhile getting initial credentials while getting keytab namewhile getting local socket addresswhile getting master key listwhile getting master key principal %swhile getting name of target ccachewhile getting policy info.while getting principal info.while getting source cachewhile getting timewhile getting time of daywhile initializingwhile initializing %s interfacewhile initializing %s interface, retryingwhile initializing Kerberos 5 librarywhile initializing Kerberos codewhile initializing SAMwhile initializing databasewhile initializing database for realm %swhile initializing error handlingwhile initializing i_vectorwhile initializing krb5while initializing krb5 librarywhile initializing krb5_contextwhile initializing ldap handlewhile initializing lookaside cachewhile initializing networkwhile initializing random key generatorwhile initializing routing socketwhile initializing server listwhile initializing signal handlerswhile initializing target cachewhile initializing the Kerberos admin interfacewhile initializing update logwhile listing ccache collectionwhile listing credential cacheswhile listing policy objectswhile listing realmswhile loading audit plugin module(s)while locking 'ok' file, '%s'while looking for credentials cache %swhile looking up active kvno listwhile looking up active master keywhile looking up active version of master keywhile looking up mkey aux data listwhile looking up the Kerberos configurationwhile making newly loaded database livewhile mapping update logwhile modifying "%s".while modifying information of realm '%s'while modifying policy "%s".while modifying policy objectwhile obtaining socketwhile opening %swhile opening %s for writingwhile opening ccachewhile opening credential cache %swhile opening credentials cache %swhile opening databasewhile opening database file, '%s'while opening default credentials cachewhile opening default keytabwhile parsing -add principal name %swhile parsing admin principal namewhile parsing command argumentswhile parsing command arguments while parsing keysalts %swhile parsing name %swhile parsing new principal namewhile parsing old principal namewhile parsing optionswhile parsing principalwhile parsing principal namewhile parsing principal name %swhile parsing temporary namewhile permanently locking databasewhile providing time specificationwhile purging keys for principal "%s"while randomizing key for "%s".while reading Kerberos container informationwhile reading cache name from ccachewhile reading information of policy '%s'while reading information of realm '%s'while reading kerberos container informationwhile reading keytab "%s"while reading ldap configurationwhile reading ldap parameterswhile reading master keywhile reading master key from keyboardwhile reading new master keywhile reading new master key from keyboardwhile reading new password.while reading passwordwhile reading password for "%s".while reading password for '%s' while reading realm informationwhile reading response from serverwhile reading size of database from clientwhile reading srvtab "%s"while reading update log headerwhile receiving from networkwhile reclaiming root uidwhile reinitializing update logwhile renaming %s to %swhile renaming dump file into placewhile renaming principal "%s" to "%s"while resetting target ccache namewhile resolving %swhile resolving ccache %swhile resolving kdb keytab for realm %swhile resolving keytabwhile resolving keytab %swhile restarting keytab scanwhile retreiving configuration parameterswhile retrieving "%s".while retrieving a ticketwhile retrieving creds from cachewhile retrieving highest kvno from keytabwhile retrieving ldap configurationwhile retrieving list.while retrieving master entrywhile retrieving policy "%s".while retrieving principalwhile retrieving principal namewhile retrieving privilegeswhile returning to source uid after finding best principalwhile saving principal %swhile scanning keytabwhile searching for ccache for %swhile seeding random number generatorwhile selecting the best principalwhile sending # of received byteswhile sending database block starting at %dwhile sending database sizewhile sending reply to %s/%s from %swhile setting '%s'='%s'while setting FAST ccachewhile setting SO_REUSEADDR optionwhile setting attribute on principal "%s"while setting changetimewhile setting client principal namewhile setting client principal realmwhile setting default realm namewhile setting default realm to %swhile setting euid to source userwhile setting server principal namewhile setting service object passwordwhile setting up KDB keytab for realm %swhile setting up enctype %dwhile setting up lib handlewhile setting up loggingwhile setting up master key namewhile setting up master key name %s for realm %swhile starting keytab scanwhile starting to retrieve ticketswhile storing %swhile storing credentialswhile storing keywhile switching back from target after authorization checkwhile switching to credential cachewhile switching to new ccachewhile switching to target for authorization checkwhile switching to target uidwhile temporarily ending keytab scanwhile transforming master key from passwordwhile trying to change password.while trying to close database filewhile trying to construct host service principalwhile trying to construct my service namewhile trying to exec %swhile trying to execv %swhile trying to fork %swhile trying to fork.while trying to lock '%s'while trying to malloc data_ok_fnwhile trying to open %swhile trying to stat %swhile unlocking '%s'while unlocking databasewhile unlocking database '%s'while unlocking locked databasewhile unparsing client namewhile unparsing principalwhile unparsing principal namewhile unparsing server namewhile unparsing ticket etypewhile unsetting IPV6_V6ONLY optionwhile updating actkvno data for master principal entrywhile updating mkey_aux data for master principal entrywhile updating principal '%s' key data in the databasewhile updating principal '%s' modification timewhile updating the master key principal modification timewhile verifying master keywhile verifying ticket for serverwhile viewing policywhile viewing policy '%s'while waiting for %swhile waiting to receive databasewhile writing keytab "%s"while writing update log headerworker %ld exited with status %dwould skip: %s would update: %s wrong oid yet no policy set! Contact your system security administrator.Project-Id-Version: mit-krb5 13.2 Report-Msgid-Bugs-To: krbdev@mit.edu POT-Creation-Date: 2015-05-06 14:59-0400 PO-Revision-Date: 2016-04-07 08:15+0200 Last-Translator: Chris Leick Language-Team: German Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n != 1; -n löst nicht rückwärts auf. -K zeigt die Schlüssel der Schlüsseltabelleneinträge. -a zeigt die Adressliste. -d zeigt die übertragenen Autorisierungsdatentypen. t -f zeigt die Anmeldedatenschalter. -s setzt den Exit-Status auf Basis der Existenz eines gültigen TGTs. -t zeigt die Zeitstempel der Schlüsseltabelleneinträge. Attributschalter fehlgeschlagener Passwortversuch Schlüsseldaten letzte fehlgeschlagene Authentifizierung letzte erfolgreiche Authentifizierung Länge maximale verlängerbare Lebensdauer maximale Ticketlebensdauer Änderungszeit Geändert wobei tPrincipal wird geändert Ablauf des Passworts Passwortchronik Passwortchronik KVNO letzte Passwortänderung Passwortrichtlinie Passwortrichtlinienumschalter Principal Ablauf des Principals TL-Daten [-lockoutduration Dauer] [-maxlife Zeit] [-minlife Zeit] [-minlength Länge] [-minclasses Anzahl] [-history Nummer] [-maxfailure Anzahl] [-failurecountinterval Zeit] [-allowedkeysalts Schlüssel-Salts] [-randkey|-nokey] [-x DB-Principal-Argumente]* [-expire Ablaufdatum] [-pwexpire Passwortablaufdatum] [-maxlife maximale_Ticketlebensdauer] [-kvno KVNO] [-policy Richtlinie] [-clearpolicy] [-pw Passwort] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern] [-e Schlüssel-Salt-Liste] [{+|-}Attribut] [-x DB-Principal-Argumente]* [-expire Ablaufdatum] [-pwexpire Passwortablaufdatum] [-maxlife maximale_Ticketlebensdauer] [-kvno KVNO] [-policy Richtlinie] [-clearpolicy] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern] [-unlock] [{+|-}Attribut] allow_postdated allow_forwardable allow_tgs_req allow_renewable allow_proxiable allow_dup_skey allow_tix requires_preauth requires_hwauth needchange allow_svr password_changing_service ok_as_delegate ok_to_auth_as_delegate no_auth_data_required wobei [-x DB-Principal-Argumente]* - eine beliebige Zahl datenbankspezifischer Argumente ist. Die unterstützten Argumente finden Sie in der jeweiligen Datenbankdokumentation. (Voreinstellung ist Anmeldedatenzwischenspeicher) -A vernichtet alle Anmeldedatenzwischenspeicher in der Sammlung. -a bezieht Adressen nicht ein. -A zeigt den Inhalt aller Anmeldedatenzwischenspeicher an. -C bringt in Normalform -E Client ist der Principal-Name des Unternehmens -F nicht weiterleitbar -P Proxy nicht nutzbar -R erneuert -S Dienst -T gehärteter Anmeldedatenzwischenspeicher -V zeigt die Kerberos-Version und wird beendet. -V detaillierte Ausgabe -X [=] -a bezieht Adressen ein. -c Kerberos-5-Zwischenspeichername -c gibt den Anmeldedatenzwischenspeicher an -c gibt den Namen des Zwischenspeichers für Anmeldedaten an. -e zeigt den Verschlüsselungstyp. -f weiterleitbar -i verwendet die Standardschlüsseltabelle des Clients (mit -k). -i verwendet die Standardschlüsseltabelle des Clients, falls kein Name angegeben wurde. -k gibt die Schlüsseltabelle an. -k verwendet Schlüsseltabelle -l Lebensdauer -l listet gesammelte Anmeldedatenzwischenspeicher auf. -n anonym -p Proxy nutzbar -p gibt den Namen des Principals an. -q stiller Modus -r verlängerbare Lebensdauer -s Startzeit -t Dateiname der zu verwendenden Schlüsseltabelle -v überprüft Adressen: Adressen: (keine) geänderte Attribute: %d Blockgrößeneintrag: %u erste Seriennummer: erste Seriennummer: keine erster Zeitstempel: %s erster Zeitstempel: keiner letzte Seriennummer: letzte Seriennummer: keine letzter Zeitstempel: %s letzter Zeitstempel: keiner Protokollstatus: Protokollversion #: %u Anzahl der Einträge: %u Aktualisierung übergeben: %s Aktualisierungsaktion: Aktualisierung des Principals: %s Aktualisierung der Seriennummer: %u Größe der Aktualisierung: %u Zeitstempel der Aktualisierung: %s Zeitstempel der Aktualisierung: keiner [-A Serveradministrator] [-F Kerberos-Datenbankdatei ] [-p KDB5-Hilfswerkzeugpfadname] [-k Schlüsseltabelle] [-S Sname] [-U für_Benutzer [-P]] [-x Datenbankargumente]* [-P Port] [-a ACL-Datei] Es gibt folgende Attribute: für Client %s Es gibt folgende Optionen: Optionen für Anmeldedatenzwischenspeicher: Optionen für Schlüsseltabellen: Dienst1 Dienst2 … update_princ_encryption [-f] [-n] [-v] [Principal-Muster] purge_mkeys [-f] [-n] [-v] dabei sind [-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer Argumente. Welche Argumente unterstützt werden, finden Sie in der Dokumentation der jeweiligen Datenbank. (Geben Sie als Bestätigung »yes« ein) Speicher konnte nicht reserviert werden Kerberos-Aktualisierungsprotokoll (%s) Aufruf: %s [-h] [-v] [-v] [-e Zahl] %s -R Aufruf: %s [-r Realm] [-f Datei] [-d] [-P Port] [-s Dienstschlüsseltabelle] untergeordneter_Rechner Aufruf: %s [-r Realm] [-s Dienstschlüsseltabelle] [-dS] [-f untergeordnete_Datei] %s erfolgreich in der Ferne über einen unsicheren (unverschlüsselten) Kanal angemeldet sind. in der Ferne mittels eines unsicheren (unverschlüsselten) Kanals angemeldet sind. GSS-API-Fehlermeldungen vollständig%s beim Rückgängigmachen der Namensauswertung vollständiges erneutes Synchronisieren, das Master-KDC gab einen Fehler zurückKDC kann nicht initialisiert werden. Speicher reicht nicht aus [existiert nicht]$Id$%.*s%s%s. Bitte versuchen Sie es erneut. %d ist kein gültiger KVNO-Wert%d Schlüssel vollständig entfernt %d Schlüssel würde(n) vollständig entfernt. %s: Status %d kann nicht dekodiert werden%s geändert %s-Konstruktion von AP-REQ-Schutz%s enthält einen ungültigen Dateinamen.%s hat nicht die korrekten Rechte für %s, %s wird abgebrochen.%s ist ein ungültiger VerschlüsselungstypLaden von %s beendetOption %s wird nicht unterstütztWert der Option %s fehlt%s gab einen falschen Exit-Status (%d) zurück%s Version %s %s bei %s, wird abgebrochen %s beim Entschlüsseln der FAST-Antwort%s bei der Handhabung des »ap-request«-Schutzes%s beim Öffnen der ACL-Datei %s%s beim Speichern der Anmeldedaten%s(%d): %s %s(%d): Müll am Zeilenende wird ignoriert: %s, wird abgebrochen%s. Bitte versuchen Sie es erneut.%s: Wiederherstellen von %s fehlgeschlagen %s: %s bei %s, wird abgebrochen %s: %s beim Initialisieren des Kontextes, wird abgebrochen %s: %s, wird abgebrochen %s: %s, es wird versucht, den Standard-Realm abzufragen %s: Zu wenig Speicher zum Initialisieren %s: Protokolldatei konnte nicht abgebildet werden %s: ungültiges Passwort %s: KDC kann nicht initialisiert werden. Speicher reicht nicht aus %s: Schlüsseltabelle %s existiert nicht. %s: Für Principal %s existiert kein Eintrag in der Schlüsseltabelle %s. %s: Für den Principal %s mit der KVNO %d existiert kein Eintrag in der Schlüsseltabelle %s. %s: Passwort falsch %s: Passwort bei %s falsch %s: Principal %s existiert nicht. %s: Bei der Standardeingabe scheint es sich nicht um ein Netzwerk-Socket zu handeln (läuft nicht aus Inetd und die Option -S fehlt?). %s: Es gibt nur einen Eintrag für Principal %s in der Schlüsseltabelle %s. %s: unbekannte Iprop-Auszugsversion %d %s: Kopfzeilen des Auszugs in %s können nicht gelesen werden. Ausgabenzeichenkette des KDB5-Hilfswerkzeugs nicht konstruierbar, da zu lang; Speicher reicht nicht aus.%s: Die Ausgabezeichenkette des KDB5-Hilfswerkzeugs kann nicht erstellt werden, weil sie zu lang ist. Der Speicherplatz reicht nicht aus.%s: Speicher für die Realm-Liste kann nicht erlangt werden %s: Realm %s kann nicht initialisiert werden - Einzelheiten finden Sie in der Protokolldatei %s: Realm %s kann nicht initialisiert werden. Speicher reicht nicht aus %s: kann nicht initialisiert werden: Speicher reicht nicht aus. %s: <%s> kann nicht ausgewertet werden %s: eingeschränkte Abtretung fehlgeschlagen%s: IPROP-Dienst wird erstellt (PROG=%d, VERS=%d) %s: falsche Kopfzeilen des Auszugs in %s %s: Die Auszugsversion %s kann nur mit dem Schalter -update geladen werden. %s: Fehler beim Verarbeiten von Zeile %d von %s %s: Fehler beim Schreiben auf %s %s: Fehler beim Schreiben auf Gerät %s %s: exec fehlgeschlagen: %s%s: Verzweigen fehlgeschlagen: %s%s: getclhoststr fehlgeschlagen%s: ungültige Argumente %s: ungültige Beschränkung: %s%s: KVNO = %d %s: KVNO = %d, Schlüsseltabelleneintrag gültig %s: Zeile %d zu lang, wurde gekürzt%s: zu löschender Eintrag muss angegeben werden %s: Die Schlüsseltabelle, die gelesen werden soll, muss angegeben werden. %s: Die zu schreibende Schlüsseltabelle muss angegeben werden. %s: Die zu lesende Dienstschlüsseltabelle muss angegeben werden. %s: Speicherplatz reicht nicht aus %s: Speicher reicht nicht zur Aufzeichnung der Principal-Namen aus%s: Auswertungsprogramm verlor Anzahl! %s: pclose(popen) fehlgeschlagen: %s%s: popen fehlgeschlagen: %s%s: Fehler im regulären Ausdruck: %s %s: Fehler beim Abgleich mit regulärem Ausdruck: %s %s: Server-Identifikator ist NULL%s: setup_gss_names fehlgeschlagen%s: startet … %s: Syntaxfehler in Zeile %d <%10s …>%s: Unstimmigkeit in der markierten Datenliste für %s (%d gezählt, %d gespeichert) %s: Principal kann nicht in die normale Form gebracht werden %s: Es kann kein Principal-Name herausgefunden werden. %s: Standard-Realm kann nicht geholt werden %s: Kiprop-rechnerbasierter Dienstname für Realm %s kann nicht geholt werden %s: Aufruf: %s [-t] [-k] [-e] %s: Warnung – Syntaxfehler bei Protokolleintrag %s: Schreiben der Dienstschlüsseltabelle wird nicht länger unterstützt %s; eingehende Seriennummer=%lu; ausgehende Seriennummer=%lu%s; eingehende Seriennummer=%lu; ausgehende Seriennummer=N/A%spreauth benötigt, aber Hinweisliste ist leer%u Principals verarbeitet: %u aktualisiert, %u bereits aktuell %u Principals verarbeitet: %u würden aktualisiert, %u bereits aktuell »%s« ist keine gültige Option »%s« ist aktueller als »%s«.»%s« nicht gefunden: Wert »%s« fehlt(abgelaufen)(keine Zeichenkettenattribute) (Principal %s)(Geben Sie als Bestätigung »yes« ein)? ** Datenbank »%s« vernichtet ** Datenbank von »%s« vernichtet Die Optionen -Z und -z schließen sich gegenseitig aus. Die Option »-norandkey« ist nur für »kadmin.local« gültig. Die Optionen -z und -Z schließen sich gegenseitig aus. … EINHESCHRÄNKTE DELEGIERUNG s4u-client=%s… PROTOKOLLÜBERGANG s4u-client=%s0 ist kein gültiger KVNO-Wert: %s ist kein gültiger Verschlüsselungstyp: %s ist kein gültiger MkeyVNOEine der Anmeldedaten war ungültig.Es wurde bereits ein neueres Merkmal verarbeitet.Ein Parameter hatte eine falsche FormEin benötigter Eingabeparameter konnte nicht gelesen werden.Ein benötigter Eingabeparameter konnte nicht geschrieben werden.Ein erforderlicher Ausgabeparameter konnte nicht geschrieben werden.Ein Dienst, der zum Verarbeiten der Abfrage erforderlich ist, ist nicht verfügbar.Ein übergebener Name hatte einen nicht unterstützten Typ.Ein Merkmal hatte eine ungültige Meldungsintegritätsprüfung (Message Integrity Check/MIC).Ein Merkmal hatte eine ungültige Signatur.Ein Merkmal war ungültig.AD-TypenALARMDie von der Anwendung angegebene Version der API-Struktur wird nicht länger unterstützt. (Kompilieren Sie die Anwendung mit den aktuellen KADM5-API-Header-Dateien und -Bibliotheken, um dies zu beheben.)Die von der Anwendung angegebene Version der API-Struktur ist den Bibliotheken unbekannt. (Besorgen Sie sich die aktuellen KADM5-API-Header-Dateien und -Bibliotheken und kompilieren Sie die Anwendung neu, um dies zu beheben.)Die von der Anwendung angegebene Version der API-Struktur wird nicht länger von den Bibliotheken unterstützt. (Aktualisieren Sie die Anwendung, dass sie zu der aktuellen API-Version passt, und kompilieren Sie sie, um dies zu beheben.)Die von der Anwendung angegebene Version der API-Struktur wird nicht länger vom Server unterstützt. (Aktualisieren Sie die Anwendung, dass sie zu der aktuellen API-Version passt, und kompilieren Sie sie, um dies zu beheben.)Die von der Anwendung angegebenene API-Version ist den Bibliotheken unbekannt. (Besorgen Sie sich die aktuellen KADM5-API-Header-Dateien und -Bibliotheken und kompilieren Sie die Anwendung neu, um dies zu beheben.)Die von der Anwendung angegebene API-Version ist dem Server unbekannt. (Besorgen und installieren Sie sich den neuesten KADM5-Admin-Server, um dies zu beheben.)ASN.1 falscher Rückgabewert von Gmtimefehlerhaft formatierte ASN.1-KodierungASN.1-Kodierung endete unerwartetASN.1 beim Aufruf der Systemzeitbibliothek gescheitertASN.1-Bezeichner passt nicht zum erwarteten WertLänge von ASN.1 passt nicht zum erwarteten WertASN.1 fehlt erwartetes EOCnicht konstruierte unbestimmte ASN.1-KodierungASN.1-Objekt in Sequenz ausgelassenASN.1-Auswertungsfehlerein erforderliches Feld fehlt in der ASN.1-StrukturASN.1-Typnummern sind inkonsistentASN.1 unerwartete FeldnummerASN.1-Wert zu großAS_REQ (%s) %s: %s: %s für %s%s%sAS_REQ (%s) %s: PROBLEM: Authentifizierungszeit %d, %s, %s für %sAS_REQ: handle_authdata (%d)Abnehmer und Initiator haben keinen gemeinsamen PrüfsummentypZugriff verweigertKonto %s: Autorisierung für %s zum Ausführen von Konto %s: Autorisierung für %s zum Ausführen von %s fehlgeschlagen Konto %s: Autorisierung für %s erfolgreich Konto %s: Autorisierung von %s fehlgeschlagen Hinzufügen zusätzlich Vorauthentifizierung erforderlichAdministratordiensteDer Administrationsrechner unterstützt beim Erstellen von »%s« kein -nokey Verwaltungsanmeldedaten NICHT VERNICHTET keine Tickets erlaubtAlle Schlüssel für Principal »%s« wurden entfernt. Alle Schlüssel sind in Gebrauch, keiner wurde vollständig entfernt. erlaubte Schlüssel-/Salt-Typen: %s alternative Authentifizierungsmethode erforderlichEin erwartetes nachrichtenspezifisches Token wurde nicht empfangen.Ein ungültiger Name wurde übergeben.Ein ungültiger Statuscode wurde übergeben.Es wurde eine nicht unterstützte kritische FAST-Aktion angefordert.Ein nicht unterstützter Mechanismus wurde angefordert.Anonymes Pkinit wird nicht ohne öffentlichen DH-Wert unterstützt.»ap-request«-Schutz nicht mit TGS gestattetSind Sie sicher, dass Sie die Richtlinie »%s« löschen möchten? (yes/no): Sind Sie sicher, dass Sie den Principal »%s« löschen möchten? (yes/no): Sind Sie sicher, dass Sie den Principal »%s« in »%s« umbenennen möchten? (yes/no): Es wurde zweimal versucht, die Datenbank zu sperren.Es wurde versucht, die Datenbank zu entsperren, obwohl sie nicht gesperrt ist.Es wurde versucht, einen unvollständigen Sicherheitskontext zu verwenden.Attribut von Principal »%s« wurde gelöscht. Attribute für Principal »%s« wurden gesetzt. Attribute:Authentifizierungskontext muss lokale Adresse enthaltenAuthentifizierungskontext muss ferne Adresse enthaltenAuthentifiziert %s Authentifiziert für Kerberos v5 Authentifizierung als Principal %s mit Standardschlüsseltabelle Authentifizierung als Principal %s mit existierenden Anmeldedaten Authentifizierung als Principal %s mit Schlüsseltabelle %s Authentifizierung als Principal %s mit Passwort Authentifizierung als Principal %s mit Passwort; Anonymität erwünscht Authentifizierungsversuch fehlgeschlagen: %s, GSS-API-Fehlermeldungen:AuthentifizierungsfehlerAuthentifizierung fehlgeschlagen. Schlüsselziffer hat keinen Unterschlüsselfalsche SAM-Schalter in »obtain_sam_padata«Es wurde eine falsche Anwendungsversion (über Sendauth) verschicktfalsche Prüfsumme in der SAM-Aufforderungfalsche Schalter zum Erstellen der Datenbankfalsche Richtung zum Umwandeln von Schlüsselnfalscher Verschlüsselungstypfalsches Format im Anmeldedatenzwischenspeicherfalsches Format in der Schlüsseltabellefalscher Rechnername des KRB5-Admin-Serversfalscher Wert für die Lebensdauer %s falscher Wert für Lebensdauer (%s Stunden?) falscher Sperrmodusfalsche magische Zahl für FAST-Anfragefalsche magische Zahl für FAST-Antwortfalsche magische Zahl für GSSAPI OIDfalsche magische Zahl für GSSAPI QUEUEfalsche magische Zahl für per FAST geschützte Anfragefalsche magische Zahl für »iakerb_ctx_id_t«falsche magische Zahl für Krb5_address-Strukturfalsche magische Zahl für Krb5_alt_method-Strukturfalsche magische Zahl für Krb5_ap_rep-Strukturfalsche magische Zahl für Krb5_ap_rep_enc_part-Strukturfalsche magische Zahl für Krb5_ap_req-Strukturfalsche magische Zahl für Krb5_auth_context-Strukturfalsche magische Zahl für Krb5_authdata-Strukturfalsche magische Zahl für Krb5_authdata_contextfalsche magische Zahl für Krb5_authenticator-Strukturfalsche magische Zahl für Krb5_ccache-Strukturfalsche magische Zahl für Krb5_krb5_checksum-Strukturfalsche magische Zahl für Krb5_checksum_entry-Strukturfalsche magische Zahl für Krb5_context-Strukturfalsche magische Zahl für Krb5_cred-Strukturfalsche magische Zahl für Krb5_cred_enc_part-Strukturfalsche magische Zahl für Krb5_cred_info-Strukturfalsche magische Zahl für Krb5_creds-Strukturfalsche magische Zahl für Krb5_cryptosystem_entry-Strukturfalsche magische Zahl für Krb5_cs_table_entry-Strukturfalsche magische Zahl für Krb5_data-Strukturfalsche magische Zahl für Krb5_db_context-Strukturfalsche magische Zahl für Krb5_enc_data-Strukturfalsche magische Zahl für Krb5_enc_kdc_rep_part-Strukturfalsche magische Zahl für Krb5_enc_sam_response_encfalsche magische Zahl für Krb5_enc_tkt_part-Strukturfalsche magische Zahl für Krb5_encrypt_bloc-Strukturfalsche magische Zahl für Krb5_error-Strukturfalsche magische Zahl für Krb5_etype_info_entry-Strukturfalsche magische Zahl für »krb5_gss_cred_id_t«falsche magische Zahl für »krb5_gss_ctx_id_t«falsche magische Zahl für »krb5_gss_enc_desc«falsche magische Zahl für Krb5_kdc_rep-Strukturfalsche magische Zahl für Krb5_kdc_req-Strukturfalsche magische Zahl für Krb5_krb5_keyblock-Strukturfalsche magische Zahl für Krb5_keytab-Strukturfalsche magische Zahl für Krb5_keytab_entry-Strukturfalsche magische Zahl für Krb5_last_req_entry-Strukturfalsche magische Zahl für Krb5_os_context-Strukturfalsche magische Zahl für Krb5_pa_data-Strukturfalsche magische Zahl für Krb5_preauth_opsfalsche magische Zahl für Krb5_predicted_sam_responsefalsche magische Zahl für Krb5_principal-Strukturfalsche magische Zahl für Krb5_priv-Strukturfalsche magische Zahl für Krb5_priv_enc_part-Strukturfalsche magische Zahl für Krb5_pwd_data-Strukturfalsche magische Zahl für Krb5_rcache-Strukturfalsche magische Zahl für Krb5_response-Strukturfalsche magische Zahl für Krb5_safe-Strukturfalsche magische Zahl für Krb5_sam_challengefalsche magische Zahl für Krb5_sam_challenge_2falsche magische Zahl für Krb5_sam_keyfalsche magische Zahl für Krb5_sam_responsefalsche magische Zahl für Krb5_sam_response 2falsche magische Zahl für Krb5_ticket-Strukturfalsche magische Zahl für Krb5_tkt_authent-Strukturfalsche magische Zahl für Krb5_transited-Strukturfalsche magische Zahl für Passwd_phrase_elementfalscher Principal beim Versuch, Anmeldedaten weiterzuleitenfalsche Antwort (beim Sendauth-Austausch)Es wurde eine falsche Sendauth-Version verschicktfalscher Wert für die Startzeit %s Bind-DN-Eintrag »%s« fehlt in der LDAP-Passwortdatei »%s«Puffer hat die falsche GrößeVom Master wurde ein Signal empfangen, dass er ausgelastet ist, Zurückhaltung für %d Sekunden KRITISCH»iprop_get_updates_1()« wird aufgerufen (sno=%u sec=%u usec=%u) Hauptschlüssel kann nicht abgeholt werden (Fehler: %s)Der neue ergänzende Zwischenspeicher kann nicht erzeugt werdenDer neue ergänzende Zwischenspeicher kann nicht erstellt werden, da der Standardzwischenspeicher bereits eine Ergänzung ist.Der neue ergänzende Zwischenspeicher kann nicht erstellt werden, da der Standardzwischenspeicher keine Ansammlung von Verzeichnissen ist.Wiederholungszwischenspeicher kann nicht vernichtet werden: %sClient-Principal %s kann nicht in der Zwischenspeicheransammlung gefunden werdenZu UID %lu kann kein Benutzername gefunden werden.Kerberos-Konfigurationsdatei kann nicht geöffnet/gefunden werdendie Lname-Übersetzungsdatenbank kann nicht geöffnet/gefunden werdenRealm-Übersetzungsdatei kann nicht geöffnet/gefunden werdenaus dem Wiederholungszwischenspeicher kann nicht gelesen werden: %sZertifikat kann nicht überprüft werdenin Wiederholungszwischenspeicherdatei kann nicht geschrieben werden: %s%s der Wiederholungszwischenspeicherdatei %s nicht möglich: %s%s des Wiederholungszwischenspeichers nicht möglich: %sServer-Socket kann nicht an %s gebunden werdenmit LDAP-Server »%s« kann keine Verbindung als »%s« hergestellt werden: %smit LDAP-Server »%s« kann keine Verbindung mit SASL-Mechanismus »%s« hergestellt werden: %sGSS-API-Authentifizierungsnamen können nicht gebildet werden.Schlüsseltabelle mit aktiven Schlüsseltabelleniteratoren kann nicht geändert werdengeschützter Principal kann nicht geändert werdenfür Realm »%.*s« kann nicht KDC kontaktiert werdenFür den angeforderten Realm kann kein KDC kontaktiert werden.V5-Adressinformationen können nicht umgewandelt werdenV5-Schlüsselblock kann nicht umgewandelt werdenV5-Principal kann nicht umgewandelt werdenLDAP-Identifikator für »%s« kann nicht erstellt werden: %sRPC-Dienst kann nicht erstellt werden: %s; es wird fortgefahrenAuf %s kann kein TCP-Server-Socket erstellt werden.Zertifikatskette kann nicht erstellt werden: %sTicket für %s kann nicht mittels des Schlüsseltabellenschlüssels für %s entschlüsselt werdenRealm für Rechner kann nicht bestimmt werdenRealm für numerische Rechneradresse kann nicht bestimmt werdenSO_REUSEADDR kann nicht für Dateideskriptor %d aktiviert werdenKDC für Realm »%.*s« kann nicht gefunden werdenKDC für angeforderten Realm kann nicht gefunden werdenDer aktive Hauptschlüssel kann nicht gefunden werden.Schlüssel für %s-KNVO %d kann nicht in der Schlüsseltabelle gefunden werdenSchlüssel für %s-KNVO %d kann nicht in der Schlüsseltabelle gefunden werden (angefragter Ticketserver %s)Hauptschlüsseldatensatz kann nicht in der Datenbank gefunden werdenTicket für angeforderten Realm kann nicht gefunden werdenDer gespeicherte Hauptschlüssel kann nicht gefunden/gelesen werden.»fstat« für Antwortzwischenspeicherdatei %s nicht möglich: %sGSSAPI-Dienstname kann nicht initialisiert werdenAuf dem TCP-Server-Socket kann nicht auf eine Verbindung gewartet werden auf %s.Datenbank kann nicht gesperrt werdenLDAP-Passwortdatei »%s« kann nicht geöffnet werden: %sPasswort kann nicht gelesen werdenRPC-Dienst kann nicht registriert werden: %s; es wird fortgefahrenPaketinformation für UDP-Socket-Adresse %s, Port %d, kann nicht abgefragt werdenAdresse des Admin-Servers »%s« für Realm »%s« kann nicht ermittelt werdenNetzwerkadresse für KDC im angeforderten Realm kann nicht aufgelöst werdenDie Netzwerkadresse für den Admin-Server im angeforderten Realm kann nicht aufgelöst werden.Das Passwort kann nicht erneut verwendet werden.GSS-API-Authentifizierungsnamen können nicht gesetzt werden.Die KDB-Schlüsseltabelle kann nicht eingerichtet werden.Wiederholungszwischenspeicherdatei kann nicht synchronisiert werden: %sin angegebene Schlüsseltabelle kann nicht geschrieben werdenCcache-Funktion nicht unterstützt: nicht implementiertCcache-Funktion nicht unterstützt: Ccache-Typ nur lesbarZertifikat passt nichtAnforderung für Activcard-MechanismusAnforderung für Digital-Pathway-MechanismusAnforderung für erweiterten S/Key-MechanismusAnforderung für Enigma-Logic-MechanismusAnforderung für Security-Dynamics-MechanismusAnforderung für traditionellen S/Key-MechanismusAnforderung vom AuthentifizierungsserverUID wird zu %s (%ld) geändert Prüfsumme muss enthalten seinClient »%s« wurde nicht in der Kerberos-Datenbank gefundenClient-Name passt nichtClient nicht in der Kerberos-Datenbank gefundenClient nicht vertrauenswürdigClient noch nicht gültig – versuchen Sie es später noch einmalClient oder Server hat einen NullschlüsselEintrag des Clients in der Datenbank ist abgelaufenDer Schlüssel des Clients wurde mit einem alten Hauptschlüssel verschlüsselt.Client-/Server-Realm passen in der anfänglichen Ticketanfrage nicht zusammen.Anmeldedaten des Clients wurden widerrufenUhrzeitabweichung zu großZeitversatz in der KDC-Antwort zu großKommunikation mit dem Server fehlgeschlagenBedingter Auszug ist eine nicht dokumentierte Option, die nur für Iprop-Auszüge benutzt wird.Konfigurationsdatei gibt keinen Standard-Realm anVerbindung von %sVerbindung zum Server ist bereits initialisiertVerbindung zum Server nicht initialisiertKontext wurde bereits vollständig eingerichtetUmwandlung in Dienst-Principal für Namenstyp nicht definiertbeschädigt beschädigtes Kopfzeilenprotokoll, wird beendet beschädigter Aktualisierungseintrag Der Principal-Name konnte nicht reserviert werden. Temporärer Schlüsseltabellendateiname konnte nicht erstellt werden.Das Inetd-Socket konnte nicht dupliziert werden: %sDas Erweiterungsmodul %s namens »%s« konnte nicht gefunden werden.Es konnte kein TGT geholt werden für /dev/null konnte nicht geöffnet werden: %sIprop-Ulog kann nicht geöffnet werden. »gss_buffer_t«-Daten konnten reserviert werdenProtokolldatei %s konnte nicht geöffnet werden: %s »database_name« kann nicht gelesen werden Ulog-Datei %s konnte nicht neu initialisiert werden Es wird ein neuer Hauptschlüssel für den Hauptschlüssel-Principal »%s« erstellt. Anmeldedatenzwischenspeicherverzeichnis %s existiert nicht.Anmeldedatenzwischenspeicherverzeichnis %s existiert, ist jedoch kein VerzeichnisAnmeldedatenzwischenspeicher hat kein TGTAnmeldedatenzwischenspeicher ist leerfalsche Form des AnmeldedatenzwischenspeichernamensTyp des Anmeldedatenaufrufs ist unbekanntAnmeldedatenzwischenspeicher-E/A-Aktion fehlgeschlagen (%s)E/A-Aktion für Anmeldedatenzwischenspeicher fehlgeschlagen XXXAnmeldedatenzwischenspeicherdatei »%s« nicht gefundenSchlüsselbund %s des Anmeldedatenzwischenspeichers nicht gefundenAnmeldedatenzwischenspeicherrechte nicht korrektAnmeldedatenzwischenspeichertyp ist bereits registriertAnmeldedaten für den Server wurden widerrufeninterner Fehler des VerschlüsselungssystemsDie aktuell minimale Lebensdauer des Passworts ist nicht abgelaufen.DES-Schlüssel hat falsche ParitätDES-Schlüssel ist schwachDN-Information fehltDN liegt außerhalb ders Teilbaums des RealmsDatenbankfehler! Erforderlicher KADM5-Principal fehltfehlerhaftes DatenbankformatDatenbank wurde bereits initialisiertDatenbank wurde nicht initialisiertDatenbankinkonsistenz entdecktDatenbank ist gesperrt oder wird gerade benutzt – versuchen Sie es später wiederInitialisieren der Datenbankbibliothek fehlgeschlagenDer Datenbankladeprozess für eine vollständige Verbreitung ist abgeschlossen. Datenbankmodul passt nicht zur KDC-VersionDie Datenbank ist zur Zeit nicht geöffnet!Datenbank nicht initialisiertDatenbank nicht gesperrtDatenbankverbreitung auf %s: ERFOLGREICH Datenbank-LesefehlerDatensatz ist unvollständig oder beschädigtDatenbank-SpeicherfehlerDatenbanktyp nicht unterstütztDatenbank wurde während des Lesens geändertDekodieren außerhalb der DatenEntschlüsselungsintegritätsprüfung fehlgeschlagenStandard-Realm nicht gesetztLöschen Löschen fehlgeschlagen: Ein oder mehrere Principals gehören zur Ticket-Richtlinie.Sind Sie sicher, dass die KDC-Datenbank von »%s« gelöscht werden soll? Die in »%s« gespeicherte KDC-Datenbank wird gelöscht. Sind Sie sicher? Kurzfassung im Zertifikat nicht akzeptiertKurzfassung in signierten Daten nicht akzeptiertNOTFALLFEHLER vom Master-KDC zurückgegeben, Ausstieg FEHLER vom Master zurückgegeben, Ausstieg Leere Passwörter sind nicht erlaubt.Kodierung zu langverschlüsselte Aufforderung wurde außerhalb des FAST-Tunnels verwendetVerschlüsselungstyp %s nicht erlaubtVerschlüsselungstyp nicht erlaubtVerschlüsselungstyp %d hat keine PRFEnde des Anmeldedatenzwischenspeichers erreichtEnde der Schlüsseltabelle erreichtDateiende bei der E/A des WiederholungszwischenspeichersGeben Sie # einGeben Sie die den DN des Kerberos-Containers ein: Geben Sie den Wert des Einwegpasswort-Tokens anGeben Sie es erneut ein.Geben Sie ein neues Passwort ein.Geben Sie das Passwort für Principal »%s« ein.Eintrag existiert bereits in der DatenbankDekodieren der eingetragenen Daten fehlgeschlagen Der Eintrag für Principal %s mit KVNO %d wurde aus der Schlüsseltabelle %s entfernt. Der Eintrag für Principal %s mit KVNO %d und Verschlüsselungstyp %s wurde der Schlüsseltabelle %s hinzugefügt. FehlerFehler beim Erstellen der Datei %sFehler in »krb5_auth_con_ini«: %sFehler in »krb5_auth_con_setaddrs«: %sFehler in »krb5_auth_con_setflags«: %sFehler in »krb5_copy_prinicpal«: %sFehler in »krb5_kt_resolve«: %sFehler in »krb5_recvauth«: %sFehler beim Verarbeiten der LDAP-Datenbankparameter:Fehler beim Lesen des Attributs »%s«: %sFehler beim Lesen der LDAP-Server-Parameters:Fehler beim Lesen des Container-Objekts: Fehler beim Lesen des Kerberos-Container-Speicherorts aus der »krb5.conf«.Fehler beim Lesen des Passworts aus der Ablage: Fehler beim Lesen der Passwortdatei für das DienstobjektFehler beim Lesen der Ticket-RichtlinieFehler beim Lesen der Ticket-Richtlinie:Fehlermeldung vom Client: %s Fehlermeldung vom Server: %s Fehler beim Schreiben in den AnmeldedatenzwischenspeicherFehler beim Schreiben in SchlüsseltabelleFehler: falscher Eintrag – %s in Datei %s. CMD_PATH enthält keine Pfade. Fehler: falscher Eintrag – %s in Datei %s muss entweder ein vollständiger Pfad oder nur ein Befehlsname sein. Fehler: falscher Eintrag – %s in Datei %s. Da %s nur ein Befehlsname ist, muss CMD_PATH definiert sein. Fehler: falscher Pfad %s in CMD_PATH für %s muss mit »/« beginnen Fehler: nicht gefunden -> Etype (Skey, TKT): %s, Innerhalb des FAST-Containers wird »FX_ERROR pa-data« erwartet.Ablaufdatum: %s exponentieller Wartezyklus zusätzliche Argumente (beginnend mit »%s«) FAST-geschützte Vorauthentifizierung erforderlich, aber nicht vom KDC unterstütztFAST-»req_checksum« ungültig; Anfrage geändertDer FAST-Anwort fehlt die Beendigungsnachricht in der KDC-AnwortHolen von Objektbezügen fehlgeschlagenFehlgeschlagene Anmeldeversuche: %d Das Umwandeln des Passworts in Dezimalschreibweise ist fehlgeschlagen.Datei %s konnte nicht geöffnet werden: %sNeukonfiguration des Netzwerks fehlgeschlagen, wird beendetSchreiben des Passworts für das Dienstobjekt in eine Datei fehlgeschlagenFehlschlag!Feld ist für diese Implementierung zu langSchalter: %svollständige Verbreitungsübertragung beendet vollständige Verbreitungsübertragung gestartet Fehler beim vollständigen erneuten Synchronisieren vom Master Beim vollständigen erneuten Synchronisieren gab der Master ein ungültiges Ergebnis zurück. erneutes vollständiges Synchronisieren erforderlich vollständiges erneutes Synchronisieren nicht gestattet Anfrage nach vollständigem erneuten Synchronisieren genehmigt Anfrage nach vollständigem erneuten Synchronisieren genehmigtvollständiges erneutes Synchronisieren, ungültiger Rückgabewert vom Master-KDCvollständiges erneutes Synchronisieren, nicht gestattetGSS-API- (oder Kerberos-) Fehlerallgemeiner Fehler (siehe E-Text)allgemeiner Fehlschlag der Vorauthentifizierungallgemeiner ferner Fehler: %s allgemeiner unbekannter Wiederholungszwischenspeicherfehlerallgemeiner unbekannter Wiederholungszwischenspeicher-/E/A-Fehlerallgemeiner AktualisierungsprotokollfehlerAuf Wiedersehen inkrementelle Aktualisierungen erhalten (sno=%u sec=%u usec=%u) Signal zur Anfrage des Beendens empfangenSignal zum Zurücksetzen empfangenHW-Authentifizierung erforderlichChronikeintrag enthält keine SchlüsseldatenRechnername kann nicht in Normalform gebracht werdenRechnername in der Zeichenkette »SERVICE-NAME« konnte nicht in Normalform gebracht werdenE/A-Fehler im Wiederholungszwischenspeicher-E/A-Codeungültiges Zeichen in Komponentennamewiderrechtlicher Konfigurationsparameter für lokalen KADM5-Clientwiderrechtlicher Konfigurationsparameter für fernen KADM5-ClientWiderrechliches Realm-übergreifendes Ticketunzulässiger Richtliniennameunzulässiger Principal-Nameungültige Verwendung eines PlatzhaltersUngültige Versionsnummer für KRB5_TL_ACTKVNO %d Ungültige Versionsnummer für KRB5_TL_MKEY_AUX %d Format der Kerberos-Konfigurationsdatei ist ungeeignetFormat der Realm-Übersetzungsdatei ist ungeeignetFormat des Eintrags der Übersetzungsdatenbank ist ungeeignetungeeigneter Prüfsummentyp in der Nachrichtinkonstistenter SchlüsselzweckFalsche Kanalbindungen wurden übergeben.falsche Nachrichtenrichtungfalsche Netzwerkadressefalsches Passwortfalsches Passwort in verschlüsselter Aufforderungfalsche Sequenznummer in der Nachrichtinkrementelle Verbreitung aktiviert inkrementelle Aktualisierungen: %d Aktualisierungen / %lu usinkrementelle Aktualisierungen: %d Aktualisierungen / %lu us anfängliche Ticket-Antwort scheint ein Fehler der Version 4 zu seinErstpasswort erforderlichinitialisierter Zwischenspeicher Datenbank »%s« für Realm »%s« wird initialisiert, Hauptschlüsselname »%s« Datenbank für Realm »%s« wird initialisiert Kadm5 wird als Client %s initialisiert unsicherer Dateimodus für Wiederholungszwischenspeicherdatei %sunsicherer mkstemp()-Dateimodus für Antwortzwischenspeicherdatei %s; versuchen Sie, dieses Programm mit der Umask 077 auszuführenkeine ausreichenden Zugriffsrechte zum Sperren der DatenbankZugriffsrechte reichen nicht zur Durchführung der angeforderten Aktionunzureichende Berechtigung für diese Aktionkeine ausreichenden Rechte zum Sperren der DateiPlatz reicht nicht zur Rückgabe aller Informationen ausPlatz im System reicht nicht zum Speichern der Wiederholungsinformationeninterner Anmeldedatenzwischenspeicherfehlerinterner Fehler beim Auswerten von »X509_user_identity« Interner Fehler: Befehl %s wurde nicht aufgelöst ungültig!ungültige Kombination von KDC-Optionen (interner Bibliotheksfehler)ungültiger Kerberos-Container-DNungültige UID im beständigen Schlüsselbundnamenungültige UTF-8-Zeichenketteungültige Zusatzattributeungültiges Zertifikatungültige Anmeldedaten wurden übergebenungültige Datumsangabe »%s« ungültiger Verschlüsselungstyp in der SAM-Aufforderungwiderrechtlicher Verschlüsselungstyp für Setv4keyfalsche Feldlänge im Tokenungültige Feldmaske für Aktionungültiger Schalter für den Datei-Sperrmodusungültiges Format der Kerberos-Lebensdauer oder der Zeitversatzzeichenketteungültiger KDB-Sperrmodusungültige Parameter zum Erzeugen von Schlüsseln vom KDCungültige Schlüssel-/Salt-Tupelungültiger Schlüsselbundverankerungsnameungültiger Nachrichtentypder zum Kodieren angegebene Nachrichtentyp ist ungültigungültige Modulangabeungültiger Modulbezeichner %sungültige Anzahl von Zeichenklassenungültige Passwortchronikanzahlungültige Passwortlängeungültiges Pkinit-Paket: Achtbit-Zeichenkette erwartetungültiger Richtliniennameungültiger Principal-Nameungültige Signaturungültiges TokenEs wurde ein ungültiges Token übergeben.Iprop nicht aktiviert Es ist wichtig, dass Sie dieses Passwort NICHT VERGESSEN. Sperrdatei der KADM5-Verwaltungsdatenbank fehltAntwort des KCM-Daemons zu großKDB-Modul benötigt Argument »-update«KDC-DiensteKDC kann erforderliche Option nicht erfüllenKDC unterstützt diesen Prüfsummentyp nichtKDC unterstützt diesen Verschlüsselungstyp nichtKDC unterstützt diesen Padata-Typ nichtKDC unterstützt diesen Übergangstyp nichtKDC wurde mit dem Master synchronisiert. KDC-Name passt nichtKDC nicht vertrauenswürdigKDC-Richtlinie weist die Anfrage zurückKDC-Richtlinie verwirft durchgereichten PfadKDC-Antwort entsprach nicht den ErwartungenKDC gab eine Fehlermeldung zurück: %.*sKRB5-Fehlercode 101KRB5-Fehlercode 102KRB5-Fehlercode 103KRB5-Fehlercode 104KRB5-Fehlercode 105KRB5-Fehlercode 106KRB5-Fehlercode 107KRB5-Fehlercode 108KRB5-Fehlercode 109KRB5-Fehlercode 110KRB5-Fehlercode 111KRB5-Fehlercode 112KRB5-Fehlercode 113KRB5-Fehlercode 114KRB5-Fehlercode 115KRB5-Fehlercode 116KRB5-Fehlercode 117KRB5-Fehlercode 118KRB5-Fehlercode 119KRB5-Fehlercode 120KRB5-Fehlercode 121KRB5-Fehlercode 122KRB5-Fehlercode 123KRB5-Fehlercode 124KRB5-Fehlercode 125KRB5-Fehlercode 126KRB5-Fehlercode 127KRB5-Fehlercode 30KRB5-Fehlercode 53KRB5-Fehlercode 54KRB5-Fehlercode 55KRB5-Fehlercode 56KRB5-Fehlercode 57KRB5-Fehlercode 58KRB5-Fehlercode 59KRB5-Fehlercode 82KRB5-Fehlercode 83KRB5-Fehlercode 84KRB5-Fehlercode 87KRB5-Fehlercode 88KRB5-Fehlercode 89KRB5-Fehlercode 90KRB5-Fehlercode 91KRB5-Fehlercode 92KRB5-Fehlercode 94KRB5-Fehlercode 95KRB5-Fehlercode 96KRB5-Fehlercode 97KRB5-Fehlercode 98KRB5-Fehlercode 99KVNO des neuen Hauptschlüssels passt nicht zum erwarteten WertKVNO: %d KVNO: %d, Verschlüsselungstyp: %s, aktiviert auf: %s KVNO: %d, Verschlüsselungstyp: %s, aktiviert auf: %s * KVNO: %d, Verschlüsselungstyp: %s, keine Aktivierungszeit gesetzt Kerberos 4 wird nicht mehr unterstützt. Erstellen des Kerberos-Containers FEHLGESCHLAGEN: %sLöschen des Kerberos-Containers FEHLGESCHLAGEN: %sKerberos-Container-Information fehltKerberos-V4-FehlerTabelle magischer Zahlen von Kerberos V5Kerberos-Container-Speicherort nicht angegebenKerberos-Datenbankbeschränkungen verletztinterner Kerberos-DatenbankfehlerInitialisieren der Kerberos-Bibliothek fehlgeschlagenKerberos-Passwort für %s: Kerberos-Dienst unbekanntKerberos 4 Unterstützung ist deaktiviertEs wurde ein zufälliger Schlüssel für %s erzeugt Schlüssel für %s (hexadezimal): Schlüsselparameter nicht akzeptiertDie Schlüssellänge in der Datenbank ist ungültig,Schlüssellänge ist nicht mit dem Verschlüsselungstyp kompatibelSchlüsseltabelleneintrag nicht gefundenSchlüsseltabellendatei »%s« nicht gefundenfalsche Form des SchlüsseltabellennamensSchlüsseltabellentyp ist bereits registriertSchlüsselversion ist nicht verfügbarSchlüsselversionsnummer des Principals in der Schlüsseltabelle ist nicht korrektSchlüsseltabelle %s existiert nicht oder ist leerSchlüsseltabelle enthält keine passenden Schlüssel für %sSchlüsseltabellennamen zu langBeenden des Fullprop-Kindprozesses (%d) wird erzwungen Kpropd sendet Datenbankgröße %d, erwartet wurde %dLDAP-Bindungs-DN-Wert fehltLDAP-Bindungs-Passwortwert fehltzuletzt geändert: %s (%s) Letzte Passwortänderung: %s letzte erfolgreiche Authentifizierung: %s UID bleibt %s (%ld) Zufällige Daten werden geladen.Zufällige Daten werden geladen. lokaler Rechnername konnte nicht bestimmt werdenSchleife innerhalb von »krb5_get_in_tkt« entdecktMKey: vno %d Mach-RPC-Fehler beim der Kommunikation mit dem KCM-DaemonStellen Sie sicher, dass Sie den alten Principal aus allen ACLs entfernt haben, bevor Sie ihn erneut benutzen. Stellen Sie sicher, dass Sie diesen Principal aus allen ACLs entfernt haben, bevor Sie ihn erneut benutzen. Antwort des KCM-Daemons hat die falsche FormDarstellung des Principals in falscher FormFehler wegen Anfrage in falscher FormHauptschlüssel passt nicht zur Datenbankkeine passenden Anmeldedaten gefundenmaximale verlängerbare Lebensdauermaximale Ticketlebensdauermaximale Anzahl falscher Passworteingaben vor dem Sperren: %lu maximale Passwortlebensdauer: %ld maximale verlängerbare Lebensdauer: %s maximale Ticketlebensdauer: %s Mechanismus ist nicht korrektNachrichtenkontext ungültigNachricht ist eine WiederholungNachricht nicht in OrdnungErkennung der Antwortnachricht erfordert den Parameter »rcache«Nachrichtengröße ist nicht mit Verschlüsselungstyp kompatibelNachrichtendatenstrom geändertDie benötigte Mindestanzahl von Verbindungen pro Server ist zweiminimale Anzahl von Passwortzeichenklassen: %ld minimale Passwortlänge: %ld minimale Passwortlebensdauer: %ld sonstiger PRC-Fehler: %s, %ssonstiger Fehlschlagnicht zusammenpassende Verschlüsselungstypen für Setkey3fehlende Prüfsumme in der SAM-Aufforderungfür Kadmin-Client benötigte Parameter fehlen in »krb5.conf«erforderliche ACL-Dateikonfiguration fehlterforderliche Realm-Konfiguration fehltmehrere Werte für einzelnen Verschlüsselungstyp oder Verschlüsselungstyp mit Saltgegenseitige Authentifizierung fehlgeschlagenHINWEIS: Für %s wurde keine Richtlinie angegeben, es wird »default« zugewiesen neues Passwortneues Passwort (erneut)Das neue Passwort kann nicht die Länge Null haben.Das neue Passwort besteht aus zu wenigen Zeichenklassen. Die Zeichenklassen sind: - Kleinbuchstaben, - Großbuchstaben, - Ziffern, - Satzzeichen und - alle anderen Zeichen (z.B. Steuerzeichen). Bitte wählen Sie ein Passwort mit mindestens %d Zeichenklassen.Das neue Passwort ist zu kurz. Bitte wählen Sie ein Passwort, das mindestens %d Zeichen lang ist.Das neue Passwort wurde in einem Wörterbuch mit möglichen Passwörtern gefunden und kann daher leicht erraten werden. Bitte wählen Sie ein anderes Passwort. Hilfe bei der Wahl guter Passwörter finden Sie in der Handbuchseite von »kpasswd«.Das neue Passwort wurde zuvor schon benutzt. Bitte wählen Sie ein anderes Passwort.neue Passwörter stimmen nicht überein – Passwort nicht geändert keine @ in der Namenszeichenkette SERVICE-NAMEkeine DUP_SKEY-Anfragenkein FehlerKein KCM-Server gefundenkeine Kerberos-Anmeldedaten verfügbarkeine TGT-basierten Anfragenkein akzeptables KDF angebotenkein Administrationsserver für den Realm gefundenEs gibt keinen Schutzschlüssel aber eine FAST-geschützte Anfragekeine Autorisierungsdaten erforderlichEs wurde keine Kontext etabliert.kein Anmeldedatenzwischenspeicher gefundenkeine Anmeldedaten mit unterstützten Verschlüsselungstypen gefundender Bibliotheks-Routine wurden keine Anmeldedaten geliefertEs wurden keine Anmeldedaten übergeben.Es wurden keine Anmeldedaten übergeben oder die Anmeldedaten waren nicht verfügbar bzw. ein Zugriff darauf nicht möglich.kein Standard-Realm gesetzt; KDB kann nicht initialisiert werdenkeine Wörterbuchdatei angegeben, es wird ohne fortgefahrenkein FehlerFür %s wurde kein Schlüsseltabelleneintrag gefunden.Es wurde kein zu %s passender Schlüsseltabelleneintrag gefunden.keine Schlüssel in der SchlüsseltabelleFür den Principal-Namen wurde kein lokaler Name gefunden.kein passender Schlüssel im Eintragkein passender Schlüssel in einem Eintrag mit erlaubtem Verschlüsselungstypkein weiterer Speicher zu reservieren (im Anmeldedatenzwischenspeichercode)kein weiterer Speicher reservierbar (im Wiederholungszwischenspeicher-E/A-Code)kein Speicher mehr zu reservieren (im Wiederholungszwischenspeichercode)kein Passwort angegeben Für Realm %s werden keine »pkinit_anchors« bereitgestellt.Für Realm %s wird keine »pkinit_identity« bereitgestellt.Kein Principal in der Schlüsseltabelle passt zum gewünschten Namen.Für Pkinit-Unterstützung wurden keine Realms korrekt konfiguriert.kein derartiger Eintrag in der Datenbankkeine unterstützten Verschlüsselungstypen (Fehler in der Konfigurationsdatei?)keine unterstützten Tokenkein ticketgewährendes TicketFür den angeforderten Principal ist keine Übersetzung verfügbar.keine Optionen der Nutzeridentität angegebennicht weiterleitbarnicht vordatierbarkein hexadezimales PasswortSpeicher reicht nicht aus Proxy nicht nutzbarnicht erneuerbarHinweisAnzahl der Schlüssel: %d Anzahl aufbewahrter alter Schlüssel: %ld OK als VertreterOK, Datenbank »%s« wird gelöscht … OK, die Datenbank von »%s« wird gelöscht … Ok, es wird nichts getan. Ok, die nicht verwendeten Hauptschlüssel von »%s« werden vollständig entfernt … Anforderung des Einwegpassworts:Einwegpasswort-Token-PINWert des Einwegpassworts entspricht keinem Token-FormatAlte Schlüssel für Principal »%s« wurden entfernt. Entweder -c oder -p muss angegeben werden. Nur eine -I-Option ist erlaubt. Nur eine »-c«-Option ist erlaubt. Nur eine der Optionen -c oder -p ist erlaubt. Nur eine -t-Option ist erlaubt. nur ein gehärteter Ccache Nur eine der Optionen -a und -A ist erlaubt. Nur eine der Optionen -f und -F ist erlaubt. Nur eine der Optionen -p und -P ist erlaubt. Nur eine der Optionen -t und-i ist erlaubt. Aktion aus nicht näher beschriebenem Grund fehlgeschlagenAktion erfordert »add«-RechtAktion erfordert das »change-password«-RechtAktion erfordert »delete«-RechtAktion erfordert »get«-RechtAktion erfordert das »list«-RechtAktion erfordert »modify«-RechtAktion erfordert das »set-key«-RechtDie Option -P (eingeschränkte Abtretung) erfordert zur Angabe eine Schlüsseltabelle. Die Option -P (eingeschränkte Abtretung) erfordert die Option -U (Protokollübergang) Die Optionen -u und -S schließen sich gegenseitig aus. Speicherplatz reicht nicht aus. PA-Option %s = %s PRF-Eingabe zu langPROCESS_TGS: Abstammungsprüfung fehlgeschlagenPaket wurde in falscher Richtung erneut abgespieltPassphrase fürPasswortdienstePasswortänderung erforderlichPasswortänderungsdienstDas Passwort kann nicht geändert werden, da es erst vor kurzem geändert wurde. Bitte warten Sie bis %s, ehe Sie es ändern. Falls Sie es vorher ändern müssen, kontaktieren Sie Ihren Systemsicherheitsadministrator.Ändern des Passworts fehlgeschlagenPasswortänderung abgelehntPasswort geändert Passwort beschädigtDas Passwort enthält nicht genug Zeichenklassen.Passwortablaufdatum: %s Passwort abgelaufen. Sie müssen es nun ändern.Rücksetzintervall für zu viele falsch eingebene Passwörter: %s Passwort für »%s«Passwort von »%s« geändert Passwort für %.1000sPasswort für %sPasswort ist abgelaufenDie Passwortchronikschlüssel des Principals passen nicht zusammen.Passwort beim Holen des anfänglichen Tickets falschDas Passwort steht im Passwortwörterbuch.Das Passwort ist zu kurz.Passwortsperrdauer: %s Das Passwort darf nicht mit dem Principal-Namen übereinstimmen.Das Passwort darf keinen Anwenderdaten entsprechen.Die minimale Lebensdauer des Passworts ist größer als die maximale.Passwort stimmt nicht übereinPasswort nicht geändertLesen des Passworts unterbrochenZugriff im Wiederholungszwischenspeichercode verweigertPkinit-Anfrage nicht signiert, Client ist jedoch nicht anonymBitte wählen Sie aus dem Folgenden aus: Bitte geben Sie den neuen Hauptschlüssel ein … Erweiterung unterstützt nicht die SchnittstellenversionErweiterung unterstützt diese Aktion nichtErweiterungsmodulname nicht gefundenRichtlinie »%s« nicht gelöscht Richtlinie existiert nichtRichtlinie ist in BenutzungRichtlinie verwirft durchgereichten PfadRichtlinie: »%s« Richtlinie: %s%s Vorauthentifizierungsmodul %s: %sVorauthentifizierung fehlgeschlagenVorauthentifizierung erforderlichvorzeitiges EOF für Datenbankdatei gefunden!Principal »%s« gelöscht Principal »%s« wurde geändert. Principal »%s« nicht gelöscht Principal »%s« wurde nicht umbenannt. Principal »%s« wurde in »%s« umbenannt. Für Principal %s ist Realm vorhandenPrincipal %s fehlt erforderlicher RealmPrincipal-Container-BezugHinzufügen des Principals fehlgeschlagen: %sLöschen des Principals fehlgeschlagen (es wird versucht, den Eintrag zu ersetzen): %sPrincipal gehört nicht zum RealmPrincipal gehört nicht zum Standard-RealmPrincipal existiert nichtPrincipal hat in der Kerberos-Datenbank mehrere EinträgePrincipal im Anmeldedatenzwischenspeicher entspricht nicht dem gewünschten NamenPrincipal oder Richtlinie existiert bereitsPrincipal oder Richtlinie existiert nichtPrincipal: %s Principals, deren Schlüssel mit dem Hauptschlüssel VNO %u neu verschlüsselt WÜRDEN: Principals, deren Schlüssel mit dem Hauptschlüssel VNO %u neu verschlüsselt werden, falls nötig: Das Programm rief eine veraltete, gelöschte Funktion auf.Dem Programm fehlt es an der Unterstützung des Adresstyps.Dem Programm fehlt es an der Unterstützung für den Prüfsummentyp.Dem Programm fehlt es an der Unterstützung für den Verschlüsselungstyp.Dem Programm fehlt es an der Unterstützung für den Schlüsseltyp.Fehler des Programmierers! Falsche API-StrukturversionFehler des Programmierers! Falsche API-VersionFehler des Programmierers! Falscher Admin-Server-IdentifikatorFehler des Programmierers! Widerrechlicher Listentyp für gekennzeichnete DatenProtokollübergang mit Vertretung erlaubtProtokollversion passt nichtAsymetrische Verschlüsselung nicht unterstütztDer/Die folgende(n) Hauptschlüssel werden/wird von %s vollständig entfernt: RPC-»svc_freeargs« fehlgeschlagen (%s)RPC-»svc_getargs« fehlgeschlagen (%s)RPC-»svc_sendreply« fehlgeschlagen (%s)unbekannte PRC-Anfrage: %d (%s)RSA-MD5 unterstütztZufallszahlengenerator konnte kein Startwert zugewiesen werdenSollen alle Schlüssel neu verschlüsselt werden, die nicht die Hauptschlüssel-VNO %u verwenden?Geben Sie das Passwort für »%s« erneut ein.Geben Sie das Passwort für Principal »%s« erneut ein.Löschen des Realms FEHLGESCHLAGEN: %sRealm-NameRealm-Information nicht verfügbarRealm für KDC nicht lokalDie empfangene Token-Kennung passt nicht zur erwarteten Token-Kennung.Das Ulog wurde neu initialisiert. Iprop wird neu initialisiert, da Aktualisierungen fehlgeschlagen sind Zurückgewiesene Verbindung von nicht authorisiertem Principal %sZurückgewiesene Verbindung von nicht autorisiertem Principal %s Wiederholungszwischenspeicher-E/A-Aktion fehlgeschlagenAuswerte-/Formatfehler im WiederholungszwischenspeichernamensWiederholungszwischenspeichertyp unterstützt keinen beständigen SpeicherWiederholungszwischenspeichertyp ist bereits registriertWiederholungszwischenspeichertyp ist unbekanntAntwort hat die falsche Form des Sitzungschlüssels für eine anonyme AnfrageAnfrage lieferte kein TicketAnfrage ist eine WiederholungDer Anfrage fehlt das zweite Ticket.abgefragter Ticketserver %s wurde in der Schlüsseltabelle gefunden, er passte jedoch nicht zu Server-Principal %sAbgefragter Ticketserver %s KVNO %d mit Verschlüsselungstyp %s in der Schlüsseltabelle gefunden, Ticket kann jedoch nicht entschlüsselt werden.Abgefragter Ticketserver %s KVNO %d wurde in der Schlüsseltabelle gefunden, jedoch nicht mit Verschlüsselungstyp %s.Abgefragter Ticketserver %s KVNO %d wurde nicht in der Schlüsseltabelle gefunden; Schlüsseltabelle ist wahrscheinlich nicht mehr aktuell.Abgefragter Ticketserver %s KVNO %d wurde nicht in der Schlüsseltabelle gefunden; Ticket ist wahrscheinlich abgelaufen.Abgefragter Ticketserver %s wurde nicht in der Schlüsseltabelle gefunden (Ticket KVNO %d).Anfrage: %s, %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%sAnfrage: %s, %s, %s, Client=%s, Dienst=%s, Adresse=%sAnfrage: %s, hervorgebrachter Neusynchronisationsprozess %d, Client=%s, Dienst=%s, Adresse=%sAnfrage: kadm5_init, %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s, Version=%d, Variante=%dAnfrage: kadm5_rename_principal, %.*s%s bis %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%sDie angeforderte effektive Lebensdauer ist negativ oder zu kurz.Der angeforderte Verschlüsselungstyp wird in der Nachricht nicht verwendet.angeforderte »lucid«-Kontextversion nicht unterstütztangeforderter Principal und Ticket passen nicht zusammenangeforderte Protokollversion nicht unterstütztabgefragter Server und Ticket passen nicht zusammenanforderndes Ticket kann keine weiterleitbaren Tickets holenerforderliche Parameter in »kdc.conf« fehlenerforderlicher Vorauthentifizierungsschlüssel nicht bereitgestelltAntwort für UDP zu groß, erneuter Versuch mit TCPWiderrufsstatus nicht verfügbarWiderrufsstatus unbekanntwiderrufenes ZertifikatSAM-AuthentifizierungSPNEGO-Abnehmer hat kein gültiges Token zurückgeliefertSPNEGO-Abnehmer hat keinen Mechanismus ausgewähltSPNEGO kann keine Mechanismen zum Aushandeln finden.SPNEGO ist beim Beschaffen von Anmeldedaten gescheitertSPNEGO ist beim Aushandeln eines Mechanismus gescheitert.STRING-UID-NAME enthält etwas anderes als ZiffernSuchbereichStartwert des Zufallszahlengenerators wird erzeugtSequnznummer im Token ist beschädigtServer %s wurde nicht in der Kerberos-Datenbank gefundenServerfehlerServer nicht in der Kerberos-Datenbank gefundenServer noch nicht gültig – versuchen Sie es später noch einmalServer-Principal %s hat keinen passenden Schlüssel in der SchlüsseltabelleServer-Principal %s passt nicht zum abgefragten Ticketserver %sDer Server-Principal ist nur für »user2user« gültigServer wies Authentifizierung (beim Sendauth-Austausch) zurückEintrag des Servers in der Datenbank ist abgelaufenDer Schlüssel des Servers wurde mit einem alten Hauptschlüssel verschlüsselt.Dienst deaktiviertDienstschlüssel nicht verfügbarDienst antwortet nichtLänge des Dienstpassworts ist NullUm Kadm5 neu zu initialisieren, wird %d Sekunden gewartet (RPC-FEHLER). Um Kadm5 neu zu initialisieren, wird %d Sekunden gewartet (läuft Krb5kdc nicht?). stabil Es wird immer noch auf das vollständige erneute Synchronisieren gewartet. gespeicherte Anmeldedaten Der gespeicherte Hauptschlüssel ist beschädigt.gespeicherter Hauptschlüssel ist nicht aktuellDas Speichern von Abnehmeranmeldedaten wird nicht durch den Mechanismus unterstützt.Das Speichern von Nichtstandardanmeldedaten wird nicht durch den Mechanismus unterstützt.Dateiname des ergänzenden Zwischenspeicherpfads %s beginnt nicht mit »tkt«Ergänzender Zwischenspeicherpfad %s hat kein übergeordnetes Verzeichnis.TeilbaumErfolgDie bereitgestellten Daten werden nicht von dieser Erweiterung behandelt.TCP-Client %s will %lu Byte, Cap ist %luTCP-Socket-Deskriptornummer %d (für %s) zu hochTGS_REQ %s: %s: Authentifizierungszeit %d, %s für %s, 2. TKT-Client %sTGS_REQ (%s) %s: %s: Authentifizierungszeit %d, %s%s %s für %s%s%sTGS_REQ: handle_authdata (%d)TGS_REQ: SITZUNGSSCHLÜSSEL oder BEIDERSEITIGTGS_REQ: UNBEKANNTER SERVER: Server=»%s«TGS_REQ: TGT %s wird erstelltTGS_REQ: alternativer TGT wird erstelltTGT wurde widerrufenTemporäre Ablagedatei existiert bereits: %s.Der IAKERB-Proxy konnte kein KDC finden.Das KDC anwortete dem IAKERB-Proxy nicht.Das KDC sollte diese Anfrage verwerfenDer Kontext ist abgelaufen.Die Verwendung der angegebenen Anmeldedaten passt nicht zur angeforderten Verwendung.Die Aktion wird durch die lokale Sicherheitsrichtinie verboten.Die Aktion wird durch die lokale Sicherheitsrichtinie verboten.Die Aktion oder Option ist nicht verfügbar.Die Aktion oder Option ist nicht verfügbar oder wird nicht unterstützt.Das Passwort kann nur einmal täglich geändert werden.Das Passwort kann nur alle %d Tage geändert werden.Das Passwort muss sich vom vorhergehenden Passwort unterscheiden.Das Passwort muss sich von den vorhergehenden %d Passwörtern unterscheiden.Das Passwort muss mindestens %d Zeichen enthalten.Das Passwort muss mindestens %d Zeichen enthalten.Das Passwort muss Zahlen oder Symbole enthalten. Fügen Sie keinen Teil Ihres Namens in das Passwort ein.Der bereitgestellte Name war nicht mechanismusspezifisch (MN).Die Qualität des Schutzes (quality-of-protection/QOP) konnte nicht bereitgestellt werden.Die angeforderte Qualität des Schutzes konnte nicht bereitgestellt werden.Der referenzierte Kontext ist abgelaufen.Die referenzierten Anmeldedaten sind abgelaufen.Die referenzierten Anmeldedaten sind abgelaufen.Das angeforderte Anmeldedatenelement existiert bereits.Die Routine wurde erfolgreich abgeschlossenDie Routine muss erneut aufgerufen werden, um ihre Funktion zu vervollständigen.Der Salt-Typ des angegebenen Principals unterstützt kein Umbenennen.Das Ticket ist nicht für uns.Das Merkmal war ein Zweitexemplar eines früheren Merkmals.Die Gültigkeitsperiode des Merkmals ist abgelaufen.Es gibt nur einen einzigen Hauptschlüssel, der nicht vollständig entfernt werden kann. Diese Krb5-Bibliothek ist abgelaufen.Diese Anwendung ist abgelaufen.Dies wird das Richtlinienobjekt »%s« löschen, sind Sie sicher? Ticket-Richtlinienname fehltDN des Ticket-Richtlinienobjekts fehltTicket-Richtlinienobjekt-Information fehltTicketzwischenspeicher %cNICHT%c vernichtet! Ticketzwischenspeicher NICHT vernichtet! Ticketzwischenspeicher: %s:%s Standard-Principal: %s Ticket abgelaufenTicket-FlagsDas Ticket hat einen falsch gesetzten Schalter.Ticket ist zum Vordatieren ungeeignetTicket in der KDC-Antwort verändertTicket noch nicht gültigTicket/Schlüsselziffer passen nicht zueinanderToken-Kopfzeilen haben die falsche Form oder sind beschädigtdem Token fehlen DatenToken wurde zurückgeworfenzu wenige Argumentezu viele zeichenkettenabbildenden DatenVerfolgung nicht unterstütztVersuchen Sie es mit einem etwas komplexeren Passwort oder wenden Sie sich an Ihren Administrator.UID lässt sich nicht zu Benutzernamen ermittelnauf die Kerberos-Datenbank kann nicht zugegriffen werdenLetzter Hauptschlüssel kann nicht mit dem bereitgestellten Hauptschlüssel entschlüsselt werden. angeforderter Datenbanktyp kann nicht gefunden werdenangeforderter Datenbanktyp kann nicht gefunden werden. %sStandard-Realm kann nicht geholt werdenBenutzer kann nicht identifiziert werden Der Benutzer kann nicht anhand der Passwortdatei identifiziert werden. Kerberos kann nicht initialisiert werden Vorauthentifizierungskontext konnte nicht initialisiert werden.Signalbehandlungsprogramme in PID %d konnten nicht initialisiert werdenangefordertes Datenbankmodul »%s« kann nicht geladen werden: Erweiterungssymbol »kdb_function_table« nicht gefundenProtokolldatei %s kann nicht abgebildet werden Protokoll kann nicht abgebildet werden! Kerberos-Container kann nicht gelesen werdenRealm kann nicht gelesen werdenHauptschleife konnte nicht neu initialisiert werdenUnauthorisierte Anfrage: %s, %.*s%s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%sunberechtigte Anfrage: %s, Client=%s, Dienst=%s, Adresse=%sUnauthorisierte Anfrage: kadm5_rename_principal, %.*s%s bis %.*s%s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%sin fast_req wurde eine Prüfsumme ohne Schlüssel benutzt%s unbekannt (Feld = %d)unbekanntet FAST-Schutztyp %dunbekannter Schlüsseltabellentypunbekannter Anmeldedatenzwischenspeichertypunbekannte Schlüsselbundsammlungsversionunbekannte Schutzqualität angegebenunbekannter Signaturtyp im Tokenunbekannter Status: %d unbekannte ACL-Aktion »%c« in %snicht spezifizierter GSS-Fehlschlag. Möglicherweise stellt der untergeordnete Code weitere Informationen bereit.nicht näher angegebener Passwortqualitätsfehlschlaginstabil nicht unterstütztes Argument »%s« für DB2nicht unterstütztes Versionsnummernformat des Anmeldedatenzwischenspeichersnicht unterstützter Verschlüsselungstypnicht unterstütztes Versionsnummernformat der Schlüsseltabellenicht unterstützter Vorauthentifizierungstypnicht unterstütztes Versionsnummernformat des Wiederholungszwischenspeichersnicht unterstützter Salt-Typnicht unterstützter Typ bei der Verarbeitung von »%s« nicht unterstützte Version im DatenbankeintragAktualisierungseintrag Fehler beim Umwandeln des AktualisierungsprotokollsAktualisierungsprotokollauszug : Aktualisierungsprotokoll ist beschädigtAktualisierungsprotokoll ist instabilAufruf: %s [-A] [-q] [-c Zwischenspeichername] Aufruf: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-t] [-K]] [Name] Aufruf: %s [-r Realm] [-p Principal] [-q Abfrage] [clnt|lokale Argumente] clnt Argumente: [-s Admin-Server[:Port]] [[-c Ccache]| [-k [-t Schlüsseltabelle]]]|[-n] lokale Argumente: [-x DB-Argumente]* [-d Datenbankname] [-e "enc:Salt …"] [-m] wobei [-x DB-Argumente]* - eine beliebige Anzahl datenbankspezifischer Argumente ist. Die unterstützten Argumente finden Sie in den jeweiligen Datenbankdokumentationen Aufruf: %s [Zielbenutzer] [-n Principal] [-c Quellenzwischenspeichername] [-k] [-D] [-r Zeit] [-pf] [-l Lebensdauer] [-zZ] [-q] [-e Befehl [Argumente …] ] [-a [Argumente …] ] Aufruf: %s Datenbankpfadname Realm-NameAufruf: %s {-c Zwischenspeichername | -p Principal} Aufruf: kadmind [-x Datenbankargumente]* [-r Realm] [-m] [-nofork] [-port Portummer] [-p Pfad_zum_KDB5-Hilfswerkzeug] [-F Auszugsdatei] [-K Pfad_zu_Kprop] [-P PID-Datei] dabei sind [-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer Argumente. Welche Argumente unterstützt werden, finden Sie in der Dokumentation der jeweiligen Datenbank. Aufruf: kdb5_ldap_util [-D Benutzer-DN [-w Passwort]] [-H LDAP-URI] cmd [Befehlsoptionen] create [-subtrees DN-Liste_Teilbäume] [-sscope Suchbereich] [-containerref Container-Bezug-DN] [-m|-P Passwort|-sf Ablagedateiname] [-k mkeytype] [-kv mkeyVNO] [-s] [-maxtktlife maximale_Ticketlebensdauer] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets] [Ticket_Flags] [-r Realm] modify [-subtrees DN-Liste_Teilbäume] [-sscope Suchbereich] [-containerref Container-Bezug-DN] [-maxtktlife maximale_Ticketlebensdauer] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets] [Ticket_Flags] [-r Realm] view [-r Realm] destroy [-f] [-r Realm] list stashsrvpw [-f Dateiname] Dienst-DN create_policy [-r Realm] [-maxtktlife maximale_Ticketlebensdauer] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets] [Ticket_Flags] Richtlinie modify_policy [-r Realm] [-maxtktlife maximale_Ticketlebensdauer] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets] [Ticket_Flags] Richtlinie view_policy [-r Realm] Richtlinie destroy_policy [-r Realm] [-force] Richtlinie list_policy [-r Realm] Aufruf: kdb5_util [-x Datenbankargumente]* [-r Realm] [-d Datenbankname] [-k Mkeytype] [-M Mkeyname] [-kv MkeyVNO] [-sf Ablagedateiname] [-m] Befehl [Befehlsoptionen] create [-s] destroy [-f] stash [-f Schlüsseldatei] dump [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-mkey_convert] [-new_mkey_file mkey-Datei] [-rev] [-recurse] [Dateiname [Principals …]] load [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-update] Dateiname ark [-e Etype-Liste] Principal add_mkey [-e Etype] [-s] use_mkey kvno [Zeit] list_mkeys Aufruf: ktadd [-k[eytab] Schlüsseltabelle] [-q] [-e Schlüssel-Salt-Liste] [-norandkey] [Principal | -glob Principal-Ausdruck] […] Aufruf: ktadd [-k[eytab] Schlüsseltabelle] [-q] [-e Schlüssel-Salt-Liste] [Principal | -glob Principal-Ausdruck] […] Aufruf: ktremove [-k[eytab] Schlüsseltabelle] [-q] Principal [kvno|»all«|»old«] Änderung des Benutzers fehlgeschlagen: %sBenutzer-zu-Benutzer erforderlichStandardzwischenspeicher wird verwendet: %s Existierender Zwischenspeicher wird verwendet: %s Zur Aktualisierung der Ablagedatei werden existierende gelagert Schlüssel verwendet. Schlüsseltabelle wird verwendet: %s Neuer Zwischenspeicher wird verwendet: %s verwendeter Principal: %s Angegebener Zwischenspeicher wird verwendet: %s Angegebener Eingabezwischenspeicher wird verwendet: %s V5-Realm-Name ist länger als die V4-MaximallängeÜberprüfungsfehlerAnbieter:WARNUNG! Wörterbuchdatei %s kann nicht gefunden werden, es wird ohne fortgefahrenWARNUNG! Gefälschte/verstümmelte Anfrage: %d, Client = %.*s%s, Server = %.*s%s, Adresse = %sWARNUNG! Gefälschte/verstümmelte Anfrage: %s, geforderter Client = %.*s%s, Server = %.*s%s, Adresse = %sWARNUNG: Ihr Passwort könnte offengelegt werden, falls Sie es hier eingeben und WARNUNG: Ihr Passwort könnte offengelegt werden, falls Sie es hier eingeben und WARNUNG: Für %s wurde keine Richtlinie angegeben, es wird die Vorgabe »keine Richtlinie« verwandt. WARNUNG: Richtlinie »%s« existiert nicht. vor der erneuten Prufung auf Aktualisierungen wird %d Sekunden gewartet WarnungWarnung! Mehrere DES-CBC-CRC-Schlüssel für Principal %s, Duplikate werden übersprungen. Warnung! Kein DES-CBC-CRC-Schlüssel für Principal %s, es kann kein OV-kompatibler Datensatz erzeugt werden, wird übersprungen Warnung: Ihr Passwort wird in %d Tagen am %s ablaufen.Warnung: Ihr Passwort wird in %d Stunden%s am %s ablaufen.Warnung: Ihr Passwort auf %s wird in weniger als einer Stunde ablaufen.Warnung: Hauptschlüssel kann nicht gelagert werden. Warnung: Es wird ohne Hauptschlüssel fortgefahrenbeim Bestimmen des Dienst-Principal-Namens anhand der Schlüsseltabellebeim Auflösen der Standardschlüsseltabelle des Clientsbeim Rückgängigmachen der Namensauswertungbeim Umwandeln des Verschlüsselungstyps in eine ZeichenketteSind Sie sicher, dass alle nicht verwendeten Hauptschlüssel, die für Principal »%s« gespeichert sind, vollständig entfernt werden sollen? Der/Die folgende(n) Hauptschlüssel würden/würde von %s vollständig entfernt: falscher Principal in der Anfragefalsche ProtokollversionXDR-VerschlüsselungsfehlerSie müssen ein Passwort eingeben. Passwörter müssen mindestens ein Zeichen lang sein. Sie werden nach einem neuen Datenbank-Master-Passwort gefragt. Sie werden nach dem Master-Passwort der Datenbank gefragt. Ihre UID passt nicht zu Ihrem Passworteintrag. [niemals][keins]akzeptierte PRC-Verbindung auf Socket %d von %sKonto %s: Autorisierung fehlgeschlagen addent: Fehler beim Lesen des Schlüssels addent: unerlaubtes Zeichen im Schlüssel dem Haupt-Principal wird ein neuer Hauptschlüssel hinzugefügtPuffer für neue TCP-Sitzung von %s wird reserviertDatenbankdateiname »%s« wird reserviertkrb5_get_init_creds_opt wird reserviert.»ap-request«-Schutz für etwas anderes als den lokalen TGS»ap-request«-Schutz ohne UnterschlüsselAsprintf konnte nicht genug Speicher reservieren, um die Ausgabe bereitzuhaltenes wird davon ausgegangen, dass das IPv6-Socket IPv4 akzeptiertÖffnen der Audit-Erweiterung %s fehlgeschlagen. Fehler=%iInitialisieren von »authdata« %s fehlgeschlagen: %sHandhabung von »authdata« %s fehlgeschlagen: %sAuthentifizierter Client: %s (etype == %s) Authentifizierungsversuche gescheitert: %s, PRC-Authentifizierungsvariante %dfalscher Realm-Übergangspfad von »%s« zu »%s« über »%.*s%s«falscher Dienst-Principal %.*s%skaputte Adresse (Typ %d Länge %d)AufruffehlerSpeicher für Verbindungsinformation kann nicht reserviert werdenE/A-Ereignis kann nicht erzeugt werdenGrößenmerkmale können nicht zugeordnet werden.Richtlinie kann nicht ausgewertet werden (%d gelesen) Zusätzliche Daten können nicht gelesen werden.Schlüsseldaten können nicht gelesen werden.Schlüssellänge und -version können nicht gelesen werden.Schlüsseltyp und -länge können nicht gelesen werden.Namenszeichenkette kann nicht gelesen werden.Principal-Attribute können nicht gelesen werden.Inhalt der markierten Daten kann nicht gelesen werden.Markierter Datentyp und Länge können nicht gelesen werden.Ereignis kann nicht gesichert werdenDas auf eine Verbindung wartende TCP-Socket kann nicht auf nicht-blockierendes %s gesetzt werden.Schlüssel-Salt-Liste kann nicht angegeben werden, wenn der Schlüssel nicht geändert wird change_password: zu wenig Speicher change_password: fehlendes Datenbankargumentchange_password: fehlendes Schlüssel-Salt-Listenargumentchange_password: fehlendes PasswortargumentPasswort wird geändert.check_rpcsec_auth: inquire_context fehlgeschlagen, Stat=%u»chpw«-Anfrage von %s für %.*s%s: %schpw«: Administratorschlüsseltabelle %s konnte nicht geöffnet werdenDie Principal-Namen von Client und Server müssen übereinstimmen.Ccache wird geschlossen.Dateideskriptor %d wird geschlossenAktion wird begonnenCcache-Name wird zusammengesetzt.Parameter für die Datenbank werden berechnet.Wert des Container-Bezugs: Platzhalter »%s« wird in einen regulären Ausdruck umgewandeltDatenbankargumente werden kopiertZurücksetzen kann nicht abgeschlossen werden, Fehler beim Löschen des Kerberos-Containers»date-time«-Zeichenkette »%s« konnte nicht ausgewertet werdenUlog-Kopfzeilen konnten nicht auf die Platte synchronisiert werdenRouting-Socket konnte nicht eingerichtet werden: %serstellte Richtlinie %s %d Arbeitsprozesse werden erzeugtPID-Datei wird erstelltPrincipal des Rechnerdienstes wird erstelltAufruf wird erstelltArbeitsprozesse werden erzeugtaktuelle Rechte:Datenbank gesperrtFehlersuchmeldungDatenbank »%s« wird gelöscht.Die Datenbank von »%s« wird gelöscht.Deskriptor %d geschlossen, aber immer noch in »svc_fdset«Hauptschlüssel, der für Principal »%s« benutzt wird, wird bestimmtSO_LINGER auf dem TCP-Socket auf %s wird deaktiviert»do_iprop« fehlgeschlagen hat keine geeigneten Tickets im Zwischenspeicher. %s Dateideskriptor %d von %s wird verworfenFehler %ldFehler beim Reservieren zum nicht öffentlichen TCP-Versand!Fehler beim Kompilieren des umgewandelten regulären Ausdrucks »%s«Fehler beim Erzeugen des KRB_ERR_FIELD_TOOLONG-Fehlers! %sFehler beim erneuten Verschlüsseln des Schlüssels für Principal »%s«Dateideskriptornummer %d zu hochfertig, wird beendetfür Container-Bezug beim Erstellen von Realm »%s«für Container-Bezug beim Ändern von Realm »%s«für lokale Dienstefür einen Teilbaum beim Erstellen von Realm »%s«für einen Teilbaum beim Ändern von Realm »%s«»get_updates«-Fehler vom Master ungültiges »get_updates«-Ergebnis vom Master »get_updates«-Master ausgelastet; hält sich zurück Zugriff bei »get_updates« verweigert Vom Master-KDC wurde ein »get_updates«-Fehler zurückgegeben.»get_updates«, ungültiger Rückgabewert vom Master-KDC»get_updates«, Zugriff verweigertgetaddrinfo(%s): Die Normalform des Rechnernamens kann nicht bestimmt werden. getaddrinfo: %s beim Holen der KonfigurationsparameterAnfängliche Anmeldedaten werden geholt.Anfängliches Ticket wird geholt.Lokale Adressen werden geholt.Principal wird vom Ccache geholt.Zufallsstartwert wird geholtPrincipal-Name wird im Klartext geholtgss_to_krb5_name: display_name fehlgeschlagen, Status %dName des Home-Verzeichnisses »%s« ist zu lang, Suche nach .k5login nicht möglich Home-Verzeichnispfad für %s zu lang Rechner/Domain-Name nicht gefundenin »krb5_auth_con_setaddrs«Informationwird initialisiertACL-Datei wird initialisiertKerberos-Bibliothek wird initialisiert.Netzwerk wird initialisiertungültiger Verschlüsselungstyp %sungültiger Suchbereich beim Erstellen von Realm »%s«Aufruf von »iprop_full_resync« fehlgeschlagenAufruf von »iprop_get_updates« fehlgeschlagenInitialisierung von Kadm5 fehlgeschlagen! Initialisieren von Kadm5 erfolgreich »kadm5_hook« %s ist beim Nach-Commit %s gescheitert: %sKerberos-Principal ist bereits mit einem LDAP-Objekt verknüpftSchlüsseldatei (%s) ist keine normale Datei: %sSchlüsseltabelle angegeben, -k wird erzwungen Kpropd: erneutes vollständiges Synchronisieren erforderlichksu: Umgebungsvariable %s kann nicht gesetzt werden ksu: Umgebungsvariable HOME kann nicht gesetzt werden ksu: Umgebungsvariable SHELL kann nicht gesetzt werden ksu: Umgebungsvariable USER kann nicht gesetzt werden ksu: »initgroups« fehlgeschlagen ksu: Zugriff verweigert (Shell) ksu: unbekannter Anmeldename %s ksu: Wer sind Sie? LDAP-Objekt ist bereits an Kerberos angepasstVerweisinformation kann nicht eingerichtet/aktualisiert werden, da der Kerberos-Principal zu einem LDAP-Objekt gehört.auf Dateideskriptor %d wird auf eine Verbindung gewartet: RPC %sauf Dateideskriptor %d wird auf eine Verbindung gewartet: TCP %sauf Dateideskriptor %d wird auf eine Verbindung gewartet: UDP %s%sfalsch gebildeter Anmeldedatenzwischenspeichername %s Aktualisierungsprotokoll wird abgebildetAblagedatei des Hauptschlüssels erfordert Aktualisierung, Befehl abgebrochenHauptschlüsselliste ist nicht initialisiertfehlender Principal-Namekeine Socket-Option für IPV6_V6ONLY unterstütztkeine Daten für Rechner/Domain-Namen verfügbarkeine Sockets eingerichtet?Nummer für einmaligen Gebrauch in der FAST-Anwort geändert: KDC-Anwort geändertÜbergangspfad wird nicht geprüftStandard-Ccache wird geöffnet.Die Aktion kann nicht fortfahren, da mehr als ein Principal namens »%s« gefunden wurde.Client-Name wird ausgewertet.Das Modul %s für Passwortqualität hat das Passwort für %s abgelehnt: %sAuszug von %s wird durchgeführtPktinfo sagt, die lokale Adresse sei %sNachschlagen des Erweiterungssymbols »kdb_function_table« fehlgeschlagen: %sErweiterung nicht verfügbar: %sInitialisieren von »preauth« %s fehlgeschlagen: %sEinrichten der Schleife von »preauth« %s fehlgeschlagen: %sPrincipal-Name %s für den internen Pufferbereich zu groß Programmname zu lang – wird beendet, um das Auslösen von Systemprotokollierungsfehlern zu vermeidenRcache gehört nicht %d%d vom Routing-Socket gelesen, Nachrichtenlänge ist jedoch %dAktualisierungsprotokollkopfzeilen werden gelesenbereit Wert des Realm-Objekts: Umbenennen von temporärer Schlüsseldatei (%s) in (%s) fehlgeschlagen: %serneuern bis Anmeldedaten werden erneuert.Ccache %s wird ermitteltStandardschlüsseltabelle des Clients wird ermittelt.Schlüsseltabelle wird ermittelt: %sFehler in einer RoutineDas Routing-Socket hat den Dateideskriptor %d.Dienstname unbekanntDienst nicht verfügbar%d Sockets werden eingerichtet»setpw«-Anfrage von %s durch %.*s%s für %.*s%s: %ssetsockopt(%d,IPV6_V6ONLY,1) fehlgeschlagensetsockopt(%d,IPV6_V6ONLY,1) funktioniertNetzwerk wird eingerichtet …ungenügende Daten (%d/%d) vom Routing-Socket gelesenungenügende Ausgabe der Antwort %d gegenüber %d wird heruntergefahrenÜberwachungsprogramm empfing Signal %dsignalisiert vom Serversignalisiert vom Serverwird übersprungen: %s Daemon-Prozess wird erzeugtangegeben für Suchbereich, während die Information für Realm »%s« geändert wirdStandardeingabestartetWert des Teilbaums: erfolgreichzusätzlicher InformationscodeTerminal-Name %s ist zu lang. ein Hauptschlüssel muss derzeit aktiv seinWert des Ticket-Richtlinienobjekts: Ticket-Richtlinienobjekt: zu viele Verbindungenes wird versucht, die Principal-Datenbank zu verarbeiten»ulog_replay« fehlgeschlagen (%s), Aktualisierungen nicht registriert »ulog_replay« fehlgeschlagen (%s), Aktualisierungen nicht registriertDie gespeicherten Schlüsseldaten des Principals (%s) konnten nicht dekodiert werden.Erweiterung [%s] konnte nicht gefunden werden: %sDLL [%s] konnte nicht geladen werdenErweiterung [%s] konnte nicht geladen werden: %sunerwarteter Fehler bei der Prüfung des Übergangs von »%s« zu »%s« über »%.*s%s«: %snicht behandelter Routing-Meldungstyp %d, es wird es nur zum Spaß neu konfiguriertunbekannter »addrtype« %dunbekannter Code 0x%xunbekannter Fehlschlagunbekannter Getaddrinfo-Fehlschlagunbekannte Option »%s«unbekannte Option: %sunbekannter Datensatztyp »%s« nicht druckbare Adresse (Typ %d Fehler %d %s)wird aktualisiert: %s Aufruf: %s (-key | -password) -p Principal -k KVNO -e Verschlüsselungstyp Aufruf: %s [-C] [-u] [-c Ccache] [-e Etype] Aufruf: %s [-x Datenbankargumente]* [-d Datenbankpfadname] [-r Datenbank-Realm-Name] [-m] [-k Hauptverschlüsselungstyp] [-M Hauptschlüsselname] [-p Port] [-P PID-Datei] [-n] [-w Arbeitsprozessanzahl] [/] dabei sind [-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer Argumente. Welche Argumente unterstützt werden, finden Sie in der Dokumentation der jeweiligen Datenbank. Aufruf: %s [Principal] Aufruf: add_principal [Optionen] Principal Aufruf: change_password [-randkey] [-keepold] [-e Schlüssel-Salt-Liste] [-pw Passwort] Principal Aufruf: del_string Principal Schlüssel Aufruf: delete_policy [-force] Richtlinie Aufruf: delete_principal [-force] Principal Aufruf: get_policies [Ausdruck] Aufruf: get_policy [-terse] Richtlinie Aufruf: get_principal [-terse] Principal Aufruf: get_principals [Ausdruck] Aufruf: get_privs Aufruf: get_strings Principal Aufruf: modify_principal [Optionen] Principal Aufruf: purgekeys [-all|-keepkvno älteste_KVNO_die_behalten_wird] Principal Aufruf: rename_principal [-force] alter_Principal neuer_Principal Aufruf: set_string Principal Schlüssel Wert Aufruf: %s [Optionen] Richtlinie Anmeldedaten werden geprüft.Variable fehlt }warten auf Kprop-Verbindung waitpid() schlug beim Warten auf doit() fehl (%d %s) wenn der Standard-Principal-Name des Servers erstellt wirdbeim Zusammenstellen der Parameterbeim Initialisieren des Zwischenspeichers %swenn der Name %s ausgewertet wirdbeim Rückgängigmachen der Auswertung des Namensbei %sbeim Akzeptieren der Verbindungbeim Hinzufügen von Einträgen zur Datenbankbeim Hinzufügen von Einträgen in die Datenbankbeim Hinzufügen des Schlüssels zur Schlüsseltabellebeim Hinzufügen des Hauptschlüsseleintrags zur Datenbankbeim Hinzufügen eines neuen Eintragsbeim Hinzufügen eines neuen Hauptschlüsselsbeim Hinzufügen der Option »preauth«beim Reservieren von »args.kvnos«beim Reservieren des »dump_ok«-Dateinamensbeim Reservieren des Dateinamens für die temporäre Dateibeim Reservieren des Dateinamens für »update_last_prop_file«beim Reservieren von »i_vector«beim Reservieren von »key_data«bei Reservieren von Speicherbeim Reservieren von Speicher für den Ziel-Ccache-Namenbeim Reservieren des temporären Dateinamenspeicherauszugsbeim Anhängen des Realms an den Principalbeim Versuch, »setsockopt« auszuführen (SO_KEEPALIVE)beim Versuch, eine Verbindung zum Master-KDC aufzubauen … wird erneut versuchtbeim Versuch, den Standard-Realm abzufragenbeim Authentifizieren am Serverbeim Anbinden an das auf Verbindung wartende Socketbeim Bilden des TGS-Namens für Realm %sbeim Erstellen des Principalsbeim Berechnen des Hauptschlüssel-Saltsbeim Berechnen des Hauptschlüssel-Saltsbeim Aufruf von »cc_filter«beim Aufruf von »waitpid«während der neue Principal in die normale Form gebracht wirdwährend der alte Principal in die normale Form gebracht wirdwährend der Principal in die normale Form gebracht wirdwährend der Principal-Name in die normale Form gebracht wirdbeim Ändern des Schlüssels von %sbeim Ändern des Passworts von »%s«.beim Ändern der Ziel-UID für das Zerstören von Ccachebeim Prüfen der Autorisierungbeim Prüfen, ob die Standardeingabe ein Socket istbeim Löschen von DISALLOW_ALL_TIX für »%s«.beim Leeren des Werts von %sbeim Schließen des Ccachesbeim Schließen von Ccache %sbeim Schließen der Datenbankbeim Schließen der Schlüsseltabellebeim Schließen der vorherigen Datenbankbeim Verbinden mit dem Serverbeim Erstellen meines Dienst-Realmsbeim Umwandeln von %s in den neuen Hauptschlüsselbei der Etype-Umwandlungbeim Umwandeln der lokalen Socket-Adressebeim Umwandeln der Server-Adressebeim Kopieren des Zwischenspeichers %s nach %sbeim Kopieren des Client-Principalsbeim Erstellen der Datei »last_prop«, »%s«beim Erstellen der Datei »ok«, »%s«beim Erstellen der PID-Dateibeim Erstellen der Datenbankbeim Erstellen der Datenbank »%s«beim Erstellen des Schlüsseltabellennamensbeim Erzeugen der Hauptschleifebeim Erstellen des neuen Hauptschlüsselsbei Erstellen von neuem Ziel-Ccachebeim Erstellen der Richtliniebeim Erstellen der Richtlinie »%s«beim Erstellen des Richtlinienobjektsbeim Erstellen des Principals %sbeim Erstellen von Realm »%s«beim Erstellen eines Socketsbeim Erstellen von Unterbefehlsargumentenbei Erstellen des temporären Zwischenspeichersbeim Erstellen des TGTs für lokalen Realmbeim Erstellen des Aktualisierungsprotokollsbeim Dekodieren der Datenbankgröße vom Clientbeim Dekodieren des Fehlerpakets vom Clientbeim Aufschlüsseln der Fehlerantwort vom Serverbeim Dekodieren des Tickets für %sbeim Entschlüsseln des Tickets für %sbeim Löschen eines Attributs von Principal »%s«beim Löschen der falschen Datenbank %sbeim Löschen von Eintrag %dbeim Löschen eines Eintrags aus der Schlüsseltabellebei Löschen der Richtlinie »%s«beim Löschen von Principal »%s«beim Zerstören des Zwischenspeichersbeim Zerstören des Zwischenspeichers %sbeim Zerstören des Richtlinienobjektsbeim Lösen vom Terminalbeim Bestimmen des lokalen Dienst-Principal-Namensbeim Bestimmen des Ziel-Ccache-Namensbeim Versenden (TCP)beim Versenden (UDP)beim Downgrade der Sperre auf »%s«beim Aufbereiten der Datenbankgrößebeim Beenden des Schlüsseltabellen-Scansbei Löschen des Zielzwischenspeichersbeim Expandieren des Ausdrucks »%s«.beim Abholen des Hauptschlüssels %s für Realm %sbeim Abholen der Hauptschlüsselliste für Realm %sbeim Abrufen von Principal %sbei der Suche nach den gerade verwendeten Hauptschlüsselnbeim Suchen nach Mkeywährend das Abfragem der Tickets endetbeim Erzeugen eines Kindprozessesbeim Formatieren des Haupt-Principal-Namensbeim Formatieren des ausgewerteten Principal-Namens für »%s«beim Freigeben von »ktlist«beim Freigeben des Principal-Eintragsbeim Erstellen von neuem Ccachebeim Erzeugen eines Teils des Ziel-Ccache-Namensbeim Holen von »%s«.beim Holen von Attributen für Principal »%s«beim Holen des Client-Principal-Namensbeim Holen des Kontextes für Realm %sbeim Holen der Anmeldedaten für %sbeim Holen der aktuellen Zeitbeim Holen des Standard-Ccachesbeim Holen der Standardschlüsseltabelle des Clientsbeim Holen der Standardschlüsseltabellebeim Holen des Standard-Realmsbeim Holen des Verschlüsselungsbeschreibungbeim Holen der Anfangsanmeldedatenbeim Holen der Anfangsanmeldedaten beim Holen des Schlüsseltabellennamensbeim Holen der lokalen Socket-Adressebeim Holen der Hauptschlüssellistebeim Holen des Hauptschlüssels von Principal %sbeim Holen des Ziel-Ccache-Namensbeim Holen der Richtlinieninformation.beim Holen der Principal-Information.beim Holen des Quellenzwischenspeichersbeim Holen der Zeitbeim Holen der Tageszeitbei der Initialisierungbeim Initialisieren der Schnittstelle %sbeim Initialisieren der Schnittstelle %s, wird erneut versuchtbeim Initialisieren der Kerberos-5-Bibliothekbeim Initialisieren von Kerberos-Codebeim Initialisieren des SAMsbeim Initialisieren der Datenbankbeim Initialisieren der Datenbank für Realm %sbeim Initialisieren der Fehlerbehandlungbeim Initialisieren von »i_vector«beim Initialisieren von Krb5beim Initialisieren der Krb5-Bibliothekbeim Initialisieren von »krb5_context«beim Initialisieren des LDAP-Identifikatorsbeim Initialisieren des Lookaside-Zwischenspeichersbeim Initialisieren des Netzwerksbeim Initialisieren des Zufallsschlüsselgeneratorsbeim Initialisieren des Routing-Socketsbeim Initialisieren der Serverlistebeim Initialisieren des Signalbehandlungsprogrammsbeim Initialisieren des Zielzwischenspeichersbeim Initialisieren der Kerberos-Administrationsoberflächebeim Initialisieren des Aktualisierungsprotokollsbeim Aufführen der Ccache-Sammlungbeim Auflisten der Anmeldedatenzwischenspeicherbeim Auflisten der Richtlinienobjektebeim Auflisten der Realmsbeim Laden des/der Auditerweiterungsmoduls/Auditerweiterungsmodulebeim Sperren der Datei »ok«, »%s«beim Suchen nach dem Anmeldedatenzwischenspeicher %sbeim Nachschlagen der Liste aktiver KVNOsbeim Nachschlagen des aktiven Hauptschlüsselsbeim Nachschlagen der aktiven Version des Hauptschlüsselsbeim Nachschlagen der Mkey-Aux-Datenlistebeim Nachschlagen der Kerberos-Konfigurationbeim Aktivieren der neu geladenen Datenbankbeim Abbilden des Aktualisierungsprotokollsbeim Ändern von »%s«.beim Ändern der Information von Realm »%s«beim Ändern der Richtlinie »%s«beim Ändern des Richtlinienobjektsbeim Erlangen des Socketsbeim Öffnen von %sbeim Öffnen von %s zum Schreibenbeim Öffnen des Ccachesbeim Öffnen des Anmeldedatenzwischenspeichers %sbeim Öffnen des Anmeldedatenzwischenspeichers %sbeim Öffnen der Datenbankbeim Öffnen der Datenbankdatei, »%s«beim Öffnen des Standardanmeldedatenzwischenspeichersbeim Öffnen der Standardschlüsseltabellebeim Auswerten von »-add Principal-Name %s«beim Auswerten des Principal-Namens des Administratorsbeim Auswerten von Befehlsargumentenbeim Auswerten der Befehlsargumente beim Auswerten der Schlüssel-Salts %sbeim Auswerten des Namens %sbeim Auswerten des neuen Principal-Namensbeim Auswerten des alten Principal-Namensbeim Auswerten der Optionenbeim Auswerten des Principalsbeim Auswerten des Principal-Namensbeim Auswerten des Principal-Namens %sbeim Auswertens des temporären Namensbeim dauerhaften Sperren der Datenbankbeim Bereitstellen der Zeitspezifikationbeim vollständigen Löschen der Schlüssel für Principal »%s«beim Erzeugen eines zufälligen Schlüssels für »%s«.beim Lesen der Kerberos-Container-Informationbeim Lesen des Zwischenspeichernamens aus dem Ccachebeim Lesen der Information der Richtlinie »%s«beim Lesen der Information von Realm »%s«beim Lesen der Kerberos-Container-Informationbeim Lesen der Schlüsseltabelle »%s«beim Lesen der LDAP-Konfigurationbeim Lesen der LDAP-Parameterbeim Lesen des Hauptschlüsselsbeim Lesen des Hauptschlüssels von der Tastaturbeim Lesen des neuen Hauptschlüsselsbeim Lesen des neuen Hauptschlüssels von der Tastaturbeim Lesen des neuen Passworts.beim Lesen des Passwortsbeim Lesen des Passworts von »%s«.beim Lesen des Passworts für »%s« beim Lesen der Realm-Informationbeim Lesen der Antwort vom Serversbeim Lesen der Datenbankgröße vom Clientbeim Lesen der Dienstschlüsseltabelle »%s«beim Lesen der Aktualisierungsprotokollkopfzeilenbeim Empfangen vom Netzwerkbeim erneuten Beanspruchen der Root-UIDbeim erneuten Initialisieren des Aktualisierungsprotokollsbeim Umbenennen von %s in %swährend das Umbenennen der Auszugsdateien Gestalt annimmtbeim Umbenennen von Principal »%s« in »%s«beim Zurücksetzen des Ziel-Ccache-Namensbeim Auflösen von %sbeim Ermitteln des Ccaches %sbeim Ermitteln der KDB-Schlüsseltabelle für Realm %sbeim Ermitteln der Schlüsseltabellebeim Ermitteln der Schlüsseltabelle %sbei der Wiederaufnahme des Schlüsseltabellen-Scansbeim Abfragen der Konfigurationsparameterbeim Abfragen von »%s«.beim Abfragen eines Ticketsbeim Abfragen der Anmeldedaten aus dem Zwischenspeicherbeim Abfragen der höchsten KVNO der Schlüsseltabellebeim Abfragen der LDAP-Konfigurationbeim Abfragen der Liste.beim Abfragen des Haupteintragsbeim Abfragen der Richtlinie »%s«.beim Abfragen des Principalsbeim Abfragen des Principal-Namensbeim Abfragen von Rechtenbei der Rückkehr zur Quell-UID, nachdem der beste Principal gefunden wurdebeim Speichern von Principal %sbeim Scannen der Schlüsseltabellebeim Suchen nach Ccache für %sbeim Erzeugen des Startwerts des Zufallszahlengeneratorsbeim Auswählen des besten Principalsbeim Senden n empfangener Bytebeim Senden des Datenbankblocks, der bei %d beginntbeim Senden der Datenbankgrößebeim Senden der Antwort zu %s/%s von %sbeim Setzen von »%s«=»%s«beim Setzen des FAST-Ccachesbeim Setzen der Option SO_REUSEADDRbeim Setzen eines Attributes für Principal »%s«beim Setzen der Änderungszeit der Dateibeim Setzen des Client-Principal-Namensbeim Setzen des Client-Principal-Realmsbeim Einstellen des Standard-Realm-Namensbeim Setzen des Standard-Realms auf %sbeim Setzen der EUID auf dem Quellbenutzerbeim Setzen des Server-Principal-Namensbeim Setzen des Passworts für das Dienstobjektbeim Einrichten der KDB-Schlüsseltabelle für Realm %sbeim Einrichten des Verschlüsselungstyps %dein Einrichten der BibliotheksIdentifikatorsbeim Einrichten der Protokollierungbeim Einrichten des Hauptschlüsselnamensbeim Einrichten des Hauptschlüsselnamens %s für Realm %sbeim Start des Schlüsseltabellen-Scanswährend das Abfragen der Tickets beginntbeim Speichern von %sbeim Speichern der Anmeldedatenbeim Speichern des Schlüsselsbeim Zurückwechsel vom Ziel nach der Autorisierungsprüfungbeim Wechsel auf den Anmeldedatenzwischenspeicherbeim Wechsel zum neuen Ccachebeim Wechsel des Ziels der Autorisierungsprüfungbeim Umschalten auf die Ziel-UIDbeim Unterbrechen des Schlüsseltabellen-Scansbeim Umwandeln des Hauptschlüssels vom Passwortbeim Versuch, das Passwort zu ändern.beim Versuch, die Datenbankdatei zu schließenbeim Versuch, den Rechnerdienst-Principal zu erstellenbeim Versuch, meinen Dienstnamen zu erstellenbeim Versuch, %s auszuführenbeim Versuch von »execv %s«beim Versuch, einen Kindprozess von %s zu erzeugenbeim Versuch zu verzweigen.beim Versuch, »%s« zu sperrenbeim Versuch, Speicher für »data_ok_fn« zu reservierenbeim Versuch, %s zu öffnenbeim Versuch, »stat« für %s auszuführenbeim Aufheben der Sperre »%s«beim Aufheben der Datenbanksperrebeim Entsperren von Datenbank »%s«beim Entsperren der Datenbankbeim Rückgängigmachen des Auswertens des Client-Namensbeim Rückgängigmachen der Auswertung des Principalsbeim Rückgängigmachen des Auswertens des Principal-Namensbeim Rückgängigmachen des Auswertens des Server-Namensbeim Rückgängigmachen der Auswertung des »etype«s des Ticketsbeim Entfernen der Option IPV6_V6ONLYbeim Aktualisieren der Actkvno-Daten für den Haupt-Principal-Eintragbeim Aktualisieren der Mkey-Aux-Daten für den Haupt-Principal-Eintragbeim Aktualisieren der Schlüsseldaten von Principal »%s« in der Datenbankbeim Aktualisieren der Änderungszeit von Principal »%s«beim Aktulisieren der Änderungszeit des Hauptschlüssel-Principalsbeim Prüfen des Hauptschlüsselsbeim Prüfen des Tickets für Serverbeim Betrachten der Richtliniebeim Betrachten der Richtlinie »%s«beim Warten auf %sbeim Warten auf den Erhalt der Datenbankbeim Schreiben der Schlüsseltabelle »%s«beim Schreiben der AktualisierungsprotokollkopfzeilenArbeitsprozess %ld endete mit Status %dwürde übersprungen: %s würde aktualisiert: %s falsche OID noch keine Richtlinie gesetzt! Kontaktieren Sie Ihren Systemsicherheitsadministratorlicenses/alt-krb5-libs/LICENSE000064400000172611152526542560011752 0ustar00Copyright (C) 1985-2019 by the Massachusetts Institute of Technology. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. Downloading of this software may constitute an export of cryptographic software from the United States of America that is subject to the United States Export Administration Regulations (EAR), 15 CFR 730-774. Additional laws or regulations may apply. It is the responsibility of the person or entity contemplating export to comply with all applicable export laws and regulations, including obtaining any required license from the U.S. government. The U.S. government prohibits export of encryption source code to certain countries and individuals, including, but not limited to, the countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and nationals of those countries. Documentation components of this software distribution are licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. (https://creativecommons.org/licenses/by-sa/3.0/) Individual source code files are copyright MIT, Cygnus Support, Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, FundsXpress, and others. Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, and Zephyr are trademarks of the Massachusetts Institute of Technology (MIT). No commercial use of these trademarks may be made without prior written permission of MIT. "Commercial use" means use of a name in a product or other for-profit manner. It does NOT prevent a commercial firm from referring to the MIT trademarks in order to convey information (although in doing so, recognition of their trademark status should be given). ====================================================================== The following copyright and permission notice applies to the OpenVision Kerberos Administration system located in "kadmin/create", "kadmin/dbutil", "kadmin/passwd", "kadmin/server", "lib/kadm5", and portions of "lib/rpc": Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights Reserved WARNING: Retrieving the OpenVision Kerberos Administration system source code, as described below, indicates your acceptance of the following terms. If you do not agree to the following terms, do not retrieve the OpenVision Kerberos administration system. You may freely use and distribute the Source Code and Object Code compiled from it, with or without modification, but this Source Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY OTHER REASON. OpenVision retains all copyrights in the donated Source Code. OpenVision also retains copyright to derivative works of the Source Code, whether created by OpenVision or by a third party. The OpenVision copyright notice must be preserved if derivative works are made based on the donated Source Code. OpenVision Technologies, Inc. has donated this Kerberos Administration system to MIT for inclusion in the standard Kerberos 5 distribution. This donation underscores our commitment to continuing Kerberos technology development and our gratitude for the valuable work which has been performed by MIT and the Kerberos community. ====================================================================== Portions contributed by Matt Crawford "crawdad@fnal.gov" were work performed at Fermi National Accelerator Laboratory, which is operated by Universities Research Association, Inc., under contract DE-AC02-76CHO3000 with the U.S. Department of Energy. ====================================================================== Portions of "src/lib/crypto" have the following copyright: Copyright (C) 1998 by the FundsXpress, INC. All rights reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of FundsXpress. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. FundsXpress makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ====================================================================== The implementation of the AES encryption algorithm in "src/lib/crypto/builtin/aes" has the following copyright: Copyright (C) 2001, Dr Brian Gladman "brg@gladman.uk.net", Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. DISCLAIMER This software is provided 'as is' with no explcit or implied warranties in respect of any properties, including, but not limited to, correctness and fitness for purpose. ====================================================================== Portions contributed by Red Hat, including the pre-authentication plug-in framework and the NSS crypto implementation, contain the following copyright: Copyright (C) 2006 Red Hat, Inc. Portions copyright (C) 2006 Massachusetts Institute of Technology All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of Red Hat, Inc., nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== The bundled verto source code is subject to the following license: Copyright 2011 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== The MS-KKDCP client implementation has the following copyright: Copyright 2013,2014 Red Hat, Inc. 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in "src/lib/gssapi", including the following files: lib/gssapi/generic/gssapi_err_generic.et lib/gssapi/mechglue/g_accept_sec_context.c lib/gssapi/mechglue/g_acquire_cred.c lib/gssapi/mechglue/g_canon_name.c lib/gssapi/mechglue/g_compare_name.c lib/gssapi/mechglue/g_context_time.c lib/gssapi/mechglue/g_delete_sec_context.c lib/gssapi/mechglue/g_dsp_name.c lib/gssapi/mechglue/g_dsp_status.c lib/gssapi/mechglue/g_dup_name.c lib/gssapi/mechglue/g_exp_sec_context.c lib/gssapi/mechglue/g_export_name.c lib/gssapi/mechglue/g_glue.c lib/gssapi/mechglue/g_imp_name.c lib/gssapi/mechglue/g_imp_sec_context.c lib/gssapi/mechglue/g_init_sec_context.c lib/gssapi/mechglue/g_initialize.c lib/gssapi/mechglue/g_inquire_context.c lib/gssapi/mechglue/g_inquire_cred.c lib/gssapi/mechglue/g_inquire_names.c lib/gssapi/mechglue/g_process_context.c lib/gssapi/mechglue/g_rel_buffer.c lib/gssapi/mechglue/g_rel_cred.c lib/gssapi/mechglue/g_rel_name.c lib/gssapi/mechglue/g_rel_oid_set.c lib/gssapi/mechglue/g_seal.c lib/gssapi/mechglue/g_sign.c lib/gssapi/mechglue/g_store_cred.c lib/gssapi/mechglue/g_unseal.c lib/gssapi/mechglue/g_userok.c lib/gssapi/mechglue/g_utils.c lib/gssapi/mechglue/g_verify.c lib/gssapi/mechglue/gssd_pname_to_uid.c lib/gssapi/mechglue/mglueP.h lib/gssapi/mechglue/oid_ops.c lib/gssapi/spnego/gssapiP_spnego.h lib/gssapi/spnego/spnego_mech.c and the initial implementation of incremental propagation, including the following new or changed files: include/iprop_hdr.h kadmin/server/ipropd_svc.c lib/kdb/iprop.x lib/kdb/kdb_convert.c lib/kdb/kdb_log.c lib/kdb/kdb_log.h lib/krb5/error_tables/kdb5_err.et kprop/kpropd_rpc.c kprop/kproplog.c are subject to the following license: Copyright (C) 2004 Sun Microsystems, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== Kerberos V5 includes documentation and software developed at the University of California at Berkeley, which includes this copyright notice: Copyright (C) 1983 Regents of the University of California. 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. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "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 REGENTS OR CONTRIBUTORS 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. ====================================================================== Portions contributed by Novell, Inc., including the LDAP database backend, are subject to the following license: Copyright (C) 2004-2005, Novell, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * The copyright holder's name is not used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== Portions funded by Sandia National Laboratory and developed by the University of Michigan's Center for Information Technology Integration, including the PKINIT implementation, are subject to the following license: COPYRIGHT (C) 2006-2007 THE REGENTS OF THE UNIVERSITY OF MICHIGAN ALL RIGHTS RESERVED Permission is granted to use, copy, create derivative works and redistribute this software and such derivative works for any purpose, so long as the name of The University of Michigan is not used in any advertising or publicity pertaining to the use of distribution of this software without specific, written prior authorization. If the above copyright notice or any other identification of the University of Michigan is included in any copy of any portion of this software, then the disclaimer below must also be included. THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ====================================================================== The pkcs11.h file included in the PKINIT code has the following license: Copyright 2006 g10 Code GmbH Copyright 2006 Andreas Jellinghaus This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without modifications, as long as this notice is preserved. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, to the extent permitted by law; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ====================================================================== Portions contributed by Apple Inc. are subject to the following license: Copyright 2004-2008 Apple Inc. All Rights Reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Apple Inc. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Apple Inc. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ====================================================================== The implementations of UTF-8 string handling in src/util/support and src/lib/krb5/unicode are subject to the following copyright and permission notice: The OpenLDAP Public License Version 2.8, 17 August 2003 Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source form must retain copyright statements and notices, 2. Redistributions in binary form must reproduce applicable copyright statements and notices, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution, and 3. Redistributions must contain a verbatim copy of this document. The OpenLDAP Foundation may revise this license from time to time. Each revision is distinguished by a version number. You may use this Software under terms of this license revision or under the terms of any subsequent revision of the license. THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE 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. The names of the authors and copyright holders must not be used in advertising or otherwise to promote the sale, use or other dealing in this Software without specific, written prior permission. Title to copyright in this Software shall at all times remain with copyright holders. OpenLDAP is a registered trademark of the OpenLDAP Foundation. Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, California, USA. All Rights Reserved. Permission to copy and distribute verbatim copies of this document is granted. ====================================================================== Marked test programs in src/lib/krb5/krb have the following copyright: Copyright (C) 2006 Kungliga Tekniska Högskola (Royal Institute of Technology, Stockholm, Sweden). 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. Neither the name of KTH nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS "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 KTH OR ITS CONTRIBUTORS 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. ====================================================================== The KCM Mach RPC definition file used on macOS has the following copyright: Copyright (C) 2009 Kungliga Tekniska Högskola (Royal Institute of Technology, Stockholm, Sweden). All rights reserved. Portions Copyright (C) 2009 Apple Inc. 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. Neither the name of the Institute nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "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 INSTITUTE OR CONTRIBUTORS 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. ====================================================================== Portions of the RPC implementation in src/lib/rpc and src/include/gssrpc have the following copyright and permission notice: Copyright (C) 2010, Oracle America, Inc. 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. Neither the name of the "Oracle America, Inc." nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. ====================================================================== Copyright (C) 2006,2007,2009 NTT (Nippon Telegraph and Telephone Corporation). 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 as the first lines of this file unmodified. 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. THIS SOFTWARE IS PROVIDED BY NTT "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 NTT 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. ====================================================================== Copyright 2000 by Carnegie Mellon University All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Carnegie Mellon University not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. 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. ====================================================================== Copyright (C) 2002 Naval Research Laboratory (NRL/CCS) Permission to use, copy, modify and distribute this software and its documentation is hereby granted, provided that both the copyright notice and this permission notice appear in all copies of the software, derivative works or modified versions, and any portions thereof. NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ====================================================================== Copyright (C) 1991, 1992, 1994 by Cygnus Support. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Cygnus Support makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ====================================================================== Copyright (C) 2006 Secure Endpoints Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== Portions of the implementation of the Fortuna-like PRNG are subject to the following notice: Copyright (C) 2005 Marko Kreen 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. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "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 AUTHOR OR CONTRIBUTORS 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. Copyright (C) 1994 by the University of Southern California EXPORT OF THIS SOFTWARE from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute this software and its documentation in source and binary forms is hereby granted, provided that any documentation or other materials related to such distribution or use acknowledge that the software was developed by the University of Southern California. DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The University of Southern California MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not limitation, the University of Southern California MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. The University of Southern California shall not be held liable for any liability nor for any direct, indirect, or consequential damages with respect to any claim by the user or distributor of the ksu software. ====================================================================== Copyright (C) 1995 The President and Fellows of Harvard University This code is derived from software contributed to Harvard by Jeremy Rassen. 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and its contributors. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "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 REGENTS OR CONTRIBUTORS 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. ====================================================================== Copyright (C) 2008 by the Massachusetts Institute of Technology. Copyright 1995 by Richard P. Basch. All Rights Reserved. Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Richard P. Basch, Lehman Brothers and M.I.T. make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ====================================================================== The following notice applies to "src/lib/krb5/krb/strptime.c" and "src/include/k5-queue.h". Copyright (C) 1997, 1998 The NetBSD Foundation, Inc. All rights reserved. This code was contributed to The NetBSD Foundation by Klaus Klein. 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the NetBSD Foundation, Inc. and its contributors. 4. Neither the name of The NetBSD Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS "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 FOUNDATION OR CONTRIBUTORS 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. ====================================================================== The following notice applies to Unicode library files in "src/lib/krb5/unicode": Copyright 1997, 1998, 1999 Computing Research Labs, New Mexico State University Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. ====================================================================== The following notice applies to "src/util/support/strlcpy.c": Copyright (C) 1998 Todd C. Miller "Todd.Miller@courtesan.com" Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 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. ====================================================================== The following notice applies to "src/util/profile/argv_parse.c" and "src/util/profile/argv_parse.h": Copyright 1999 by Theodore Ts'o. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 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. (Isn't it sick that the U.S. culture of lawsuit-happy lawyers requires this kind of disclaimer?) ====================================================================== The following notice applies to SWIG-generated code in "src/util/profile/profile_tcl.c": Copyright (C) 1999-2000, The University of Chicago This file may be freely redistributed without license or fee provided this copyright message remains intact. ====================================================================== The following notice applies to portiions of "src/lib/rpc" and "src/include/gssrpc": Copyright (C) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (C) 2000 Dug Song "dugsong@UMICH.EDU". All rights reserved, all wrongs reversed. 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. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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 REGENTS OR CONTRIBUTORS 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. ====================================================================== Implementations of the MD4 algorithm are subject to the following notice: Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD4 Message Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD4 Message Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. ====================================================================== Implementations of the MD5 algorithm are subject to the following notice: Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message- Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. ====================================================================== The following notice applies to "src/lib/crypto/crypto_tests/t_mddriver.c": Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. ====================================================================== Portions of "src/lib/krb5" are subject to the following notice: Copyright (C) 1994 CyberSAFE Corporation. Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. All Rights Reserved. Export of this software from the United States of America may require a specific license from the United States Government. It is the responsibility of any person or organization contemplating export to obtain such a license before exporting. WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Furthermore if you modify this software you must label your software as modified software and not distribute it in such a fashion that it might be confused with the original M.I.T. software. Neither M.I.T., the Open Computing Security Group, nor CyberSAFE Corporation make any representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ====================================================================== Portions contributed by PADL Software are subject to the following license: Copyright (c) 2011, PADL Software Pty Ltd. 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. Neither the name of PADL Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS "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 PADL SOFTWARE OR CONTRIBUTORS 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. ====================================================================== The bundled libev source code is subject to the following license: All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. Alternatively, the contents of this package may be used under the terms of the GNU General Public License ("GPL") version 2 or any later version, in which case the provisions of the GPL are applicable instead of the above. If you wish to allow the use of your version of this package only under the terms of the GPL and not to allow others to use your version of this file under the BSD license, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL in this and the other files of this package. If you do not delete the provisions above, a recipient may use your version of this file under either the BSD or the GPL. ====================================================================== Files copied from the Intel AESNI Sample Library are subject to the following license: Copyright (C) 2010, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. ====================================================================== The following notice applies to "src/ccapi/common/win/OldCC/autolock.hxx": Copyright (C) 1998 by Danilo Almeida. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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. ====================================================================== The following notice applies to portions of "src/plugins/preauth/spake/edwards25519.c" and "src/plugins/preauth/spake/edwards25519_tables.h": The MIT License (MIT) Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ====================================================================== The following notice applies to portions of "src/plugins/preauth/spake/edwards25519.c": Copyright (c) 2015-2016, Google Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 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. man/man5/krb5.conf.5000064400000141615152526542560010060 0ustar00.\" Man page generated from reStructuredText. . .TH "KRB5.CONF" "5" " " "1.17" "MIT Kerberos" .SH NAME krb5.conf \- Kerberos configuration file . .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 .. .sp The krb5.conf file contains Kerberos configuration information, including the locations of KDCs and admin servers for the Kerberos realms of interest, defaults for the current realm and for Kerberos applications, and mappings of hostnames onto Kerberos realms. Normally, you should install your krb5.conf file in the directory \fB/etc\fP\&. You can override the default location by setting the environment variable \fBKRB5_CONFIG\fP\&. Multiple colon\-separated filenames may be specified in \fBKRB5_CONFIG\fP; all files which are present will be read. Starting in release 1.14, directory names can also be specified in \fBKRB5_CONFIG\fP; all files within the directory whose names consist solely of alphanumeric characters, dashes, or underscores will be read. .SH STRUCTURE .sp The krb5.conf file is set up in the style of a Windows INI file. Lines beginning with \(aq#\(aq or \(aq;\(aq (possibly after initial whitespace) are ignored as comments. Sections are headed by the section name, in square brackets. Each section may contain zero or more relations, of the form: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C foo = bar .ft P .fi .UNINDENT .UNINDENT .sp or: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C fubar = { foo = bar baz = quux } .ft P .fi .UNINDENT .UNINDENT .sp Placing a \(aq*\(aq at the end of a line indicates that this is the \fIfinal\fP value for the tag. This means that neither the remainder of this configuration file nor any other configuration file will be checked for any other values for this tag. .sp For example, if you have the following lines: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C foo = bar* foo = baz .ft P .fi .UNINDENT .UNINDENT .sp then the second value of \fBfoo\fP (\fBbaz\fP) would never be read. .sp The krb5.conf file can include other files using either of the following directives at the beginning of a line: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C include FILENAME includedir DIRNAME .ft P .fi .UNINDENT .UNINDENT .sp \fIFILENAME\fP or \fIDIRNAME\fP should be an absolute path. The named file or directory must exist and be readable. Including a directory includes all files within the directory whose names consist solely of alphanumeric characters, dashes, or underscores. Starting in release 1.15, files with names ending in ".conf" are also included, unless the name begins with ".". Included profile files are syntactically independent of their parents, so each included file must begin with a section header. Starting in release 1.17, files are read in alphanumeric order; in previous releases, they may be read in any order. .sp The krb5.conf file can specify that configuration should be obtained from a loadable module, rather than the file itself, using the following directive at the beginning of a line before any section headers: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C module MODULEPATH:RESIDUAL .ft P .fi .UNINDENT .UNINDENT .sp \fIMODULEPATH\fP may be relative to the library path of the krb5 installation, or it may be an absolute path. \fIRESIDUAL\fP is provided to the module at initialization time. If krb5.conf uses a module directive, kdc.conf(5) should also use one if it exists. .SH SECTIONS .sp The krb5.conf file may contain the following sections: .TS center; |l|l|. _ T{ \fI\%[libdefaults]\fP T} T{ Settings used by the Kerberos V5 library T} _ T{ \fI\%[realms]\fP T} T{ Realm\-specific contact information and settings T} _ T{ \fI\%[domain_realm]\fP T} T{ Maps server hostnames to Kerberos realms T} _ T{ \fI\%[capaths]\fP T} T{ Authentication paths for non\-hierarchical cross\-realm T} _ T{ \fI\%[appdefaults]\fP T} T{ Settings used by some Kerberos V5 applications T} _ T{ \fI\%[plugins]\fP T} T{ Controls plugin module registration T} _ .TE .sp Additionally, krb5.conf may include any of the relations described in kdc.conf(5), but it is not a recommended practice. .SS [libdefaults] .sp The libdefaults section may contain any of the following relations: .INDENT 0.0 .TP \fBallow_weak_crypto\fP If this flag is set to false, then weak encryption types (as noted in Encryption_types in kdc.conf(5)) will be filtered out of the lists \fBdefault_tgs_enctypes\fP, \fBdefault_tkt_enctypes\fP, and \fBpermitted_enctypes\fP\&. The default value for this tag is false, which may cause authentication failures in existing Kerberos infrastructures that do not support strong crypto. Users in affected environments should set this tag to true until their infrastructure adopts stronger ciphers. .TP \fBap_req_checksum_type\fP An integer which specifies the type of AP\-REQ checksum to use in authenticators. This variable should be unset so the appropriate checksum for the encryption key in use will be used. This can be set if backward compatibility requires a specific checksum type. See the \fBkdc_req_checksum_type\fP configuration option for the possible values and their meanings. .TP \fBcanonicalize\fP If this flag is set to true, initial ticket requests to the KDC will request canonicalization of the client principal name, and answers with different client principals than the requested principal will be accepted. The default value is false. .TP \fBccache_type\fP This parameter determines the format of credential cache types created by kinit(1) or other programs. The default value is 4, which represents the most current format. Smaller values can be used for compatibility with very old implementations of Kerberos which interact with credential caches on the same host. .TP \fBclockskew\fP Sets the maximum allowable amount of clockskew in seconds that the library will tolerate before assuming that a Kerberos message is invalid. The default value is 300 seconds, or five minutes. .sp The clockskew setting is also used when evaluating ticket start and expiration times. For example, tickets that have reached their expiration time can still be used (and renewed if they are renewable tickets) if they have been expired for a shorter duration than the \fBclockskew\fP setting. .TP \fBdefault_ccache_name\fP This relation specifies the name of the default credential cache. The default is \fBFILE:/tmp/krb5cc_%{uid}\fP\&. This relation is subject to parameter expansion (see below). New in release 1.11. .TP \fBdefault_client_keytab_name\fP This relation specifies the name of the default keytab for obtaining client credentials. The default is \fBFILE:/opt/alt/krb5/usr/var/krb5/user/%{euid}/client.keytab\fP\&. This relation is subject to parameter expansion (see below). New in release 1.11. .TP \fBdefault_keytab_name\fP This relation specifies the default keytab name to be used by application servers such as sshd. The default is \fBFILE:/etc/krb5.keytab\fP\&. This relation is subject to parameter expansion (see below). .TP \fBdefault_realm\fP Identifies the default Kerberos realm for the client. Set its value to your Kerberos realm. If this value is not set, then a realm must be specified with every Kerberos principal when invoking programs such as kinit(1)\&. .TP \fBdefault_tgs_enctypes\fP Identifies the supported list of session key encryption types that the client should request when making a TGS\-REQ, in order of preference from highest to lowest. The list may be delimited with commas or whitespace. See Encryption_types in kdc.conf(5) for a list of the accepted values for this tag. The default value is \fBaes256\-cts\-hmac\-sha1\-96 aes128\-cts\-hmac\-sha1\-96 aes256\-cts\-hmac\-sha384\-192 aes128\-cts\-hmac\-sha256\-128 des3\-cbc\-sha1 arcfour\-hmac\-md5 camellia256\-cts\-cmac camellia128\-cts\-cmac des\-cbc\-crc des\-cbc\-md5 des\-cbc\-md4\fP, but single\-DES encryption types will be implicitly removed from this list if the value of \fBallow_weak_crypto\fP is false. .sp Do not set this unless required for specific backward compatibility purposes; stale values of this setting can prevent clients from taking advantage of new stronger enctypes when the libraries are upgraded. .TP \fBdefault_tkt_enctypes\fP Identifies the supported list of session key encryption types that the client should request when making an AS\-REQ, in order of preference from highest to lowest. The format is the same as for default_tgs_enctypes. The default value for this tag is \fBaes256\-cts\-hmac\-sha1\-96 aes128\-cts\-hmac\-sha1\-96 aes256\-cts\-hmac\-sha384\-192 aes128\-cts\-hmac\-sha256\-128 des3\-cbc\-sha1 arcfour\-hmac\-md5 camellia256\-cts\-cmac camellia128\-cts\-cmac des\-cbc\-crc des\-cbc\-md5 des\-cbc\-md4\fP, but single\-DES encryption types will be implicitly removed from this list if the value of \fBallow_weak_crypto\fP is false. .sp Do not set this unless required for specific backward compatibility purposes; stale values of this setting can prevent clients from taking advantage of new stronger enctypes when the libraries are upgraded. .TP \fBdns_canonicalize_hostname\fP Indicate whether name lookups will be used to canonicalize hostnames for use in service principal names. Setting this flag to false can improve security by reducing reliance on DNS, but means that short hostnames will not be canonicalized to fully\-qualified hostnames. The default value is true. .TP \fBdns_lookup_kdc\fP Indicate whether DNS SRV records should be used to locate the KDCs and other servers for a realm, if they are not listed in the krb5.conf information for the realm. (Note that the admin_server entry must be in the krb5.conf realm information in order to contact kadmind, because the DNS implementation for kadmin is incomplete.) .sp Enabling this option does open up a type of denial\-of\-service attack, if someone spoofs the DNS records and redirects you to another server. However, it\(aqs no worse than a denial of service, because that fake KDC will be unable to decode anything you send it (besides the initial ticket request, which has no encrypted data), and anything the fake KDC sends will not be trusted without verification using some secret that it won\(aqt know. .TP \fBdns_uri_lookup\fP Indicate whether DNS URI records should be used to locate the KDCs and other servers for a realm, if they are not listed in the krb5.conf information for the realm. SRV records are used as a fallback if no URI records were found. The default value is true. New in release 1.15. .TP \fBerr_fmt\fP This relation allows for custom error message formatting. If a value is set, error messages will be formatted by substituting a normal error message for %M and an error code for %C in the value. .TP \fBextra_addresses\fP This allows a computer to use multiple local addresses, in order to allow Kerberos to work in a network that uses NATs while still using address\-restricted tickets. The addresses should be in a comma\-separated list. This option has no effect if \fBnoaddresses\fP is true. .TP \fBforwardable\fP If this flag is true, initial tickets will be forwardable by default, if allowed by the KDC. The default value is false. .TP \fBignore_acceptor_hostname\fP When accepting GSSAPI or krb5 security contexts for host\-based service principals, ignore any hostname passed by the calling application, and allow clients to authenticate to any service principal in the keytab matching the service name and realm name (if given). This option can improve the administrative flexibility of server applications on multihomed hosts, but could compromise the security of virtual hosting environments. The default value is false. New in release 1.10. .TP \fBk5login_authoritative\fP If this flag is true, principals must be listed in a local user\(aqs k5login file to be granted login access, if a \&.k5login(5) file exists. If this flag is false, a principal may still be granted login access through other mechanisms even if a k5login file exists but does not list the principal. The default value is true. .TP \fBk5login_directory\fP If set, the library will look for a local user\(aqs k5login file within the named directory, with a filename corresponding to the local username. If not set, the library will look for k5login files in the user\(aqs home directory, with the filename .k5login. For security reasons, .k5login files must be owned by the local user or by root. .TP \fBkcm_mach_service\fP On macOS only, determines the name of the bootstrap service used to contact the KCM daemon for the KCM credential cache type. If the value is \fB\-\fP, Mach RPC will not be used to contact the KCM daemon. The default value is \fBorg.h5l.kcm\fP\&. .TP \fBkcm_socket\fP Determines the path to the Unix domain socket used to access the KCM daemon for the KCM credential cache type. If the value is \fB\-\fP, Unix domain sockets will not be used to contact the KCM daemon. The default value is \fB/var/run/.heim_org.h5l.kcm\-socket\fP\&. .TP \fBkdc_default_options\fP Default KDC options (Xored for multiple values) when requesting initial tickets. By default it is set to 0x00000010 (KDC_OPT_RENEWABLE_OK). .TP \fBkdc_timesync\fP Accepted values for this relation are 1 or 0. If it is nonzero, client machines will compute the difference between their time and the time returned by the KDC in the timestamps in the tickets and use this value to correct for an inaccurate system clock when requesting service tickets or authenticating to services. This corrective factor is only used by the Kerberos library; it is not used to change the system clock. The default value is 1. .TP \fBkdc_req_checksum_type\fP An integer which specifies the type of checksum to use for the KDC requests, for compatibility with very old KDC implementations. This value is only used for DES keys; other keys use the preferred checksum type for those keys. .sp The possible values and their meanings are as follows. .TS center; |l|l|. _ T{ 1 T} T{ CRC32 T} _ T{ 2 T} T{ RSA MD4 T} _ T{ 3 T} T{ RSA MD4 DES T} _ T{ 4 T} T{ DES CBC T} _ T{ 7 T} T{ RSA MD5 T} _ T{ 8 T} T{ RSA MD5 DES T} _ T{ 9 T} T{ NIST SHA T} _ T{ 12 T} T{ HMAC SHA1 DES3 T} _ T{ \-138 T} T{ Microsoft MD5 HMAC checksum type T} _ .TE .TP \fBnoaddresses\fP If this flag is true, requests for initial tickets will not be made with address restrictions set, allowing the tickets to be used across NATs. The default value is true. .TP \fBpermitted_enctypes\fP Identifies all encryption types that are permitted for use in session key encryption. The default value for this tag is \fBaes256\-cts\-hmac\-sha1\-96 aes128\-cts\-hmac\-sha1\-96 aes256\-cts\-hmac\-sha384\-192 aes128\-cts\-hmac\-sha256\-128 des3\-cbc\-sha1 arcfour\-hmac\-md5 camellia256\-cts\-cmac camellia128\-cts\-cmac des\-cbc\-crc des\-cbc\-md5 des\-cbc\-md4\fP, but single\-DES encryption types will be implicitly removed from this list if the value of \fBallow_weak_crypto\fP is false. .TP \fBplugin_base_dir\fP If set, determines the base directory where krb5 plugins are located. The default value is the \fBkrb5/plugins\fP subdirectory of the krb5 library directory. This relation is subject to parameter expansion (see below) in release 1.17 and later. .TP \fBpreferred_preauth_types\fP This allows you to set the preferred preauthentication types which the client will attempt before others which may be advertised by a KDC. The default value for this setting is "17, 16, 15, 14", which forces libkrb5 to attempt to use PKINIT if it is supported. .TP \fBproxiable\fP If this flag is true, initial tickets will be proxiable by default, if allowed by the KDC. The default value is false. .TP \fBrdns\fP If this flag is true, reverse name lookup will be used in addition to forward name lookup to canonicalizing hostnames for use in service principal names. If \fBdns_canonicalize_hostname\fP is set to false, this flag has no effect. The default value is true. .TP \fBrealm_try_domains\fP Indicate whether a host\(aqs domain components should be used to determine the Kerberos realm of the host. The value of this variable is an integer: \-1 means not to search, 0 means to try the host\(aqs domain itself, 1 means to also try the domain\(aqs immediate parent, and so forth. The library\(aqs usual mechanism for locating Kerberos realms is used to determine whether a domain is a valid realm, which may involve consulting DNS if \fBdns_lookup_kdc\fP is set. The default is not to search domain components. .TP \fBrenew_lifetime\fP (duration string.) Sets the default renewable lifetime for initial ticket requests. The default value is 0. .TP \fBsafe_checksum_type\fP An integer which specifies the type of checksum to use for the KRB\-SAFE requests. By default it is set to 8 (RSA MD5 DES). For compatibility with applications linked against DCE version 1.1 or earlier Kerberos libraries, use a value of 3 to use the RSA MD4 DES instead. This field is ignored when its value is incompatible with the session key type. See the \fBkdc_req_checksum_type\fP configuration option for the possible values and their meanings. .TP \fBspake_preauth_groups\fP A whitespace or comma\-separated list of words which specifies the groups allowed for SPAKE preauthentication. The possible values are: .TS center; |l|l|. _ T{ edwards25519 T} T{ Edwards25519 curve (\fI\%RFC 7748\fP) T} _ T{ P\-256 T} T{ NIST P\-256 curve (\fI\%RFC 5480\fP) T} _ T{ P\-384 T} T{ NIST P\-384 curve (\fI\%RFC 5480\fP) T} _ T{ P\-521 T} T{ NIST P\-521 curve (\fI\%RFC 5480\fP) T} _ .TE .sp The default value for the client is \fBedwards25519\fP\&. The default value for the KDC is empty. New in release 1.17. .TP \fBticket_lifetime\fP (duration string.) Sets the default lifetime for initial ticket requests. The default value is 1 day. .TP \fBudp_preference_limit\fP When sending a message to the KDC, the library will try using TCP before UDP if the size of the message is above \fBudp_preference_limit\fP\&. If the message is smaller than \fBudp_preference_limit\fP, then UDP will be tried before TCP. Regardless of the size, both protocols will be tried if the first attempt fails. .TP \fBverify_ap_req_nofail\fP If this flag is true, then an attempt to verify initial credentials will fail if the client machine does not have a keytab. The default value is false. .UNINDENT .SS [realms] .sp Each tag in the [realms] section of the file is the name of a Kerberos realm. The value of the tag is a subsection with relations that define the properties of that particular realm. For each realm, the following tags may be specified in the realm\(aqs subsection: .INDENT 0.0 .TP \fBadmin_server\fP Identifies the host where the administration server is running. Typically, this is the master Kerberos server. This tag must be given a value in order to communicate with the kadmind(8) server for the realm. .TP \fBauth_to_local\fP This tag allows you to set a general rule for mapping principal names to local user names. It will be used if there is not an explicit mapping for the principal name that is being translated. The possible values are: .INDENT 7.0 .TP \fBRULE:\fP\fIexp\fP The local name will be formulated from \fIexp\fP\&. .sp The format for \fIexp\fP is \fB[\fP\fIn\fP\fB:\fP\fIstring\fP\fB](\fP\fIregexp\fP\fB)s/\fP\fIpattern\fP\fB/\fP\fIreplacement\fP\fB/g\fP\&. The integer \fIn\fP indicates how many components the target principal should have. If this matches, then a string will be formed from \fIstring\fP, substituting the realm of the principal for \fB$0\fP and the \fIn\fP\(aqth component of the principal for \fB$n\fP (e.g., if the principal was \fBjohndoe/admin\fP then \fB[2:$2$1foo]\fP would result in the string \fBadminjohndoefoo\fP). If this string matches \fIregexp\fP, then the \fBs//[g]\fP substitution command will be run over the string. The optional \fBg\fP will cause the substitution to be global over the \fIstring\fP, instead of replacing only the first match in the \fIstring\fP\&. .TP \fBDEFAULT\fP The principal name will be used as the local user name. If the principal has more than one component or is not in the default realm, this rule is not applicable and the conversion will fail. .UNINDENT .sp For example: .INDENT 7.0 .INDENT 3.5 .sp .nf .ft C [realms] ATHENA.MIT.EDU = { auth_to_local = RULE:[2:$1](johndoe)s/^.*$/guest/ auth_to_local = RULE:[2:$1;$2](^.*;admin$)s/;admin$// auth_to_local = RULE:[2:$2](^.*;root)s/^.*$/root/ auth_to_local = DEFAULT } .ft P .fi .UNINDENT .UNINDENT .sp would result in any principal without \fBroot\fP or \fBadmin\fP as the second component to be translated with the default rule. A principal with a second component of \fBadmin\fP will become its first component. \fBroot\fP will be used as the local name for any principal with a second component of \fBroot\fP\&. The exception to these two rules are any principals \fBjohndoe/*\fP, which will always get the local name \fBguest\fP\&. .TP \fBauth_to_local_names\fP This subsection allows you to set explicit mappings from principal names to local user names. The tag is the mapping name, and the value is the corresponding local user name. .TP \fBdefault_domain\fP This tag specifies the domain used to expand hostnames when translating Kerberos 4 service principals to Kerberos 5 principals (for example, when converting \fBrcmd.hostname\fP to \fBhost/hostname.domain\fP). .TP \fBdisable_encrypted_timestamp\fP If this flag is true, the client will not perform encrypted timestamp preauthentication if requested by the KDC. Setting this flag can help to prevent dictionary attacks by active attackers, if the realm\(aqs KDCs support SPAKE preauthentication or if initial authentication always uses another mechanism or always uses FAST. This flag persists across client referrals during initial authentication. This flag does not prevent the KDC from offering encrypted timestamp. New in release 1.17. .TP \fBhttp_anchors\fP When KDCs and kpasswd servers are accessed through HTTPS proxies, this tag can be used to specify the location of the CA certificate which should be trusted to issue the certificate for a proxy server. If left unspecified, the system\-wide default set of CA certificates is used. .sp The syntax for values is similar to that of values for the \fBpkinit_anchors\fP tag: .sp \fBFILE:\fP \fIfilename\fP .sp \fIfilename\fP is assumed to be the name of an OpenSSL\-style ca\-bundle file. .sp \fBDIR:\fP \fIdirname\fP .sp \fIdirname\fP is assumed to be an directory which contains CA certificates. All files in the directory will be examined; if they contain certificates (in PEM format), they will be used. .sp \fBENV:\fP \fIenvvar\fP .sp \fIenvvar\fP specifies the name of an environment variable which has been set to a value conforming to one of the previous values. For example, \fBENV:X509_PROXY_CA\fP, where environment variable \fBX509_PROXY_CA\fP has been set to \fBFILE:/tmp/my_proxy.pem\fP\&. .TP \fBkdc\fP The name or address of a host running a KDC for that realm. An optional port number, separated from the hostname by a colon, may be included. If the name or address contains colons (for example, if it is an IPv6 address), enclose it in square brackets to distinguish the colon from a port separator. For your computer to be able to communicate with the KDC for each realm, this tag must be given a value in each realm subsection in the configuration file, or there must be DNS SRV records specifying the KDCs. .TP \fBkpasswd_server\fP Points to the server where all the password changes are performed. If there is no such entry, DNS will be queried (unless forbidden by \fBdns_lookup_kdc\fP). Finally, port 464 on the \fBadmin_server\fP host will be tried. .TP \fBmaster_kdc\fP Identifies the master KDC(s). Currently, this tag is used in only one case: If an attempt to get credentials fails because of an invalid password, the client software will attempt to contact the master KDC, in case the user\(aqs password has just been changed, and the updated database has not been propagated to the replica servers yet. .TP \fBv4_instance_convert\fP This subsection allows the administrator to configure exceptions to the \fBdefault_domain\fP mapping rule. It contains V4 instances (the tag name) which should be translated to some specific hostname (the tag value) as the second component in a Kerberos V5 principal name. .TP \fBv4_realm\fP This relation is used by the krb524 library routines when converting a V5 principal name to a V4 principal name. It is used when the V4 realm name and the V5 realm name are not the same, but still share the same principal names and passwords. The tag value is the Kerberos V4 realm name. .UNINDENT .SS [domain_realm] .sp The [domain_realm] section provides a translation from a domain name or hostname to a Kerberos realm name. The tag name can be a host name or domain name, where domain names are indicated by a prefix of a period (\fB\&.\fP). The value of the relation is the Kerberos realm name for that particular host or domain. A host name relation implicitly provides the corresponding domain name relation, unless an explicit domain name relation is provided. The Kerberos realm may be identified either in the \fI\%realms\fP section or using DNS SRV records. Host names and domain names should be in lower case. For example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C [domain_realm] crash.mit.edu = TEST.ATHENA.MIT.EDU .dev.mit.edu = TEST.ATHENA.MIT.EDU mit.edu = ATHENA.MIT.EDU .ft P .fi .UNINDENT .UNINDENT .sp maps the host with the name \fBcrash.mit.edu\fP into the \fBTEST.ATHENA.MIT.EDU\fP realm. The second entry maps all hosts under the domain \fBdev.mit.edu\fP into the \fBTEST.ATHENA.MIT.EDU\fP realm, but not the host with the name \fBdev.mit.edu\fP\&. That host is matched by the third entry, which maps the host \fBmit.edu\fP and all hosts under the domain \fBmit.edu\fP that do not match a preceding rule into the realm \fBATHENA.MIT.EDU\fP\&. .sp If no translation entry applies to a hostname used for a service principal for a service ticket request, the library will try to get a referral to the appropriate realm from the client realm\(aqs KDC. If that does not succeed, the host\(aqs realm is considered to be the hostname\(aqs domain portion converted to uppercase, unless the \fBrealm_try_domains\fP setting in [libdefaults] causes a different parent domain to be used. .SS [capaths] .sp In order to perform direct (non\-hierarchical) cross\-realm authentication, configuration is needed to determine the authentication paths between realms. .sp A client will use this section to find the authentication path between its realm and the realm of the server. The server will use this section to verify the authentication path used by the client, by checking the transited field of the received ticket. .sp There is a tag for each participating client realm, and each tag has subtags for each of the server realms. The value of the subtags is an intermediate realm which may participate in the cross\-realm authentication. The subtags may be repeated if there is more then one intermediate realm. A value of "." means that the two realms share keys directly, and no intermediate realms should be allowed to participate. .sp Only those entries which will be needed on the client or the server need to be present. A client needs a tag for its local realm with subtags for all the realms of servers it will need to authenticate to. A server needs a tag for each realm of the clients it will serve, with a subtag of the server realm. .sp For example, \fBANL.GOV\fP, \fBPNL.GOV\fP, and \fBNERSC.GOV\fP all wish to use the \fBES.NET\fP realm as an intermediate realm. ANL has a sub realm of \fBTEST.ANL.GOV\fP which will authenticate with \fBNERSC.GOV\fP but not \fBPNL.GOV\fP\&. The [capaths] section for \fBANL.GOV\fP systems would look like this: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C [capaths] ANL.GOV = { TEST.ANL.GOV = . PNL.GOV = ES.NET NERSC.GOV = ES.NET ES.NET = . } TEST.ANL.GOV = { ANL.GOV = . } PNL.GOV = { ANL.GOV = ES.NET } NERSC.GOV = { ANL.GOV = ES.NET } ES.NET = { ANL.GOV = . } .ft P .fi .UNINDENT .UNINDENT .sp The [capaths] section of the configuration file used on \fBNERSC.GOV\fP systems would look like this: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C [capaths] NERSC.GOV = { ANL.GOV = ES.NET TEST.ANL.GOV = ES.NET TEST.ANL.GOV = ANL.GOV PNL.GOV = ES.NET ES.NET = . } ANL.GOV = { NERSC.GOV = ES.NET } PNL.GOV = { NERSC.GOV = ES.NET } ES.NET = { NERSC.GOV = . } TEST.ANL.GOV = { NERSC.GOV = ANL.GOV NERSC.GOV = ES.NET } .ft P .fi .UNINDENT .UNINDENT .sp When a subtag is used more than once within a tag, clients will use the order of values to determine the path. The order of values is not important to servers. .SS [appdefaults] .sp Each tag in the [appdefaults] section names a Kerberos V5 application or an option that is used by some Kerberos V5 application[s]. The value of the tag defines the default behaviors for that application. .sp For example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C [appdefaults] telnet = { ATHENA.MIT.EDU = { option1 = false } } telnet = { option1 = true option2 = true } ATHENA.MIT.EDU = { option2 = false } option2 = true .ft P .fi .UNINDENT .UNINDENT .sp The above four ways of specifying the value of an option are shown in order of decreasing precedence. In this example, if telnet is running in the realm EXAMPLE.COM, it should, by default, have option1 and option2 set to true. However, a telnet program in the realm \fBATHENA.MIT.EDU\fP should have \fBoption1\fP set to false and \fBoption2\fP set to true. Any other programs in ATHENA.MIT.EDU should have \fBoption2\fP set to false by default. Any programs running in other realms should have \fBoption2\fP set to true. .sp The list of specifiable options for each application may be found in that application\(aqs man pages. The application defaults specified here are overridden by those specified in the \fI\%realms\fP section. .SS [plugins] .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 \fI\%pwqual\fP interface .IP \(bu 2 \fI\%kadm5_hook\fP interface .IP \(bu 2 \fI\%clpreauth\fP and \fI\%kdcpreauth\fP interfaces .UNINDENT .UNINDENT .UNINDENT .sp Tags in the [plugins] section can be used to register dynamic plugin modules and to turn modules on and off. Not every krb5 pluggable interface uses the [plugins] section; the ones that do are documented here. .sp New in release 1.9. .sp Each pluggable interface corresponds to a subsection of [plugins]. All subsections support the same tags: .INDENT 0.0 .TP \fBdisable\fP This tag may have multiple values. If there are values for this tag, then the named modules will be disabled for the pluggable interface. .TP \fBenable_only\fP This tag may have multiple values. If there are values for this tag, then only the named modules will be enabled for the pluggable interface. .TP \fBmodule\fP This tag may have multiple values. Each value is a string of the form \fBmodulename:pathname\fP, which causes the shared object located at \fIpathname\fP to be registered as a dynamic module named \fImodulename\fP for the pluggable interface. If \fIpathname\fP is not an absolute path, it will be treated as relative to the \fBplugin_base_dir\fP value from \fI\%[libdefaults]\fP\&. .UNINDENT .sp For pluggable interfaces where module order matters, modules registered with a \fBmodule\fP tag normally come first, in the order they are registered, followed by built\-in modules in the order they are documented below. If \fBenable_only\fP tags are used, then the order of those tags overrides the normal module order. .sp The following subsections are currently supported within the [plugins] section: .SS ccselect interface .sp The ccselect subsection controls modules for credential cache selection within a cache collection. In addition to any registered dynamic modules, the following built\-in modules exist (and may be disabled with the disable tag): .INDENT 0.0 .TP \fBk5identity\fP Uses a .k5identity file in the user\(aqs home directory to select a client principal .TP \fBrealm\fP Uses the service realm to guess an appropriate cache from the collection .TP \fBhostname\fP If the service principal is host\-based, uses the service hostname to guess an appropriate cache from the collection .UNINDENT .SS pwqual interface .sp The pwqual subsection controls modules for the password quality interface, which is used to reject weak passwords when passwords are changed. The following built\-in modules exist for this interface: .INDENT 0.0 .TP \fBdict\fP Checks against the realm dictionary file .TP \fBempty\fP Rejects empty passwords .TP \fBhesiod\fP Checks against user information stored in Hesiod (only if Kerberos was built with Hesiod support) .TP \fBprinc\fP Checks against components of the principal name .UNINDENT .SS kadm5_hook interface .sp The kadm5_hook interface provides plugins with information on principal creation, modification, password changes and deletion. This interface can be used to write a plugin to synchronize MIT Kerberos with another database such as Active Directory. No plugins are built in for this interface. .SS kadm5_auth interface .sp The kadm5_auth section (introduced in release 1.16) controls modules for the kadmin authorization interface, which determines whether a client principal is allowed to perform a kadmin operation. The following built\-in modules exist for this interface: .INDENT 0.0 .TP \fBacl\fP This module reads the kadm5.acl(5) file, and authorizes operations which are allowed according to the rules in the file. .TP \fBself\fP This module authorizes self\-service operations including password changes, creation of new random keys, fetching the client\(aqs principal record or string attributes, and fetching the policy record associated with the client principal. .UNINDENT .SS clpreauth and kdcpreauth interfaces .sp The clpreauth and kdcpreauth interfaces allow plugin modules to provide client and KDC preauthentication mechanisms. The following built\-in modules exist for these interfaces: .INDENT 0.0 .TP \fBpkinit\fP This module implements the PKINIT preauthentication mechanism. .TP \fBencrypted_challenge\fP This module implements the encrypted challenge FAST factor. .TP \fBencrypted_timestamp\fP This module implements the encrypted timestamp mechanism. .UNINDENT .SS hostrealm interface .sp The hostrealm section (introduced in release 1.12) controls modules for the host\-to\-realm interface, which affects the local mapping of hostnames to realm names and the choice of default realm. The following built\-in modules exist for this interface: .INDENT 0.0 .TP \fBprofile\fP This module consults the [domain_realm] section of the profile for authoritative host\-to\-realm mappings, and the \fBdefault_realm\fP variable for the default realm. .TP \fBdns\fP This module looks for DNS records for fallback host\-to\-realm mappings and the default realm. It only operates if the \fBdns_lookup_realm\fP variable is set to true. .TP \fBdomain\fP This module applies heuristics for fallback host\-to\-realm mappings. It implements the \fBrealm_try_domains\fP variable, and uses the uppercased parent domain of the hostname if that does not produce a result. .UNINDENT .SS localauth interface .sp The localauth section (introduced in release 1.12) controls modules for the local authorization interface, which affects the relationship between Kerberos principals and local system accounts. The following built\-in modules exist for this interface: .INDENT 0.0 .TP \fBdefault\fP This module implements the \fBDEFAULT\fP type for \fBauth_to_local\fP values. .TP \fBrule\fP This module implements the \fBRULE\fP type for \fBauth_to_local\fP values. .TP \fBnames\fP This module looks for an \fBauth_to_local_names\fP mapping for the principal name. .TP \fBauth_to_local\fP This module processes \fBauth_to_local\fP values in the default realm\(aqs section, and applies the default method if no \fBauth_to_local\fP values exist. .TP \fBk5login\fP This module authorizes a principal to a local account according to the account\(aqs \&.k5login(5) file. .TP \fBan2ln\fP This module authorizes a principal to a local account if the principal name maps to the local account name. .UNINDENT .SS certauth interface .sp The certauth section (introduced in release 1.16) controls modules for the certificate authorization interface, which determines whether a certificate is allowed to preauthenticate a user via PKINIT. The following built\-in modules exist for this interface: .INDENT 0.0 .TP \fBpkinit_san\fP This module authorizes the certificate if it contains a PKINIT Subject Alternative Name for the requested client principal, or a Microsoft UPN SAN matching the principal if \fBpkinit_allow_upn\fP is set to true for the realm. .TP \fBpkinit_eku\fP This module rejects the certificate if it does not contain an Extended Key Usage attribute consistent with the \fBpkinit_eku_checking\fP value for the realm. .TP \fBdbmatch\fP This module authorizes or rejects the certificate according to whether it matches the \fBpkinit_cert_match\fP string attribute on the client principal, if that attribute is present. .UNINDENT .SH PKINIT OPTIONS .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 The following are PKINIT\-specific options. These values may be specified in [libdefaults] as global defaults, or within a realm\-specific subsection of [libdefaults], or may be specified as realm\-specific values in the [realms] section. A realm\-specific value overrides, not adds to, a generic [libdefaults] specification. The search order is: .UNINDENT .UNINDENT .INDENT 0.0 .IP 1. 3 realm\-specific subsection of [libdefaults]: .INDENT 3.0 .INDENT 3.5 .sp .nf .ft C [libdefaults] EXAMPLE.COM = { pkinit_anchors = FILE:/usr/local/example.com.crt } .ft P .fi .UNINDENT .UNINDENT .IP 2. 3 realm\-specific value in the [realms] section: .INDENT 3.0 .INDENT 3.5 .sp .nf .ft C [realms] OTHERREALM.ORG = { pkinit_anchors = FILE:/usr/local/otherrealm.org.crt } .ft P .fi .UNINDENT .UNINDENT .IP 3. 3 generic value in the [libdefaults] section: .INDENT 3.0 .INDENT 3.5 .sp .nf .ft C [libdefaults] pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ .ft P .fi .UNINDENT .UNINDENT .UNINDENT .SS Specifying PKINIT identity information .sp The syntax for specifying Public Key identity, trust, and revocation information for PKINIT is as follows: .INDENT 0.0 .TP \fBFILE:\fP\fIfilename\fP[\fB,\fP\fIkeyfilename\fP] This option has context\-specific behavior. .sp In \fBpkinit_identity\fP or \fBpkinit_identities\fP, \fIfilename\fP specifies the name of a PEM\-format file containing the user\(aqs certificate. If \fIkeyfilename\fP is not specified, the user\(aqs private key is expected to be in \fIfilename\fP as well. Otherwise, \fIkeyfilename\fP is the name of the file containing the private key. .sp In \fBpkinit_anchors\fP or \fBpkinit_pool\fP, \fIfilename\fP is assumed to be the name of an OpenSSL\-style ca\-bundle file. .TP \fBDIR:\fP\fIdirname\fP This option has context\-specific behavior. .sp In \fBpkinit_identity\fP or \fBpkinit_identities\fP, \fIdirname\fP specifies a directory with files named \fB*.crt\fP and \fB*.key\fP where the first part of the file name is the same for matching pairs of certificate and private key files. When a file with a name ending with \fB\&.crt\fP is found, a matching file ending with \fB\&.key\fP is assumed to contain the private key. If no such file is found, then the certificate in the \fB\&.crt\fP is not used. .sp In \fBpkinit_anchors\fP or \fBpkinit_pool\fP, \fIdirname\fP is assumed to be an OpenSSL\-style hashed CA directory where each CA cert is stored in a file named \fBhash\-of\-ca\-cert.#\fP\&. This infrastructure is encouraged, but all files in the directory will be examined and if they contain certificates (in PEM format), they will be used. .sp In \fBpkinit_revoke\fP, \fIdirname\fP is assumed to be an OpenSSL\-style hashed CA directory where each revocation list is stored in a file named \fBhash\-of\-ca\-cert.r#\fP\&. This infrastructure is encouraged, but all files in the directory will be examined and if they contain a revocation list (in PEM format), they will be used. .TP \fBPKCS12:\fP\fIfilename\fP \fIfilename\fP is the name of a PKCS #12 format file, containing the user\(aqs certificate and private key. .TP \fBPKCS11:\fP[\fBmodule_name=\fP]\fImodname\fP[\fB:slotid=\fP\fIslot\-id\fP][\fB:token=\fP\fItoken\-label\fP][\fB:certid=\fP\fIcert\-id\fP][\fB:certlabel=\fP\fIcert\-label\fP] All keyword/values are optional. \fImodname\fP specifies the location of a library implementing PKCS #11. If a value is encountered with no keyword, it is assumed to be the \fImodname\fP\&. If no module\-name is specified, the default is \fBopensc\-pkcs11.so\fP\&. \fBslotid=\fP and/or \fBtoken=\fP may be specified to force the use of a particular smard card reader or token if there is more than one available. \fBcertid=\fP and/or \fBcertlabel=\fP may be specified to force the selection of a particular certificate on the device. See the \fBpkinit_cert_match\fP configuration option for more ways to select a particular certificate to use for PKINIT. .TP \fBENV:\fP\fIenvvar\fP \fIenvvar\fP specifies the name of an environment variable which has been set to a value conforming to one of the previous values. For example, \fBENV:X509_PROXY\fP, where environment variable \fBX509_PROXY\fP has been set to \fBFILE:/tmp/my_proxy.pem\fP\&. .UNINDENT .SS PKINIT krb5.conf options .INDENT 0.0 .TP \fBpkinit_anchors\fP Specifies the location of trusted anchor (root) certificates which the client trusts to sign KDC certificates. This option may be specified multiple times. These values from the config file are not used if the user specifies X509_anchors on the command line. .TP \fBpkinit_cert_match\fP Specifies matching rules that the client certificate must match before it is used to attempt PKINIT authentication. If a user has multiple certificates available (on a smart card, or via other media), there must be exactly one certificate chosen before attempting PKINIT authentication. This option may be specified multiple times. All the available certificates are checked against each rule in order until there is a match of exactly one certificate. .sp The Subject and Issuer comparison strings are the \fI\%RFC 2253\fP string representations from the certificate Subject DN and Issuer DN values. .sp The syntax of the matching rules is: .INDENT 7.0 .INDENT 3.5 [\fIrelation\-operator\fP]\fIcomponent\-rule\fP ... .UNINDENT .UNINDENT .sp where: .INDENT 7.0 .TP .B \fIrelation\-operator\fP can be either \fB&&\fP, meaning all component rules must match, or \fB||\fP, meaning only one component rule must match. The default is \fB&&\fP\&. .TP .B \fIcomponent\-rule\fP can be one of the following. Note that there is no punctuation or whitespace between component rules. .INDENT 7.0 .INDENT 3.5 .nf \fB\fP\fIregular\-expression\fP \fB\fP\fIregular\-expression\fP \fB\fP\fIregular\-expression\fP \fB\fP\fIextended\-key\-usage\-list\fP \fB\fP\fIkey\-usage\-list\fP .fi .sp .UNINDENT .UNINDENT .sp \fIextended\-key\-usage\-list\fP is a comma\-separated list of required Extended Key Usage values. All values in the list must be present in the certificate. Extended Key Usage values can be: .INDENT 7.0 .IP \(bu 2 pkinit .IP \(bu 2 msScLogin .IP \(bu 2 clientAuth .IP \(bu 2 emailProtection .UNINDENT .sp \fIkey\-usage\-list\fP is a comma\-separated list of required Key Usage values. All values in the list must be present in the certificate. Key Usage values can be: .INDENT 7.0 .IP \(bu 2 digitalSignature .IP \(bu 2 keyEncipherment .UNINDENT .UNINDENT .sp Examples: .INDENT 7.0 .INDENT 3.5 .sp .nf .ft C pkinit_cert_match = ||.*DoE.*.*@EXAMPLE.COM pkinit_cert_match = &&msScLogin,clientAuth.*DoE.* pkinit_cert_match = msScLogin,clientAuthdigitalSignature .ft P .fi .UNINDENT .UNINDENT .TP \fBpkinit_eku_checking\fP This option specifies what Extended Key Usage value the KDC certificate presented to the client must contain. (Note that if the KDC certificate has the pkinit SubjectAlternativeName encoded as the Kerberos TGS name, EKU checking is not necessary since the issuing CA has certified this as a KDC certificate.) The values recognized in the krb5.conf file are: .INDENT 7.0 .TP \fBkpKDC\fP This is the default value and specifies that the KDC must have the id\-pkinit\-KPKdc EKU as defined in \fI\%RFC 4556\fP\&. .TP \fBkpServerAuth\fP If \fBkpServerAuth\fP is specified, a KDC certificate with the id\-kp\-serverAuth EKU will be accepted. This key usage value is used in most commercially issued server certificates. .TP \fBnone\fP If \fBnone\fP is specified, then the KDC certificate will not be checked to verify it has an acceptable EKU. The use of this option is not recommended. .UNINDENT .TP \fBpkinit_dh_min_bits\fP Specifies the size of the Diffie\-Hellman key the client will attempt to use. The acceptable values are 1024, 2048, and 4096. The default is 2048. .TP \fBpkinit_identities\fP Specifies the location(s) to be used to find the user\(aqs X.509 identity information. If this option is specified multiple times, the first valid value is used; this can be used to specify an environment variable (with \fBENV:\fP\fIenvvar\fP) followed by a default value. Note that these values are not used if the user specifies \fBX509_user_identity\fP on the command line. .TP \fBpkinit_kdc_hostname\fP The presense of this option indicates that the client is willing to accept a KDC certificate with a dNSName SAN (Subject Alternative Name) rather than requiring the id\-pkinit\-san as defined in \fI\%RFC 4556\fP\&. This option may be specified multiple times. Its value should contain the acceptable hostname for the KDC (as contained in its certificate). .TP \fBpkinit_pool\fP Specifies the location of intermediate certificates which may be used by the client to complete the trust chain between a KDC certificate and a trusted anchor. This option may be specified multiple times. .TP \fBpkinit_require_crl_checking\fP The default certificate verification process will always check the available revocation information to see if a certificate has been revoked. If a match is found for the certificate in a CRL, verification fails. If the certificate being verified is not listed in a CRL, or there is no CRL present for its issuing CA, and \fBpkinit_require_crl_checking\fP is false, then verification succeeds. .sp However, if \fBpkinit_require_crl_checking\fP is true and there is no CRL information available for the issuing CA, then verification fails. .sp \fBpkinit_require_crl_checking\fP should be set to true if the policy is such that up\-to\-date CRLs must be present for every CA. .TP \fBpkinit_revoke\fP Specifies the location of Certificate Revocation List (CRL) information to be used by the client when verifying the validity of the KDC certificate presented. This option may be specified multiple times. .UNINDENT .SH PARAMETER EXPANSION .sp Starting with release 1.11, several variables, such as \fBdefault_keytab_name\fP, allow parameters to be expanded. Valid parameters are: .INDENT 0.0 .INDENT 3.5 .TS center; |l|l|. _ T{ %{TEMP} T} T{ Temporary directory T} _ T{ %{uid} T} T{ Unix real UID or Windows SID T} _ T{ %{euid} T} T{ Unix effective user ID or Windows SID T} _ T{ %{USERID} T} T{ Same as %{uid} T} _ T{ %{null} T} T{ Empty string T} _ T{ %{LIBDIR} T} T{ Installation library directory T} _ T{ %{BINDIR} T} T{ Installation binary directory T} _ T{ %{SBINDIR} T} T{ Installation admin binary directory T} _ T{ %{username} T} T{ (Unix) Username of effective user ID T} _ T{ %{APPDATA} T} T{ (Windows) Roaming application data for current user T} _ T{ %{COMMON_APPDATA} T} T{ (Windows) Application data for all users T} _ T{ %{LOCAL_APPDATA} T} T{ (Windows) Local application data for current user T} _ T{ %{SYSTEM} T} T{ (Windows) Windows system folder T} _ T{ %{WINDOWS} T} T{ (Windows) Windows folder T} _ T{ %{USERCONFIG} T} T{ (Windows) Per\-user MIT krb5 config file directory T} _ T{ %{COMMONCONFIG} T} T{ (Windows) Common MIT krb5 config file directory T} _ .TE .UNINDENT .UNINDENT .SH SAMPLE KRB5.CONF FILE .sp Here is an example of a generic krb5.conf file: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C [libdefaults] default_realm = ATHENA.MIT.EDU dns_lookup_kdc = true dns_lookup_realm = false [realms] ATHENA.MIT.EDU = { kdc = kerberos.mit.edu kdc = kerberos\-1.mit.edu kdc = kerberos\-2.mit.edu admin_server = kerberos.mit.edu master_kdc = kerberos.mit.edu } EXAMPLE.COM = { kdc = kerberos.example.com kdc = kerberos\-1.example.com admin_server = kerberos.example.com } [domain_realm] mit.edu = ATHENA.MIT.EDU [capaths] ATHENA.MIT.EDU = { EXAMPLE.COM = . } EXAMPLE.COM = { ATHENA.MIT.EDU = . } .ft P .fi .UNINDENT .UNINDENT .SH FILES .sp \fB/etc/krb5.conf\fP .SH SEE ALSO .sp syslog(3) .SH AUTHOR MIT .SH COPYRIGHT 1985-2019, MIT .\" Generated by docutils manpage writer. . man/man5/k5login.5000064400000005417152526542560007640 0ustar00.\" Man page generated from reStructuredText. . .TH "K5LOGIN" "5" " " "1.17" "MIT Kerberos" .SH NAME k5login \- Kerberos V5 acl file for host access . .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 .. .SH DESCRIPTION .sp The .k5login file, which resides in a user\(aqs home directory, contains a list of the Kerberos principals. Anyone with valid tickets for a principal in the file is allowed host access with the UID of the user in whose home directory the file resides. One common use is to place a .k5login file in root\(aqs home directory, thereby granting system administrators remote root access to the host via Kerberos. .SH EXAMPLES .sp Suppose the user \fBalice\fP had a .k5login file in her home directory containing just the following line: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C bob@FOOBAR.ORG .ft P .fi .UNINDENT .UNINDENT .sp This would allow \fBbob\fP to use Kerberos network applications, such as ssh(1), to access \fBalice\fP\(aqs account, using \fBbob\fP\(aqs Kerberos tickets. In a default configuration (with \fBk5login_authoritative\fP set to true in krb5.conf(5)), this .k5login file would not let \fBalice\fP use those network applications to access her account, since she is not listed! With no .k5login file, or with \fBk5login_authoritative\fP set to false, a default rule would permit the principal \fBalice\fP in the machine\(aqs default realm to access the \fBalice\fP account. .sp Let us further suppose that \fBalice\fP is a system administrator. Alice and the other system administrators would have their principals in root\(aqs .k5login file on each host: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C alice@BLEEP.COM joeadmin/root@BLEEP.COM .ft P .fi .UNINDENT .UNINDENT .sp This would allow either system administrator to log in to these hosts using their Kerberos tickets instead of having to type the root password. Note that because \fBbob\fP retains the Kerberos tickets for his own principal, \fBbob@FOOBAR.ORG\fP, he would not have any of the privileges that require \fBalice\fP\(aqs tickets, such as root access to any of the site\(aqs hosts, or the ability to change \fBalice\fP\(aqs password. .SH SEE ALSO .sp kerberos(1) .SH AUTHOR MIT .SH COPYRIGHT 1985-2019, MIT .\" Generated by docutils manpage writer. . man/man5/k5identity.5000064400000005766152526542560010370 0ustar00.\" Man page generated from reStructuredText. . .TH "K5IDENTITY" "5" " " "1.17" "MIT Kerberos" .SH NAME k5identity \- Kerberos V5 client principal selection rules . .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 .. .SH DESCRIPTION .sp The .k5identity file, which resides in a user\(aqs home directory, contains a list of rules for selecting a client principals based on the server being accessed. These rules are used to choose a credential cache within the cache collection when possible. .sp Blank lines and lines beginning with \fB#\fP are ignored. Each line has the form: .INDENT 0.0 .INDENT 3.5 \fIprincipal\fP \fIfield\fP=\fIvalue\fP ... .UNINDENT .UNINDENT .sp If the server principal meets all of the field constraints, then principal is chosen as the client principal. The following fields are recognized: .INDENT 0.0 .TP \fBrealm\fP If the realm of the server principal is known, it is matched against \fIvalue\fP, which may be a pattern using shell wildcards. For host\-based server principals, the realm will generally only be known if there is a domain_realm section in krb5.conf(5) with a mapping for the hostname. .TP \fBservice\fP If the server principal is a host\-based principal, its service component is matched against \fIvalue\fP, which may be a pattern using shell wildcards. .TP \fBhost\fP If the server principal is a host\-based principal, its hostname component is converted to lower case and matched against \fIvalue\fP, which may be a pattern using shell wildcards. .sp If the server principal matches the constraints of multiple lines in the .k5identity file, the principal from the first matching line is used. If no line matches, credentials will be selected some other way, such as the realm heuristic or the current primary cache. .UNINDENT .SH EXAMPLE .sp The following example .k5identity file selects the client principal \fBalice@KRBTEST.COM\fP if the server principal is within that realm, the principal \fBalice/root@EXAMPLE.COM\fP if the server host is within a servers subdomain, and the principal \fBalice/mail@EXAMPLE.COM\fP when accessing the IMAP service on \fBmail.example.com\fP: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C alice@KRBTEST.COM realm=KRBTEST.COM alice/root@EXAMPLE.COM host=*.servers.example.com alice/mail@EXAMPLE.COM host=mail.example.com service=imap .ft P .fi .UNINDENT .UNINDENT .SH SEE ALSO .sp kerberos(1), krb5.conf(5) .SH AUTHOR MIT .SH COPYRIGHT 1985-2019, MIT .\" Generated by docutils manpage writer. . man/man5/.k5login.5000064400000000023152526542560007702 0ustar00.so man5/k5login.5 man/man5/.k5identity.5000064400000000026152526542560010426 0ustar00.so man5/k5identity.5 man/man7/kerberos.7000064400000016310152526542560010102 0ustar00.\" Man page generated from reStructuredText. . .TH "KERBEROS" "7" " " "1.17" "MIT Kerberos" .SH NAME kerberos \- Overview of using Kerberos . .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 .. .SH DESCRIPTION .sp The Kerberos system authenticates individual users in a network environment. After authenticating yourself to Kerberos, you can use Kerberos\-enabled programs without having to present passwords or certificates to those programs. .sp If you receive the following response from kinit(1): .sp kinit: Client not found in Kerberos database while getting initial credentials .sp you haven\(aqt been registered as a Kerberos user. See your system administrator. .sp A Kerberos name usually contains three parts. The first is the \fBprimary\fP, which is usually a user\(aqs or service\(aqs name. The second is the \fBinstance\fP, which in the case of a user is usually null. Some users may have privileged instances, however, such as \fBroot\fP or \fBadmin\fP\&. In the case of a service, the instance is the fully qualified name of the machine on which it runs; i.e. there can be an ssh service running on the machine ABC (\fI\%ssh/ABC@REALM\fP), which is different from the ssh service running on the machine XYZ (\fI\%ssh/XYZ@REALM\fP). The third part of a Kerberos name is the \fBrealm\fP\&. The realm corresponds to the Kerberos service providing authentication for the principal. Realms are conventionally all\-uppercase, and often match the end of hostnames in the realm (for instance, host01.example.com might be in realm EXAMPLE.COM). .sp When writing a Kerberos name, the principal name is separated from the instance (if not null) by a slash, and the realm (if not the local realm) follows, preceded by an "@" sign. The following are examples of valid Kerberos names: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C david jennifer/admin joeuser@BLEEP.COM cbrown/root@FUBAR.ORG .ft P .fi .UNINDENT .UNINDENT .sp When you authenticate yourself with Kerberos you get an initial Kerberos \fBticket\fP\&. (A Kerberos ticket is an encrypted protocol message that provides authentication.) Kerberos uses this ticket for network utilities such as ssh. The ticket transactions are done transparently, so you don\(aqt have to worry about their management. .sp Note, however, that tickets expire. Administrators may configure more privileged tickets, such as those with service or instance of \fBroot\fP or \fBadmin\fP, to expire in a few minutes, while tickets that carry more ordinary privileges may be good for several hours or a day. If your login session extends beyond the time limit, you will have to re\-authenticate yourself to Kerberos to get new tickets using the kinit(1) command. .sp Some tickets are \fBrenewable\fP beyond their initial lifetime. This means that \fBkinit \-R\fP can extend their lifetime without requiring you to re\-authenticate. .sp If you wish to delete your local tickets, use the kdestroy(1) command. .sp Kerberos tickets can be forwarded. In order to forward tickets, you must request \fBforwardable\fP tickets when you kinit. Once you have forwardable tickets, most Kerberos programs have a command line option to forward them to the remote host. This can be useful for, e.g., running kinit on your local machine and then sshing into another to do work. Note that this should not be done on untrusted machines since they will then have your tickets. .SH ENVIRONMENT VARIABLES .sp Several environment variables affect the operation of Kerberos\-enabled programs. These include: .INDENT 0.0 .TP \fBKRB5CCNAME\fP Default name for the credentials cache file, in the form \fITYPE\fP:\fIresidual\fP\&. The type of the default cache may determine the availability of a cache collection. \fBFILE\fP is not a collection type; \fBKEYRING\fP, \fBDIR\fP, and \fBKCM\fP are. .sp If not set, the value of \fBdefault_ccache_name\fP from configuration files (see \fBKRB5_CONFIG\fP) will be used. If that is also not set, the default \fItype\fP is \fBFILE\fP, and the \fIresidual\fP is the path /tmp/krb5cc_*uid*, where \fIuid\fP is the decimal user ID of the user. .TP \fBKRB5_KTNAME\fP Specifies the location of the default keytab file, in the form \fITYPE\fP:\fIresidual\fP\&. If no \fItype\fP is present, the \fBFILE\fP type is assumed and \fIresidual\fP is the pathname of the keytab file. If unset, \fBFILE:/etc/krb5.keytab\fP will be used. .TP \fBKRB5_CONFIG\fP Specifies the location of the Kerberos configuration file. The default is \fB/etc\fP\fB/krb5.conf\fP\&. Multiple filenames can be specified, separated by a colon; all files which are present will be read. .TP \fBKRB5_KDC_PROFILE\fP Specifies the location of the KDC configuration file, which contains additional configuration directives for the Key Distribution Center daemon and associated programs. The default is \fB/opt/alt/krb5/usr/var\fP\fB/krb5kdc\fP\fB/kdc.conf\fP\&. .TP \fBKRB5RCACHETYPE\fP Specifies the default type of replay cache to use for servers. Valid types include \fBdfl\fP for the normal file type and \fBnone\fP for no replay cache. The default is \fBdfl\fP\&. .TP \fBKRB5RCACHEDIR\fP Specifies the default directory for replay caches used by servers. The default is the value of the \fBTMPDIR\fP environment variable, or \fB/var/tmp\fP if \fBTMPDIR\fP is not set. .TP \fBKRB5_TRACE\fP Specifies a filename to write trace log output to. Trace logs can help illuminate decisions made internally by the Kerberos libraries. For example, \fBenv KRB5_TRACE=/dev/stderr kinit\fP would send tracing information for kinit(1) to \fB/dev/stderr\fP\&. The default is not to write trace log output anywhere. .TP \fBKRB5_CLIENT_KTNAME\fP Default client keytab file name. If unset, \fBFILE:/opt/alt/krb5/usr/var/krb5/user/%{euid}/client.keytab\fP will be used). .TP \fBKPROP_PORT\fP kprop(8) port to use. Defaults to 754. .UNINDENT .sp Most environment variables are disabled for certain programs, such as login system programs and setuid programs, which are designed to be secure when run within an untrusted process environment. .SH SEE ALSO .sp kdestroy(1), kinit(1), klist(1), kswitch(1), kpasswd(1), ksu(1), krb5.conf(5), kdc.conf(5), kadmin(1), kadmind(8), kdb5_util(8), krb5kdc(8) .SH BUGS .SH AUTHORS .nf Steve Miller, MIT Project Athena/Digital Equipment Corporation Clifford Neuman, MIT Project Athena Greg Hudson, MIT Kerberos Consortium Robbie Harwood, Red Hat, Inc. .fi .sp .SH HISTORY .sp The MIT Kerberos 5 implementation was developed at MIT, with contributions from many outside parties. It is currently maintained by the MIT Kerberos Consortium. .SH RESTRICTIONS .sp Copyright 1985, 1986, 1989\-1996, 2002, 2011, 2018 Masachusetts Institute of Technology .SH AUTHOR MIT .SH COPYRIGHT 1985-2019, MIT .\" Generated by docutils manpage writer. . doc/alt-libssh2/COPYING000064400000003536152527006560010507 0ustar00/* Copyright (c) 2004-2007 Sara Golemon * Copyright (c) 2005,2006 Mikhail Gusarov * Copyright (c) 2006-2007 The Written Word, Inc. * Copyright (c) 2007 Eli Fant * Copyright (c) 2009-2014 Daniel Stenberg * Copyright (C) 2008, 2009 Simon Josefsson * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * 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. * * Neither the name of the copyright holder nor the names * of any other contributors may be used to endorse or * promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "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 COPYRIGHT OWNER OR * CONTRIBUTORS 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. */ doc/alt-libssh2/README000064400000000734152527006560010331 0ustar00libssh2 - SSH2 library ====================== libssh2 is a library implementing the SSH2 protocol, available under the revised BSD license. Web site: https://www.libssh2.org/ Mailing list: https://cool.haxx.se/mailman/listinfo/libssh2-devel License: see COPYING Source code: https://github.com/libssh2/libssh2 Web site source code: https://github.com/libssh2/www Installation instructions are in: - docs/INSTALL_CMAKE for CMake - docs/INSTALL_AUTOTOOLS for Autotools doc/alt-libssh2/ChangeLog000064400000000011152527006560011207 0ustar00see NEWS doc/alt-libssh2/NEWS000064400000551116152527006560010155 0ustar00 Changelog for the libssh2 project. Generated with git2news.pl Version 1.8.0 (25 Oct 2016) Daniel Stenberg (25 Oct 2016) - RELEASE-NOTES: adjusted for 1.8.0 Kamil Dudka (20 Oct 2016) - Revert "aes: the init function fails when OpenSSL has AES support" This partially reverts commit f4f2298ef3635acd031cc2ee0e71026cdcda5864 because it caused the compatibility code to call initialization routines redundantly, leading to memory leakage with OpenSSL 1.1 and broken curl test-suite in Fedora: 88 bytes in 1 blocks are definitely lost in loss record 5 of 8 at 0x4C2DB8D: malloc (vg_replace_malloc.c:299) by 0x72C607D: CRYPTO_zalloc (mem.c:100) by 0x72A2480: EVP_CIPHER_meth_new (cmeth_lib.c:18) by 0x4E5A550: make_ctr_evp.isra.0 (openssl.c:407) by 0x4E5A8E8: _libssh2_init_aes_ctr (openssl.c:471) by 0x4E5BB5A: libssh2_init (global.c:49) Daniel Stenberg (19 Oct 2016) - [Charles Collicutt brought this change] libssh2_wait_socket: Fix comparison with api_timeout to use milliseconds (#134) Fixes #74 - [Charles Collicutt brought this change] Set err_msg on _libssh2_wait_socket errors (#135) - Revert "travis: Test mbedtls too" This reverts commit 3e6de50a24815e72ec5597947f1831f6083b7da8. Travis doesn't seem to support the mbedtls-dev package - maketgz: support "only" to only update version number locally and fix the date output locale - configure: make the --with-* options override the OpenSSL default ... previously it would default to OpenSSL even with the --with-[crypto] options used unless you specificly disabled OpenSSL. Now, enabling another backend will automatically disable OpenSSL if the other one is found. - [Keno Fischer brought this change] docs: Add documentation on new cmake/configure options - [Keno Fischer brought this change] configure: Add support for building with mbedtls - [wildart brought this change] travis: Test mbedtls too - [wildart brought this change] crypto: add support for the mbedTLS backend Closes #132 - [wildart brought this change] cmake: Add CLEAR_MEMORY option, analogously to that for autoconf - README.md: fix link typo - README: markdown version to look nicer on github Viktor Szakats (5 Sep 2016) - [Taylor Holberton brought this change] openssl: add OpenSSL 1.1.0 compatibility Daniel Stenberg (4 Sep 2016) - [Antenore Gatta brought this change] tests: HAVE_NETINET_IN_H was not defined correctly (#127) Fixes #125 - SECURITY: fix web site typo - SECURITY: security process GitHub (14 Aug 2016) - [Alexander Lamaison brought this change] Basic dockerised test suite. This introduces a test suite for libssh2. It runs OpenSSH in a Docker container because that works well on Windows (via docker-machine) as well as Linux. Presumably it works on Mac too with docker-machine, but I've not tested that. Because the test suite is docker-machine aware, you can also run it against a cloud provider, for more realistic network testing, by setting your cloud provider as your active docker machine. The Appveyor CI setup in this commit does that because Appveyor doesn't support docker locally. Kamil Dudka (3 Aug 2016) - [Viktor Szakats brought this change] misc.c: Delete unused static variables Closes #114 Daniel Stenberg (9 Apr 2016) - [Will Cosgrove brought this change] Merge pull request #103 from willco007/patch-2 Fix for security issue CVE-2016-0787 Alexander Lamaison (2 Apr 2016) - [Zenju brought this change] Fix MSVC 14 compilation errors For _MSC_VER == 1900 these macros are not needed and create problems: 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt\stdio.h(1925): warning C4005: 'snprintf': macro redefinition (compiling source file libssh2-files\src\mac.c) 1> \win32\libssh2_config.h(27): note: see previous definition of 'snprintf' (compiling source file libssh2-files\src\mac.c) 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt\stdio.h(1927): fatal error C1189: #error: Macro definition of snprintf conflicts with Standard Library function declaration (compiling source file libssh2-files\src\mac.c) Daniel Stenberg (26 Mar 2016) - [Brad Harder brought this change] _libssh2_channel_open: speeling error fixed in channel error message Alexander Lamaison (15 Mar 2016) - Link with crypt32.lib on Windows. Makes linking with static OpenSSL work again. Although it's not required for dynamic OpenSSL, it does no harm. Fixes #98. - [Craig A. Berry brought this change] Tweak VMS help file building. Primarily this is handling cases where top-level files moved into the docs/ directory. I also corrected a typo and removed the claim that libssh2 is public domain. - [Craig A. Berry brought this change] Build with standard stat structure on VMS. This gets us large file support, is available on any VMS release in the last decade and more, and gives stat other modern features such as 64-bit ino_t. - [Craig A. Berry brought this change] Update vms/libssh2_config.h. VMS does have stdlib.h, gettimeofday(), and OpenSSL. The latter is appropriate to hard-wire in the configuration because it's installed by default as part of the base operating system and there is currently no libgcrypt port. - [Craig A. Berry brought this change] VMS can't use %zd for off_t format. %z is a C99-ism that VMS doesn't currently have; even though the compiler is C99-compliant, the library isn't quite. The off_t used for the st_size element of the stat can be 32-bit or 64-bit, so detect what we've got and pick a format accordingly. - [Craig A. Berry brought this change] Normalize line endings in libssh2_sftp_get_channel.3. Somehow it got Windows-style CRLF endings so convert to just LF, for consistency as well as not to confuse tools that will regard the \r as content (e.g. the OpenVMS help librarian). Dan Fandrich (29 Feb 2016) - libgcrypt: Fixed a NULL pointer dereference on OOM Daniel Stenberg (24 Feb 2016) - [Viktor Szakats brought this change] url updates, HTTP => HTTPS Closes #87 Dan Fandrich (23 Feb 2016) - RELEASE-NOTES: removed some duplicated names Version 1.7.0 (23 Feb 2016) Daniel Stenberg (23 Feb 2016) - web: the site is now HTTPS - RELEASE-NOTES: 1.7.0 release - diffie_hellman_sha256: convert bytes to bits As otherwise we get far too small numbers. Reported-by: Andreas Schneider CVE-2016-0787 Alexander Lamaison (18 Feb 2016) - Allow CI failures with VS 2008 x64. Appveyor doesn't support this combination. Daniel Stenberg (16 Feb 2016) - [Viktor Szakats brought this change] GNUmakefile: list system libs after user libs Otherwise some referenced WinSock functions will fail to resolve when linking against LibreSSL 2.3.x static libraries with mingw. Closes #80 - [Viktor Szakats brought this change] openssl: apply new HAVE_OPAQUE_STRUCTS macro Closes #81 - [Viktor Szakats brought this change] openssl: fix LibreSSL support after OpenSSL 1.1.0-pre1/2 support Alexander Lamaison (14 Feb 2016) - sftp.h: Fix non-C90 type. uint64_t does not exist in C90. Use libssh2_uint64_t instead. - Exclude sshd tests from AppVeyor. They fail complaining that sshd wasn't invoked with an absolute path. - Test on more versions of Visual Studio. - Fix Appveyor builds. Daniel Stenberg (14 Feb 2016) - [Viktor Szakats brought this change] openssl: add OpenSSL 1.1.0-pre3-dev compatibility by using API instead of accessing an internal structure. Closes #83 - RELEASE-NOTES: synced with 996b04ececdf - include/libssh2.h: next version is 1.7.0 - configure: build "silent" if possible - sftp: re-indented some minor stuff - [Jakob Egger brought this change] sftp.c: ensure minimum read packet size For optimum performance we need to ensure we don't request tiny packets. - [Jakob Egger brought this change] sftp.c: Explicit return values & sanity checks - [Jakob Egger brought this change] sftp.c: Check Read Packet File Offset This commit adds a simple check to see if the offset of the read request matches the expected file offset. We could try to recover, from this condition at some point in the future. Right now it is better to return an error instead of corrupted data. - [Jakob Egger brought this change] sftp.c: Don't return EAGAIN if data was written to buffer - [Jakob Egger brought this change] sftp.c: Send at least one read request before reading This commit ensures that we have sent at least one read request before we try to read data in sftp_read(). Otherwise sftp_read() would return 0 bytes (indicating EOF) if the socket is not ready for writing. - [Jakob Egger brought this change] sftp.c: stop reading when buffer is full Since we can only store data from a single chunk in filep, we have to stop receiving data as soon as the buffer is full. This adresses the following bug report: https://github.com/libssh2/libssh2/issues/50 Salvador Fandiño (21 Jan 2016) - agent_disconnect_unix: unset the agent fd after closing it "agent_disconnect_unix", called by "libssh2_agent_disconnect", was leaving the file descriptor in the agent structure unchanged. Later, "libssh2_agent_free" would call again "libssh2_agent_disconnect" under the hood and it would try to close again the same file descriptor. In most cases that resulted in just a harmless error, but it is also possible that the file descriptor had been reused between the two calls resulting in the closing of an unrelated file descriptor. This patch sets agent->fd to LIBSSH2_INVALID_SOCKET avoiding that issue. Signed-off-by: Salvador Fandiño Daniel Stenberg (18 Jan 2016) - [Patrick Monnerat brought this change] os400qc3: support encrypted private keys PKCS#8 EncryptedPrivateKeyinfo structures are recognized and decoded to get values accepted by the Qc3 crypto library. - [Patrick Monnerat brought this change] os400qc3: New PKCS#5 decoder The Qc3 library is not able to handle PKCS#8 EncryptedPrivateKeyInfo structures by itself. It is only capable of decrypting the (encrypted) PrivateKeyInfo part, providing a key encryption key and an encryption algorithm are given. Since the encryption key and algorithm description part in a PKCS#8 EncryptedPrivateKeyInfo is a PKCS#5 structure, such a decoder is needed to get the derived key method and hash, as well as encryption algorith and initialisation vector. - [Patrick Monnerat brought this change] os400qc3: force continuous update on non-final hash/hmac computation - [Patrick Monnerat brought this change] os400qc3: Be sure hmac keys have a minimum length The Qc3 library requires a minimum key length depending on the target hash algorithm. Append binary zeroes to the given key if not long enough. This matches RFC 2104 specifications. - [Patrick Monnerat brought this change] os400qc3: Slave descriptor for key encryption key The Qc3 library requires the key encryption key to exist as long as the encrypted key is used. Its descriptor token is then kept as an "encrypted key slave" for recursive release. - [Patrick Monnerat brought this change] os400qc3.c: comment PEM/DER decoding - [Patrick Monnerat brought this change] os400qc3.c: improve ASN.1 header byte checks - [Patrick Monnerat brought this change] os400qc3.c: improve OID matching - [Patrick Monnerat brought this change] os400: os400qc3.c: replace malloc by LIBSSH2_ALLOC or alloca where possible - [Patrick Monnerat brought this change] os400: asn1_new_from_bytes(): use data from a single element only - [Patrick Monnerat brought this change] os400: fix an ILE/RPG prototype - [Patrick Monnerat brought this change] os400: implement character encoding conversion support - [Patrick Monnerat brought this change] os400: do not miss some external prototypes Build procedure extproto() did not strip braces from header files, thus possibly prepended them to true prototypes. This prevented the prototype to be recognized as such. The solution implemented here is to map braces to semicolons, effectively considering them as potential prototype delimiters. - [Patrick Monnerat brought this change] os400: Really add specific README - [Patrick Monnerat brought this change] os400: Add specific README and include new files in dist tarball - [Patrick Monnerat brought this change] os400: add compilation scripts - [Patrick Monnerat brought this change] os400: include files for ILE/RPG In addition, file os400/macros.h declares all procedures originally defined as macros. It must not be used for real inclusion and is only intended to be used as a `database' for macro wrapping procedures generation. - [Patrick Monnerat brought this change] os400: add supplementary header files/wrappers. Define configuration. - [Patrick Monnerat brought this change] Protect callback function calls from macro substitution Some structure fields holding callback addresses have the same name as the underlying system function (connect, send, recv). Set parentheses around their reference to suppress a possible macro substitution. Use a macro for connect() on OS/400 to resolve a const/nonconst parameter problem. - [Patrick Monnerat brought this change] Add interface for OS/400 crypto library QC3 - [Patrick Monnerat brought this change] misc: include stdarg.h for debug code - [Patrick Monnerat brought this change] Document crypto library interface - [Patrick Monnerat brought this change] Feature an optional crypto-specific macro to rsa sign a data fragment vector OS/400 crypto library is unable to sign a precomputed SHA1 hash: however it does support a procedure that hashes data fragments and rsa signs. If defined, the new macro _libssh2_rsa_sha1_signv() implements this function and disables use of _libssh2_rsa_sha1_sign(). The function described above requires that the struct iovec unused slacks are cleared: for this reason, macro libssh2_prepare_iovec() has been introduced. It should be defined as empty for crypto backends that are not sensitive to struct iovec unused slack values. - [Patrick Monnerat brought this change] Fold long lines in include files - [Viktor Szakats brought this change] kex.c: fix indentation Closes #71 - [Viktor Szakats brought this change] add OpenSSL-1.1.0-pre2 compatibility Closes #70 - [Viktor Szakats brought this change] add OpenSSL 1.1.0-pre1 compatibility * close https://github.com/libssh2/libssh2/issues/69 * sync a declaration with the rest of similar ones * handle EVP_MD_CTX_new() returning NULL with OpenSSL 1.1.0 * fix potential memory leak with OpenSSL 1.1.0 in _libssh2_*_init() functions, when EVP_MD_CTX_new() succeeds, but EVP_DigestInit() fails. Marc Hoersken (22 Dec 2015) - wincng.c: fixed _libssh2_wincng_hash_final return value _libssh2_wincng_hash_final was returning the internal BCRYPT status code instead of a valid libssh2 return value (0 or -1). This also means that _libssh2_wincng_hash never returned 0. - wincng.c: fixed possible memory leak in _libssh2_wincng_hash If _libssh2_wincng_hash_update failed _libssh2_wincng_hash_final would never have been called before. Reported by Zenju. Kamil Dudka (15 Dec 2015) - [Paul Howarth brought this change] libssh2.pc.in: fix the output of pkg-config --libs ... such that it does not include LDFLAGS used to build libssh2 itself. There was a similar fix in the curl project long time ago: https://github.com/bagder/curl/commit/curl-7_19_7-56-g4c8adc8 Bug: https://bugzilla.redhat.com/1279966 Signed-off-by: Kamil Dudka Marc Hoersken (6 Dec 2015) - hostkey.c: align code path of ssh_rsa_init to ssh_dss_init - hostkey.c: fix invalid memory access if libssh2_dsa_new fails Reported by dimmaq, fixes #66 Daniel Stenberg (3 Nov 2015) - [Will Cosgrove brought this change] gcrypt: define libssh2_sha256_ctx Looks like it didn't make it into the latest commit for whatever reason. Closes #58 - [Salvador Fandino brought this change] libssh2_session_set_last_error: Add function Net::SSH2, the Perl wrapping module for libssh2 implements several features* on top of libssh2 that can fail and so need some mechanism to report the error condition to the user. Until now, besides the error state maintained internally by libssh2, another error state was maintained at the Perl level for every session object and then additional logic was used to merge both error states. That is a maintenance nighmare, and actually there is no way to do it correctly and consistently. In order to allow the high level language to add new features to the library but still rely in its error reporting features the new function libssh2_session_set_last_error (that just exposses _libssh2_error_flags) is introduced. *) For instance, connecting to a remote SSH service giving the hostname and port. Signed-off-by: Salvador Fandino Signed-off-by: Salvador Fandiño - [Salvador Fandino brought this change] _libssh2_error: Support allocating the error message Before this patch "_libssh2_error" required the error message to be a static string. This patch adds a new function "_libssh2_error_flags" accepting an additional "flags" argument and specifically the flag "LIBSSH2_ERR_FLAG_DUP" indicating that the passed string must be duplicated into the heap. Then, the method "_libssh2_error" has been rewritten to use that new function under the hood. Signed-off-by: Salvador Fandino Signed-off-by: Salvador Fandiño - [Will Cosgrove brought this change] added engine.h include to fix warning - [sune brought this change] kex.c: removed dupe entry from libssh2_kex_methods[] Closes #51 - [Salvador Fandiño brought this change] userauth: Fix off by one error when reading public key file After reading the public key from file the size was incorrectly decremented by one. This was usually a harmless error as the last character on the public key file is an unimportant EOL. But if due to some error the public key file is empty, the public key size becomes (uint)(0 - 1), resulting in an unrecoverable out of memory error later. Signed-off-by: Salvador Fandi??o - [Salvador Fandino brought this change] channel: Detect bad usage of libssh2_channel_process_startup A common novice programmer error (at least among those using the wrapping Perl module Net::SSH2), is to try to reuse channels. This patchs detects that incorrect usage and fails with a LIBSSH2_ERROR_BAD_USE error instead of hanging. Signed-off-by: Salvador Fandino - [Will Cosgrove brought this change] kex: Added diffie-hellman-group-exchange-sha256 support ... and fixed HMAC_Init depricated usage Closes #48 Alexander Lamaison (21 Sep 2015) - Prefixed new #defines to prevent collisions. Other libraries might have their own USE_WIN32_*FILES. - [keith-daigle brought this change] Update examples/scp.c to fix bug where large files on win32 would cause got to wrap and go negative - [David Byron brought this change] add libssh2_scp_recv2 to support large (> 2GB) files on windows Daniel Stenberg (17 Sep 2015) - [sune brought this change] WinCNG: support for SHA256/512 HMAC Closes #47 - [brian m. carlson brought this change] Add support for HMAC-SHA-256 and HMAC-SHA-512. Implement support for these algorithms and wire them up to the libgcrypt and OpenSSL backends. Increase the maximum MAC buffer size to 64 bytes to prevent buffer overflows. Prefer HMAC-SHA-256 over HMAC-SHA-512, and that over HMAC-SHA-1, as OpenSSH does. Closes #40 - [Zenju brought this change] kex: free server host key before allocating it (again) Fixes a memory leak when Synology server requests key exchange Closes #43 - [Viktor Szakats brought this change] GNUmakefile: up OpenSSL version closes #23 - [Viktor Szakats brought this change] GNUmakefile: add -m64 CFLAGS when targeting mingw64, add -m32/-m64 to LDFLAGS libssh2 equivalent of curl patch https://github.com/bagder/curl/commit/d21b66835f2af781a3c2a685abc92ef9f0cd86be This allows to build for the non-default target when using a multi-target mingw distro. Also bump default OpenSSL dependency path to 1.0.2c. - [Viktor Szakats brought this change] GNUmakefile: add support for LIBSSH2_LDFLAG_EXTRAS It is similar to existing LIBSSH2_CFLAG_EXTRAS, but for extra linker options. Also delete some line/file ending whitespace. closes #27 - [nasacj brought this change] hostkey.c: Fix compiling error when OPENSSL_NO_MD5 is defined Closes #32 - [Mizunashi Mana brought this change] openssl.h: adjust the rsa/dsa includes ... to work when built without DSA support. Closes #36 Alexander Lamaison (26 Jul 2015) - Let CMake build work as a subproject. Patch contributed by JasonHaslam. - Fix builds with Visual Studio 2015. VS2015 moved stdio functions to the header files as inline function. That means check_function_exists can't detect them because it doesn't use header files - just does a link check. Instead we need to use check_symbol_exists with the correct headers. Kamil Dudka (2 Jul 2015) - cmake: include CMake files in the release tarballs Despite we announced the CMake support in libssh2-1.6.0 release notes, the files required by the CMake build system were not included in the release tarballs. Hence, the only way to use CMake for build was the upstream git repository. This commit makes CMake actually supported in the release tarballs. - tests/mansyntax.sh: fix 'make distcheck' with recent autotools Do not create symbolic links off the build directory. Recent autotools verify that out-of-source build works even if the source directory tree is not writable. - openssl: fix memleak in _libssh2_dsa_sha1_verify() Daniel Stenberg (12 Jun 2015) - openssl: make libssh2_sha1 return error code - use the internal prefix _libssh2_ for non-exported functions - removed libssh2_md5() since it wasn't used Reported-by: Kamil Dudka - [LarsNordin-LNdata brought this change] SFTP: Increase speed and datasize in SFTP read The function sftp_read never return more then 2000 bytes (as it should when I asked Daniel). I increased the MAX_SFTP_READ_SIZE to 30000 but didn't get the same speed as a sftp read in SecureSSH. I analyzed the code and found that a return always was dona when a chunk has been read. I changed it to a sliding buffer and worked on all available chunks. I got an increase in speed and non of the test I have done has failed (both local net and over Internet). Please review and test. I think 30000 is still not the optimal MAX_SFTP_READ_SIZE, my next goal is to make an API to enable changing this value (The SecureSSH sftp_read has more complete filled packages when comparing the network traffic) - bump: start working on 1.6.1 Version 1.6.0 (5 Jun 2015) Daniel Stenberg (5 Jun 2015) - RELEASE-NOTES: synced with 858930cae5c6a Marc Hoersken (19 May 2015) - wincng.c: fixed indentation - [sbredahl brought this change] wincng.c: fixed memleak in (block) cipher destructor Alexander Lamaison (6 May 2015) - [Jakob Egger brought this change] libssh2_channel_open: more detailed error message The error message returned by libssh2_channel_open in case of a server side channel open failure is now more detailed and includes the four standard error conditions in RFC 4254. - [Hannes Domani brought this change] kex: fix libgcrypt memory leaks of bignum Fixes #168. Marc Hoersken (3 Apr 2015) - configure.ac: check for SecureZeroMemory for clear memory feature - Revert "wincng.c: fix clear memory feature compilation with mingw" This reverts commit 2d2744efdd0497b72b3e1ff6e732aa4c0037fc43. Autobuilds show that this did not solve the issue. And it seems like RtlFillMemory is defined to memset, which would be optimized out by some compilers. - wincng.c: fix clear memory feature compilation with mingw Alexander Lamaison (1 Apr 2015) - [LarsNordin-LNdata brought this change] Enable use of OpenSSL that doesn't have DSA. Added #if LIBSSH2_DSA for all DSA functions. - [LarsNordin-LNdata brought this change] Use correct no-blowfish #define with OpenSSL. The OpenSSL define is OPENSSL_NO_BF, not OPENSSL_NO_BLOWFISH. Marc Hoersken (25 Mar 2015) - configure: error if explicitly enabled clear-memory is not supported This takes 22bd8d81d8fab956085e2079bf8c29872455ce59 and b8289b625e291bbb785ed4add31f4759241067f3 into account, but still makes it enabled by default if it is supported and error out in case it is unsupported and was requested. Daniel Stenberg (25 Mar 2015) - configure: make clear-memory default but only WARN if backend unsupported ... instead of previous ERROR. Marc Hoersken (24 Mar 2015) - wincng.h: fix warning about computed return value not being used - nonblocking examples: fix warning about unused tvdiff on Mac OS X Daniel Stenberg (24 Mar 2015) - openssl: fix compiler warnings - cofigure: fix --disable-clear-memory check Marc Hoersken (23 Mar 2015) - scp.c: improved command length calculation Reduced number of calls to strlen, because shell_quotearg already returns the length of the resulting string (e.q. quoted path) which we can add to the existing and known cmd_len. Removed obsolete call to memset again, because we can put a final NULL-byte at the end of the string using the calculated length. - scp.c: improved and streamlined formatting - scp.c: fix that scp_recv may transmit not initialised memory - scp.c: fix that scp_send may transmit not initialised memory Fixes ticket 244. Thanks Torsten. - kex: do not ignore failure of libssh2_sha1_init() Based upon 43b730ce56f010e9d33573fcb020df49798c1ed8. Fixes ticket 290. Thanks for the suggestion, mstrsn. - wincng.h: fix return code of libssh2_md5_init() - openssl.c: fix possible segfault in case EVP_DigestInit fails - wincng.c: fix possible use of uninitialized variables - wincng.c: fix unused argument warning if clear memory is not enabled - wincng: Added explicit clear memory feature to WinCNG backend This re-introduces the original feature proposed during the development of the WinCNG crypto backend. It still needs to be added to libssh2 itself and probably other backends. Memory is cleared using the function SecureZeroMemory which is available on Windows systems, just like the WinCNG backend. - wincng.c: fixed mixed line-endings - wincng.c: fixed use of invalid parameter types in a8d14c5dcf - wincng.c: only try to load keys corresponding to the algorithm - wincng.c: moved PEM headers into definitions - wincng.h: fixed invalid parameter name - wincng: fixed mismatch with declarations in crypto.h - userauth.c: fixed warning C6001: using uninitialized sig and sig_len - pem.c: fixed warning C6269: possible incorrect order of operations - wincng: add support for authentication keys to be passed in memory Based upon 18cfec8336e and daa2dfa2db. - pem.c: add _libssh2_pem_parse_memory to parse PEM from memory Requirement to implement 18cfec8336e for Libgcrypt and WinCNG. - pem.c: fix copy and paste mistake from 55d030089b8 - userauth.c: fix another possible dereference of a null pointer - userauth.c: fix possible dereference of a null pointer - pem.c: reduce number of calls to strlen in readline Alexander Lamaison (17 Mar 2015) - [Will Cosgrove brought this change] Initialise HMAC_CTX in more places. Missed a couple more places we init ctx to avoid openssl threading crash. - Build build breakage in WinCNG backend caused when adding libssh2_userauth_publickey_frommemory. The new feature isn't implemented for the WinCNG backend currently, but the WinCNG backend didn't contain any implementation of the required backend functions - even ones that returns an error. That caused link errors. This change fixes the problem by providing an implementation of the backend functions that returns an error. - Fix breakage in WinCNG backend caused by introducing libssh2_hmac_ctx_init. The macro was defined to nothing for the libgcrypt backend, but not for WinCNG. This brings the latter into line with the former. Daniel Stenberg (15 Mar 2015) - userauth_publickey_frommemory.3: add AVAILABILITY ... it will be added in 1.6.0 - libssh2: next version will be called 1.6.0 ... since we just added a new function. - docs: add libssh2_userauth_publickey_frommemory.3 to dist The function and man page were added in commit 18cfec8336e - [Jakob Egger brought this change] direct_tcpip: Fixed channel write There were 3 bugs in this loop: 1) Started from beginning after partial writes 2) Aborted when 0 bytes were sent 3) Ignored LIBSSH2_ERROR_EAGAIN See also: https://trac.libssh2.org/ticket/281 https://trac.libssh2.org/ticket/293 Alexander Lamaison (15 Mar 2015) - [Will Cosgrove brought this change] Must init HMAC_CTX before using it. Must init ctx before using it or openssl will reuse the hmac which is not thread safe and causes a crash. Added libssh2_hmac_ctx_init macro. - Add continuous integration configurations. Linux-based CI is done by Travis CI. Windows-based CI is done by Appveyor. - [David Calavera brought this change] Allow authentication keys to be passed in memory. All credits go to Joe Turpin, I'm just reaplying and cleaning his patch: http://www.libssh2.org/mail/libssh2-devel-archive-2012-01/0015.shtml * Use an unimplemented error for extracting keys from memory with libgcrypt. Daniel Stenberg (14 Mar 2015) - docs: include the renamed INSTALL* files in dist Alexander Lamaison (13 Mar 2015) - Prevent collisions between CMake and Autotools in examples/ and tests/. - Avoid clash between CMake build and Autotools. Autotools expects a configuration template file at src/libssh2_config.h.in, which buildconf generates. But the CMake build system has its CMake-specific version of the file at this path. This means that, if you don't run buildconf, the Autotools build will fail because it configured the wrong header template. See https://github.com/libssh2/libssh2/pull/8. - Merge pull request #8 from alamaison/cmake CMake build system. - CMake build system. Tested: - Windows: - Visual C++ 2005/2008/2010/2012/2013/MinGW-w64 - static/shared - 32/64-bit - OpenSSL/WinCNG - Without zlib - Linux: - GCC 4.6.3/Clang 3.4 - static/shared - 32/64-bit - OpenSSL/Libgcrypt - With/Without zlib - MacOS X - AppleClang 6.0.0 - static - 64-bit - OpenSSL - Without zlib Conflicts: README - Man man syntax tests fail gracefully if man version is not suitable. - Return valid code from test fixture on failure. The sshd test fixture was returning -1 if an error occurred, but negative error codes aren't technically valid (google it). Bash on Windows converted them to 0 which made setup failure look as though all tests were passing. - Let mansyntax.sh work regardless of where it is called from. Daniel Stenberg (12 Mar 2015) - [Viktor Szakáts brought this change] mingw build: allow to pass custom CFLAGS Allow to pass custom `CFLAGS` options via environment variable `LIBSSH2_CFLAG_EXTRAS`. Default and automatically added options of `GNUmakefile` have preference over custom ones. This addition is useful for passing f.e. custom CPU tuning or LTO optimization (`-flto -ffat-lto-objects`) options. The only current way to do this is to edit `GNUmakefile`. This patch makes it unnecessary. This is a mirror of similar libcurl patch: https://github.com/bagder/curl/pull/136 - [Will Cosgrove brought this change] userauth: Fixed prompt text no longer being copied to the prompts struct Regression from 031566f9c - README: update the git repo locations - wait_socket: wrong use of difftime() With reversed arguments it would always return a negative value... Bug: https://github.com/bagder/libssh2/issues/1 - bump: start working toward 1.5.1 now Version 1.5.0 (11 Mar 2015) Daniel Stenberg (11 Mar 2015) - RELEASE-NOTES: 1.5.0 release - [Mariusz Ziulek brought this change] kex: bail out on rubbish in the incoming packet CVE-2015-1782 Bug: http://www.libssh2.org/adv_20150311.html - docs: move INSTALL, AUTHORS, HACKING and TODO to docs/ And with this, cleanup README to be shorter and mention the new source code home. - .gitignore: don't ignore INSTALL Dan Fandrich (4 Mar 2015) - examples/x11.c: include sys/select.h for improved portability Daniel Stenberg (4 Mar 2015) - RELEASE-NOTES: synced with a8473c819bc068 In preparation for the upcoming 1.5.0 release. Guenter Knauf (8 Jan 2015) - NetWare build: added some missing exports. Marc Hoersken (29 Dec 2014) - knownhost.c: fix use of uninitialized argument variable wrote Detected by clang scan in line 1195, column 18. - examples/x11.c: fix result of operation is garbage or undefined Fix use of uninitialized structure w_size_bck. Detected by clang scan in line 386, column 28. - examples/x11.c: remove dead assigments of some return values Detected by clang scan in line 212, column 9. Detected by clang scan in line 222, column 13. Detected by clang scan in line 410, column 13. - examples/x11.c: fix possible memory leak if read fails Detected by clang scan in line 224, column 21. - examples/x11.c: fix invalid removal of first list element Fix use of memory after it was being freed. Detected by clang scan in line 56, column 12. - userauth.c: make sure that sp_len is positive and avoid overflows ... if the pointer subtraction of sp1 - pubkey - 1 resulted in a negative or larger value than pubkey_len, memchr would fail. Reported by Coverity CID 89846. - channel.c: remove logically dead code, host cannot be NULL here ... host cannot be NULL in line 525, because it is always valid (e.g. at least set to "0.0.0.0") after lines 430 and 431. Reported by Coverity CID 89807. - session.c: check return value of session_nonblock during startup Reported by Coverity CID 89803. - session.c: check return value of session_nonblock in debug mode Reported by Coverity CID 89805. - pem.c: fix mixed line-endings introduced with 8670f5da24 - pem.c: make sure there's a trailing zero and b64data is not NULL ... if there is no base64 data between PEM header and footer. Reported by Coverity CID 89823. - kex.c: make sure mlist is not set to NULL ... if the currently unsupported LANG methods are called. Reported by Coverity CID 89834. - packet.c: i < 256 was always true and i would overflow to 0 Visualize that the 0-termination is intentional, because the array is later passed to strlen within _libssh2_packet_askv. - silence multiple data conversion warnings Daniel Stenberg (23 Dec 2014) - agent_connect_unix: make sure there's a trailing zero ... if the path name was too long. Reported by Coverity CID 89801. Marc Hoersken (22 Dec 2014) - examples on Windows: use native SOCKET-type instead of int And check return values accordingly. - userauth.c: improve readability and clarity of for-loops Daniel Stenberg (22 Dec 2014) - calloc: introduce LIBSSH2_CALLOC() A simple function using LIBSSH2_ALLOC + memset, since this pattern was used in multiple places and this simplies code in general. Marc Hoersken (15 Dec 2014) - libssh2_priv.h: Ignore session, context and format parameters - x11 example: check return value of socket function - examples: fixed mixed line-endings introduced with aedfba25b8 - wincng.c: explicitly ignore BCrypt*AlgorithmProvider return codes Fixes VS2012 code analysis warning C6031: return value ignored: could return unexpected value - wincng.c: fix possible invalid memory write access Fixes VS2012 code analysis warning C6386: buffer overrun: accessing 'pbOutput', the writable size is 'cbOutput' bytes, but '3' bytes may be written: libssh2 wincng.c 610 - tests on Windows: check for WSAStartup return code Fixes VS2012 code analysis warning C6031: return value ignored: could return unexpected value - wincng.c: fix possible NULL pointer de-reference of bignum Fixes VS2012 code analysis warning C6011: dereferencing NULL pointer 'bignum'. libssh2 wincng.c 1567 - wincng.c: fix possible use of uninitialized memory Fixes VS2012 code analysis warning C6001: using uninitialized memory 'cbDecoded'. libssh2 wincng.c 553 - packet.c: fix possible NULL pointer de-reference within listen_state Fixes VS2012 code analysis warning C6011: dereferencing NULL pointer 'listen_state->channel'. libssh2 packet.c 221 - kex.c: fix possible NULL pointer de-reference with session->kex Fixes VS2012 code analysis warning C6011: dereferencing NULL pointer 'session->kex'. libssh2 kex.c 1761 - agent.c: check return code of MapViewOfFile Fixes VS2012 code analysis warning C6387: 'p+4' may be '0': this does not adhere to the specification for the function 'memcpy': libssh2 agent.c 330 Fixes VS2012 code analysis warning C6387: 'p' may be '0': this does not adhere to the specification for the function 'UnmapViewOfFile': libssh2 agent.c 333 - examples on Windows: check for socket return code Fixes VS2012 code analysis warning C28193: The variable holds a value that must be examined - examples on Windows: check for WSAStartup return code Fixes VS2012 code analysis warning C6031: return value ignored: could return unexpected value Guenter Knauf (11 Dec 2014) - wincng.c: silent some more gcc compiler warnings. - wincng.c: silent gcc compiler warnings. - Watcom build: added support for WinCNG build. - build: updated dependencies in makefiles. Daniel Stenberg (4 Dec 2014) - configure: change LIBS not LDFLAGS when checking for libs Closes #289 Patch-by: maurerpe Guenter Knauf (3 Dec 2014) - MinGW build: some more GNUMakefile tweaks. test/GNUmakefile: added architecture autodetection; added switches to CFLAGS and RCFLAGS to make sure that the right architecture is used. Added support to build with WinCNG. - sftpdir.c: added authentication method detection. Stuff copied over from ssh2.c to make testing a bit easier. - NMake build: fixed LIBS settings. - NMake build: added support for WinCNG build. - MinGW build: some GNUMakefile tweaks. Added architecture autodetection; added switches to CFLAGS and RCFLAGS to make sure that the right architecture is used. Added support to build with WinCNG. - MinGW build: Fixed redefine warnings. - Updated copyright year. Daniel Stenberg (31 Aug 2014) - COPYING: bump the copyright year Dan Fandrich (28 Jul 2014) - docs: fixed a bunch of typos - docs: added missing libssh2_session_handshake.3 file Marc Hoersken (19 May 2014) - wincng.c: specify the required libraries for dependencies using MSVC Initially reported by Bob Kast as "for MS VS builds, specify the libraries that are required so they don't need to go into all project files that may use this library". Thanks a lot. - [Bob Kast brought this change] windows build: do not export externals from static library If you are building a DLL, then you need to explicitly export each entry point. When building a static library, you should not. libssh2 was exporting the entry points whether it was building a DLL or a static library. To elaborate further, if libssh2 was used as a static library, which was being linked into a DLL, the libssh2 API would be exported from that separate DLL. Daniel Stenberg (19 May 2014) - [Mikhail Gusarov brought this change] Fix typos in manpages Marc Hoersken (18 May 2014) - wincng.c: Fixed memory leak in case of an error during ASN.1 decoding - configure: Display individual crypto backends on separate lines This avoids line-wrapping in between parameters and makes the error message look like the following: configure: error: No crypto library found! Try --with-libssl-prefix=PATH or --with-libgcrypt-prefix=PATH or --with-wincng on Windows - [Bob Kast brought this change] libssh2_priv.h: a 1 bit bit-field should be unsigned some compilers may not like this - knownhost.c: Fixed warning that pointer targets differ in signedness - wincng.c: Fixed warning about pointer targets differing in signedness - tcpip-forward.c: Fixed warning that pointer targets differ in signedness libssh2_channel_forward_listen_ex uses ints instead of unsigned ints. - misc.c: Fixed warning about mixed declarations and code - libgcrypt.h: Fixed warning about pointer targets differing in signedness - wincng.h: Fixed warning about pointer targets differing in signedness - misc.c: Fixed warning about unused parameter abstract - tcpip-forward.c: Removed unused variables shost, sport and sockopt - wincng.h: Added forward declarations for all WinCNG functions Initially reported by Bob Kast as "Wincng - define function prototypes for wincng routines". Thanks a lot. Also replaced structure definitions with type definitions. - [Bob Kast brought this change] libssh2.h: on Windows, a socket is of type SOCKET, not int - win32: Added WinCNG targets to generated Visual Studio project Inspired by Bob Kast's reports, this commit enables the compilation of libssh2 with WinCNG using the generated Visual Studio project files. This commit adds WinCNG support to parts of the existing Win32 build infrastructure, until new build systems, like pre-defined VS project files or CMake files may be added. This commit and b20bfeb3e519119a48509a1099c06d65aa7da1d7 raise one question: How to handle build systems, like VS project files, that need to include all source files regardless of the desired target, including all supported crypto backends? For now the mentioned commit added a check for LIBSSH2_OPENSSL to openssl.c and with this commit the supported crypto backends are hardcoded within Makefile.am. - libssh2_priv msvc: Removed redundant definition of inline keyword Initially reported by Bob Kast as "Remove redundant 'inline' define". Thanks a lot. - wincng: Made data parameter to hash update function constant Initially reported by Bob Kast as "formal parameter must be const since it is used in contexts where the actual parameter may be const". Thanks a lot. - wincng: fix cross-compilation against the w64 mingw-runtime package - openssl: Check for LIBSSH2_OPENSSL in order to compile with openssl - wincng: Fixed use of possible uninitialized variable pPaddingInfo Reported by Bob Kast, thanks a lot. - wincng: Added cast for double to unsigned long conversion - wincng: Cleaned up includes and check NTSTATUS using macro Removed header file combination that is not supported on a real Windows platform and can only be compiled using MinGW. Replaced custom NTSTATUS return code checks with BCRYPT_SUCCESS macro. Daniel Stenberg (16 Mar 2014) - userauth_hostbased_fromfile: zero assign to avoid uninitialized use Detected by clang-analyze - channel_receive_window_adjust: store windows size always Avoid it sometimes returning without storing it, leaving calling functions with unknown content! Detected by clang-analyzer - publickey_packet_receive: avoid junk in returned pointers clang-analyzer found this risk it would return a non-initialized pointer in a success case Peter Stuge (16 Mar 2014) - [Marc Hoersken brought this change] Added Windows Cryptography API: Next Generation based backend - [Marc Hoersken brought this change] knownhost.c: fixed that 'key_type_len' may be used uninitialized ../src/knownhost.c: In function 'libssh2_knownhost_readline': ../src/knownhost.c:651:16: warning: 'key_type_len' may be used uninitialized in this function [-Wmaybe-uninitialized] rc = knownhost_add(hosts, hostbuf, NULL, ^ ../src/knownhost.c:745:12: note: 'key_type_len' was declared here size_t key_type_len; ^ - [Marc Hoersken brought this change] pem.c: always compile pem.c independently of crypto backend - Fix non-autotools builds: Always define the LIBSSH2_OPENSSL CPP macro Commit d512b25f69a1b6778881f6b4b5ff9cfc6023be42 introduced a crypto library abstraction in the autotools build system, to allow us to more easily support new crypto libraries. In that process it was found that all other build system which we support are hard-coded to build with OpenSSL. Commit f5c1a0d98bd51aeb24aca3d49c7c81dcf8bd858d fixes automake introduced into non-autotools build systems but still overlooked the CPP macro saying that we are using OpenSSL. Thanks to Marc Hörsken for identifying this issue and proposing a fix for win32/{GNUmakefile,config.mk}. This commit uses a slightly different approach but the end result is the same. Dan Fandrich (15 Mar 2014) - channel_close: Close the channel even in the case of errors - sftp_close_handle: ensure the handle is always closed Errors are reported on return, but otherwise the close path is completed as much as possible and the handle is freed on exit. Alexander Lamaison (6 Mar 2014) - knownhost: Restore behaviour of `libssh2_knownhost_writeline` with short buffer. Commit 85c6627c changed the behaviour of `libssh2_knownhost_writeline` so that it stopped returning the number of bytes needed when the given buffer was too small. Also, the function changed such that is might write to part of the buffer before realising it is too small. This commit restores the original behaviour, whilst keeping the unknown-key-type functionality that 85c6627c. Instead of writing to the buffer piecemeal, the length of the various parts is calculated up front and the buffer written only if there is enough space. The calculated necessary size is output in `outlen` regardless of whether the buffer was written to. The main use-case for the original behaviour that this commit restores is to allow passing in a NULL buffer to get the actual buffer size needed, before calling the function again with the buffer allocated to the exact size required. - knownhost: Fix DSS keys being detected as unknown. I missing `else` meant ssh-dss format keys were being re-detected as unknown format. Dan Fandrich (6 Mar 2014) - knownhosts: Abort if the hosts buffer is too small This could otherwise cause a match on the wrong host - agent_list_identities: Fixed memory leak on OOM - Fixed a few typos - userauth: Fixed an attempt to free from stack on error - Fixed a few memory leaks in error paths - Fixed two potential use-after-frees of the payload buffer The first might occur if _libssh2_packet_add returns an error, as fullpacket_state wasn't reset to idle so if it were possible for fullpacket to be called again, it would return to the same state handler and re-use the freed p->packet buffer. The second could occur if decrypt returned an error, as it freed the packet buffer but did not clear total_num, meaning that freed buffer could be written into again later. Alexander Lamaison (28 Nov 2013) - Fix missing `_libssh2_error` in `_libssh2_channel_write`. In one case, the error code from `_libssh2_transport_read` was being returned from `_libssh2_channel_write` without setting it as the last error by calling `_libssh2_error`. This commit fixes that. Found when using a session whose socket had been inadvertently destroyed. The calling code got confused because via `libssh2_session_last_error` it appeared no error had occurred, despite one being returned from the previous function. Kamil Dudka (21 Nov 2013) - [Mark McPherson brought this change] openssl: initialise the digest context before calling EVP_DigestInit() When using the OpenSSL libraries in FIPS mode, the function call EVP_DigestInit() is actually #defined to FIPS_digestinit(). Unfortunately wheres EVP_DigestInit() initialises the context and then calls EVP_DigestInit_ex(), this function assumes that the context has been pre-initialised and crashes when it isn't. Bug: https://trac.libssh2.org/ticket/279 Fixes #279 - [Marc Hörsken brought this change] .gitignore: Ignore files like src/libssh2_config.h.in~ Peter Stuge (13 Nov 2013) - Move automake conditionals added by commit d512b25f out of Makefile.inc Commit d512b25f69a1b6778881f6b4b5ff9cfc6023be42 added automake conditionals to Makefile.inc but since Makefile.inc is included from Makefile for all other build systems that does not work. This commit instead adds Makefile.OpenSSL.inc and Makefile.libgcrypt.inc and moves the automake conditional to its proper place, src/Makefile.am. The automake conditional includes the correct Makefile.$name.inc per the crypto library selection/detection done by configure. All non-autotools build system files in libssh2 are hardcoded to use OpenSSL and do not get a conditional but at least there is some reuse because they can all include the new Makefile.OpenSSL.inc. Daniel Stenberg (27 Oct 2013) - [Salvador Fandino brought this change] Set default window size to 2MB The default channel window size used until now was 256KB. This value is too small and results on a bottleneck on real-life networks where round-trip delays can easily reach 300ms. The issue was not visible because the configured channel window size was being ignored and a hard-coded value of ~22MB being used instead, but that was fixed on a previous commit. This patch just changes the default window size (LIBSSH2_CHANNEL_WINDOW_DEFAULT) to 2MB. It is the same value used by OpenSSH and in our opinion represents a good compromise between memory used and transfer speed. Performance tests were run to determine the optimum value. The details and related discussion are available from the following thread on the libssh2 mailing-list: http://www.libssh2.org/mail/libssh2-devel-archive-2013-10/0018.shtml http://article.gmane.org/gmane.network.ssh.libssh2.devel/6543 An excerpt follows: "I have been running some transfer test and measuring their speed. My setup was composed of a quad-core Linux machine running Ubuntu 13.10 x86_64 with a LXC container inside. The data transfers were performed from the container to the host (never crossing through a physical network device). Network delays were simulated using the tc tool. And ping was used to verify that they worked as intended during the tests. The operation performed was the equivalent to the following ssh command: $ ssh container "dd bs=16K count=8K if=/dev/zero" >/dev/null Though, establishment and closing of the SSH connection was excluded from the timings. I run the tests several times transferring files of sizes up to 128MB and the results were consistent between runs. The results corresponding to the 128MB transfer are available here: https://docs.google.com/spreadsheet/ccc?key=0Ao1yRmX6PQQzdG5wSFlrZl9HRWNET3ZyN0hnaGo5ZFE&usp=sharing It clearly shows that 256KB is too small as the default window size. Moving to a 512MB generates a great improvement and after the 1MB mark the returns rapidly diminish. Other factors (TCP window size, probably) become more limiting than the channel window size For comparison I also performed the same transfers using OpenSSH. Its speed is usually on par with that of libssh2 using a window size of 1MB (even if it uses a 2MB window, maybe it is less aggressive sending the window adjust msgs)." Signed-off-by: Salvador Fandino - [Salvador brought this change] _libssh2_channel_read: Honour window_size_initial _libssh2_channel_read was using an arbitrary hard-coded limit to trigger the window adjusting code. The adjustment used was also hard-coded and arbitrary, 15MB actually, which would limit the usability of libssh2 on systems with little RAM. This patch, uses the window_size parameter passed to libssh2_channel_open_ex (stored as remote.window_size_initial) plus the buflen as the base for the trigger and the adjustment calculation. The memory usage when using the default window size is reduced from 22MB to 256KB per channel (actually, if compression is used, these numbers should be incremented by ~50% to account for the errors between the decompressed packet sizes and the predicted sizes). My tests indicate that this change does not impact the performance of transfers across localhost or a LAN, being it on par with that of OpenSSH. On the other hand, it will probably slow down transfers on networks with high bandwidth*delay when the default window size (LIBSSH2_CHANNEL_WINDOW_DEFAULT=256KB) is used. Signed-off-by: Salvador Fandino - [Salvador Fandino brought this change] knownhosts: handle unknown key types Store but don't use keys of unsupported types on the known_hosts file. Currently, when libssh2 parses a known_host file containing keys of some type it doesn't natively support, it stops reading the file and returns an error. That means, that the known_host file can not be safely shared with other software supporting other key types (i.e. OpenSSH). This patch adds support for handling keys of unknown type. It can read and write them, even if they are never going to be matched. At the source level the patch does the following things: - add a new unknown key type LIBSSH2_KNOWNHOST_KEY_UNKNOWN - add a new slot (key_type_name) on the known_host struct that is used to store the key type in ascii form when it is not supported - parse correctly known_hosts entries with unknown key types and populate the key_type_name slot - print correctly known_hosts entries of unknown type - when checking a host key ignore keys that do not match the key Fixes #276 - windows build: fix build errors Fixes various link errors with VS2010 Reported-by: "kdekker" Fixes #272 - man page: add missing function argument for libssh2_userauth_publickey_fromfile_ex() Reported-by: "pastey" Fixes #262 - [Salvador brought this change] Fix zlib deflate usage Deflate may return Z_OK even when not all data has been compressed if the output buffer becomes full. In practice this is very unlikely to happen because the output buffer size is always some KBs larger than the size of the data passed for compression from the upper layers and I think that zlib never expands the data so much, even on the worst cases. Anyway, this patch plays on the safe side checking that the output buffer is not exhausted. Signed-off-by: Salvador - [Salvador brought this change] comp_method_zlib_decomp: Improve buffer growing algorithm The old algorithm was O(N^2), causing lots and lots of reallocations when highly compressed data was transferred. This patch implements a simpler one that just doubles the buffer size everytime it is exhausted. It results in O(N) complexity. Also a smaller inflate ratio is used to calculate the initial size (x4). Signed-off-by: Salvador - [Salvador brought this change] Fix zlib usage Data may remain in zlib internal buffers when inflate() returns Z_OK and avail_out == 0. In that case, inflate has to be called again. Also, once all the data has been inflated, it returns Z_BUF_ERROR to signal that the input buffer has been exhausted. Until now, the way to detect that a packet payload had been completely decompressed was to check that no data remained on the input buffer but that didn't account for the case where data remained on the internal zlib buffers. That resulted in packets not being completely decompressed and the missing data reappearing on the next packet, though the bug was masked by the buffer allocation algorithm most of the time and only manifested when transferring highly compressible data. This patch fixes the zlib usage. Signed-off-by: Salvador - [Salvador brought this change] _libssh2_channel_read: fix data drop when out of window After filling the read buffer with data from the read queue, when the window size was too small, "libssh2_channel_receive_window_adjust" was called to increase it. In non-blocking mode that function could return EAGAIN and, in that case, the EAGAIN was propagated upwards and the data already read on the buffer lost. The function was also moving between the two read states "libssh2_NB_state_idle" and "libssh2_NB_state_created" both of which behave in the same way (excepting a debug statment). This commit modifies "_libssh2_channel_read" so that the "libssh2_channel_receive_window_adjust" call is performed first (when required) and if everything goes well, then it reads the data from the queued packets into the read buffer. It also removes the useless "libssh2_NB_state_created" read state. Some rotted comments have also been updated. Signed-off-by: Salvador - [Salvador Fandino brought this change] window_size: redid window handling for flow control reasons Until now, the window size (channel->remote.window_size) was being updated just after receiving the packet from the transport layer. That behaviour is wrong because the channel queue may grow uncontrolled when data arrives from the network faster that the upper layer consumes it. This patch adds a new counter, read_avail, which keeps a count of the bytes available from the packet queue for reading. Also, now the window size is adjusted when the data is actually read by an upper layer. That way, if the upper layer stops reading data, the window will eventually fill and the remote host will stop sending data. When the upper layers reads enough data, a window adjust packet is delivered and the transfer resumes. The read_avail counter is used to detect the situation when the remote server tries to send data surpassing the window size. In that case, the extra data is discarded. Signed-off-by: Salvador Peter Stuge (15 Sep 2013) - configure.ac: Call zlib zlib and not libz in text but keep option names - configure.ac: Reorder --with-* options in --help output - configure.ac: Rework crypto library detection This further simplifies adding new crypto libraries. - Clean up crypto library abstraction in build system and source code libssh2 used to explicitly check for libgcrypt and default to OpenSSL. Now all possible crypto libraries are checked for explicitly, making the addition of further crypto libraries both simpler and cleaner. - configure.ac: Add zlib to Requires.private in libssh2.pc if using zlib - Revert "Added Windows Cryptography API: Next Generation based backend" This reverts commit d385230e15715e67796f16f3e65fd899f21a638b. Daniel Stenberg (7 Sep 2013) - [Leif Salomonsson brought this change] sftp_statvfs: fix for servers not supporting statfvs extension Fixes issue arising when server does not support statfvs and or fstatvfs extensions. sftp_statvfs() and sftp_fstatvfs() after this patch will handle the case when SSH_FXP_STATUS is returned from server. - [Marc Hoersken brought this change] Added Windows Cryptography API: Next Generation based backend - [Kamil Dudka brought this change] partially revert "window_size: explicit adjustments only" This partially reverts commit 03ca9020756a4e16f0294e5b35e9826ee6af2364 in order to fix extreme slowdown when uploading to localhost via SFTP. I was able to repeat the issue on RHEL-7 on localhost only. It did not occur when uploading via network and it did not occur on a RHEL-6 box with the same version of libssh2. The problem was that sftp_read() used a read-ahead logic to figure out the window_size, but sftp_packet_read() called indirectly from sftp_write() did not use any read-ahead logic. - _libssh2_channel_write: client spins on write when window full When there's no window to "write to", there's no point in waiting for the socket to become writable since it most likely just will continue to be. Patch-by: ncm Fixes #258 - _libssh2_channel_forward_cancel: avoid memory leaks on error Fixes #257 - _libssh2_packet_add: avoid using uninitialized memory In _libssh2_packet_add, called by _libssh2_packet_read, a call to _libssh2_packet_send that is supposed to send a one-byte message SSH_MSG_REQUEST_FAILURE would send an uninitialized byte upon re-entry if its call to _send returns _EAGAIN. Fixes #259 - _libssh2_channel_forward_cancel: accessed struct after free ... and the assignment was pointless anyway since the struct was about to be freed. Bug introduced in dde2b094. Fixes #268 Peter Stuge (2 Jun 2013) - [Marc Hoersken brought this change] Fixed compilation using mingw-w64 - [Marc Hoersken brought this change] knownhost.c: use LIBSSH2_FREE macro instead of free Use LIBSSH2_FREE instead of free since _libssh2_base64_encode uses LIBSSH2_ALLOC Daniel Stenberg (18 May 2013) - [Matthias Kerestesch brought this change] libssh2_agent_init: init ->fd to LIBSSH2_INVALID_SOCKET ... previously it was left at 0 which is a valid file descriptor! Bug: https://trac.libssh2.org/ticket/265 Fixes #265 - userauth_password: pass on the underlying error code _libssh2_packet_requirev() may return different errors and we pass that to the parent instead of rewriting it. Bug: http://libssh2.org/mail/libssh2-devel-archive-2013-04/0029.shtml Reported by: Cosmin Peter Stuge (9 May 2013) - [Marc Hoersken brought this change] libcrypt.c: Fix typo in _libssh2_rsa_sha1_sign() parameter type Kamil Dudka (4 May 2013) - configure.ac: replace AM_CONFIG_HEADER with AC_CONFIG_HEADERS Reported by: Quintus Bug: https://trac.libssh2.org/ticket/261 Guenter Knauf (12 Apr 2013) - Fixed copyright string for NetWare build. Daniel Stenberg (9 Apr 2013) - [Richard W.M. Jones brought this change] sftp: Add support for fsync (OpenSSH extension). The new libssh2_sftp_fsync API causes data and metadata in the currently open file to be committed to disk at the server. This is an OpenSSH extension to the SFTP protocol. See: https://bugzilla.mindrot.org/show_bug.cgi?id=1798 - [Richard W.M. Jones brought this change] sftp: statvfs: Along error path, reset the correct 'state' variable. - [Richard W.M. Jones brought this change] sftp: seek: Don't flush buffers on same offset Signed-off-by: Richard W.M. Jones Guenter Knauf (9 Feb 2013) - Updated dependency libs. - Fixed tool macro names. Daniel Stenberg (29 Nov 2012) - [Seth Willits brought this change] compiler warnings: typecast strlen in macros ... in macro parameters to avoid compiler warnings about lost precision. Several macros in libssh2.h call strlen and pass the result directly to unsigned int parameters of other functions, which warns about precision loss because strlen returns size_t which is unsigned long on at least some platforms (such as OS X). The fix is to simply typecast the strlen() result to unsigned int. - libssh2.h: bump version to 1.4.4-DEV Version 1.4.3 (27 Nov 2012) Daniel Stenberg (27 Nov 2012) - RELEASE-NOTES: fixed for 1.4.3 - sftp_read: return error if a too large package arrives Peter Stuge (13 Nov 2012) - Only define _libssh2_dsa_*() functions when building with DSA support Guenter Knauf (8 Nov 2012) - Added .def file to output. Kamil Dudka (1 Nov 2012) - libssh2_hostkey_hash.3: update the description of return value The function returns NULL also if the hash algorithm is not available. Guenter Knauf (24 Oct 2012) - Fixed mode acciedently committed. - Ignore generated file. - Added hack to make use of Makefile.inc. This should avoid further maintainance of the objects list. - Fixed MSVC NMakefile. Added missing source files; added resource for DLL. Kamil Dudka (22 Oct 2012) - examples: use stderr for messages, stdout for data Reported by: Karel Srot Bug: https://bugzilla.redhat.com/867462 - openssl: do not leak memory when handling errors ,.. in aes_ctr_init(). Detected by Coverity. - channel: fix possible NULL dereference ... in libssh2_channel_get_exit_signal(). Detected by Coverity. - Revert "aes: the init function fails when OpenSSL has AES support" This partially reverts commit f4f2298ef3635acd031cc2ee0e71026cdcda5864. We need to use the EVP_aes_???_ctr() functions in FIPS mode. - crypt: use hard-wired cipher block sizes consistently - openssl: do not ignore failure of EVP_CipherInit() - kex: do not ignore failure of libssh2_md5_init() The MD5 algorithm is disabled when running in FIPS mode. Daniel Stenberg (21 Aug 2012) - [Peter Krempa brought this change] known_hosts: Fail when parsing unknown keys in known_hosts file. libssh2_knownhost_readfile() silently ignored problems when reading keys in unsupported formats from the known hosts file. When the file is written again from the internal structures of libssh2 it gets truntcated to the point where the first unknown key was located. * src/knownhost.c:libssh2_knownhost_readfile() - return error if key parsing fails - AUTHORS: synced with 42fec44c8a4 31 recent authors added - [Dave Hayden brought this change] compression: add support for zlib@openssh.com Add a "use_in_auth" flag to the LIBSSH2_COMP_METHOD struct and a separate "zlib@openssh.com" method, along with checking session->state for LIBSSH2_STATE_AUTHENTICATED. Appears to work on the OpenSSH servers I've tried against, and it should work as before with normal zlib compression. - [Dmitry Smirnov brought this change] configure: gcrypt doesn't come with pkg-config support ... so use plain old -lgcrypt to the linker to link with it. Fixes #225 - sftp_read: Value stored to 'next' is never read Detected by clang-analyzer - publickey_init: errors are negative, fix check Detected by clang-analyzer. - [Maxime Larocque brought this change] session_free: wrong variable used for keeping state If libssh2_session_free is called without the channel being freed previously by libssh2_channel_free a memory leak could occur. A mismatch of states variables in session_free() prevent the call to libssh2_channel_free function. session->state member is used instead of session->free_state. It causes a leak of around 600 bytes on every connection on my systems (Linux, x64 and PPC). (Debugging done under contract for Accedian Networks) Fixes #246 Guenter Knauf (29 Jun 2012) - Small NetWare makefile tweak. - Some small Win32 makefile fixes. Daniel Stenberg (19 Jun 2012) - libssh2_userauth_publickey_fromfile_ex.3: mention publickey == NULL - comp_method_zlib_decomp: handle Z_BUF_ERROR when inflating When using libssh2 to perform an SFTP file transfer from the "JSCAPE MFT Server" (http://www.jscape.com) the transfer failed. The default JSCAPE configuration is to enforce zlib compression on SSH2 sessions so the session was compressed. The relevant part of the debug trace contained: [libssh2] 1.052750 Transport: unhandled zlib error -5 [libssh2] 1.052750 Failure Event: -29 - decompression failure The trace comes from comp_method_zlib_decomp() in comp.c. The "unhandled zlib error -5" is the status returned from the zlib function inflate(). The -5 status corresponds to "Z_BUF_ERROR". The inflate() function takes a pointer to a z_stream structure and "inflates" (decompresses) as much as it can. The relevant fields of the z_stream structure are: next_in - pointer to the input buffer containing compressed data avail_in - the number of bytes available at next_in next_out - pointer to the output buffer to be filled with uncompressed data avail_out - how much space available at next_out To decompress data you set up a z_stream struct with the relevant fields filled in and pass it to inflate(). On return the fields will have been updated so next_in and avail_in show how much compressed data is yet to be processed and next_out and avail_out show how much space is left in the output buffer. If the supplied output buffer is too small then on return there will be compressed data yet to be processed (avail_in != 0) and inflate() will return Z_OK. In this case the output buffer must be grown, avail_out updated and inflate() called again. If the supplied output buffer was big enough then on return the compressed data will have been exhausted (avail_in == 0) and inflate() will return Z_OK, so the data has all been uncompressed. There is a corner case where inflate() makes no progress. That is, there may be unprocessed compressed data and space available in the output buffer and yet the function does nothing. In this case inflate() will return Z_BUF_ERROR. From the zlib documentation and the source code it is not clear under what circumstances this happens. It could be that it needs to write multiple bytes (all in one go) from its internal state to the output buffer before processing the next chunk of input but but can't because there is not enough space (though my guesses as to the cause are not really relevant). Recovery from Z_BUF_ERROR is pretty simple - just grow the output buffer, update avail_out and call inflate() again. The comp_method_zlib_decomp() function does not handle the case when inflate() returns Z_BUF_ERROR. It treats it as a non-recoverable error and basically aborts the session. Fixes #240 Guenter Knauf (12 Jun 2012) - MinGW makefile tweaks. Use GNU tools when compiling on Linux. Fixed dist and dev targets. - NetWare makefile tweaks. Changed to use Windows commandline tools instead of GNU tools when compiling on Windows. Fixed dist and dev targets. Enabled nlmconv error for unresolved symbols. Daniel Stenberg (11 Jun 2012) - Revert "config.rpath: generated file, no need to keep in git" This reverts commit 1ac7bd09cc685755577fb2c8829adcd081e7ab3c. This file still used by lib/*m4 functions so we need to keep the file around. - BINDINGS: added PySsh2, a Python-ctypes binding Guenter Knauf (8 Jun 2012) - Fixed MinGW debug build. Daniel Stenberg (5 Jun 2012) - BINDINGS: Added the Cocoa/Objective-C one ... and sorted the bindings after the languages, alphabetically Reported by: Mike Abdullah - BINDINGS: document the bindings we know of Guenter Knauf (4 Jun 2012) - Fixed LIBSSH2_INT64_T_FORMAT macro. Usually a format macro should hold the whole format, otherwise it should be named a prefix. Also fixed usage of this macro in scp.c for a signed var where it was used as prefix for unsigned. - Removed obsolete define from makefiles. - Renamed NetWare makefiles. - Renamed NetWare makefiles. - Synced MinGW makefiles with 56c64a6..39e438f. Also synced MinGW test makefile with b092696..f8cb874. Peter Stuge (30 May 2012) - Revert "sftp: Don't send attrs.permissions on read-only SSH_FXP_OPEN" This reverts commit 04e79e0c798674a0796be8a55f63dd92e6877790. - sftp: Don't send attrs.permissions on read-only SSH_FXP_OPEN This works around a protocol violation in the ProFTPD 1.3.4 mod_sftp server, as reported by Will Cosgrove in: http://libssh2.org/mail/libssh2-devel-archive-2012-05/0079.shtml Based on a suggested fix by TJ Saunders in: http://libssh2.org/mail/libssh2-devel-archive-2012-05/0104.shtml Guenter Knauf (28 May 2012) - Try to detect OpenSSL build type automatically. Also fixed recently added libgdi32 linkage which is only required when OpenSSL libs are linked statically. Daniel Stenberg (25 May 2012) - config.rpath: generated file, no need to keep in git Guenter Knauf (22 May 2012) - Updated dependency libary versions. Daniel Stenberg (18 May 2012) - 1.4.3: towards the future Version 1.4.2 (18 May 2012) Daniel Stenberg (18 May 2012) - RELEASE-NOTES: synced with 92a9f952794 Alexander Lamaison (15 May 2012) - win32/libssh2_config.h: Remove hardcoded #define LIBSSH2_HAVE_ZLIB. Rationale: Everything else in this file states a fact about the win32 platform that is unconditional for that platform. There is nothing unconditional about the presence of zlib. It is neither included with Windows nor with the platform SDK. Therefore, this is not an appropriate place to assert its presence. Especially as, once asserted, it cannot be overridden using a compiler flag. In contrast, if it is omitted, then it can easily be reasserted by adding a compiler flag defining LIBSSH2_HAVE_ZLIB. Daniel Stenberg (14 May 2012) - RELEASE-NOTES: synced with 69a3354467c - _libssh2_packet_add: SSH_MSG_CHANNEL_REQUEST default to want_reply RFC4254 says the default 'want_reply' is TRUE but the code defaulted to FALSE. Now changed. Fixes #233 - gettimeofday: no need for a replacement under cygwin Fixes #224 Alexander Lamaison (13 May 2012) - Prevent sftp_packet_read accessing freed memory. sftp_packet_add takes ownership of the packet passed to it and (now that we handle zombies) might free the packet. sftp_packet_read uses the packet type byte as its return code but by this point sftp_packet_add might have freed it. This change fixes the problem by caching the packet type before calling sftp_packet_add. I don't understand why sftp_packet_read uses the packet type as its return code. A future change might get rid of this entirely. Daniel Stenberg (12 May 2012) - sftp_packet_flush: flush zombies too As this function is called when the SFTP session is closed, it needs to also kill all zombies left in the SFTP session to avoid leaking memory just in case some zombie would still be in there. - sftp_packetlist_flush: zombies must not have responses already When flushing the packetlist, we must only add the request as a zombie if no response has already been received. Otherwise we could wrongly make it a zombie even though the response was already received and then we'd get a zombie stuck there "forever"... - sftp_read: on EOF remove packet before flush Since the sftp_packetlist_flush() function will move all the existing FXP_READ requests in this handle to the zombie list we must first remove this just received packet as it is clearly not a zombie. - sftp_packet_require: sftp_packet_read() returning 0 is not an error Exactly as the comment in the code said, checking the return code from sftp_packet_read() with <= was wrong and it should be < 0. With the new filtering on incoming packets that are "zombies" we can now see this getting zero returned. - sftp_packetlist_flush: only make it zombie if it was sent The list of outgoing packets may also contain packets that never were sent off and we better not make them zombies too. - [Alexander Lamaison brought this change] Mark outstanding read requests after EOF as zombies. In order to be fast, sftp_read sends many read requests at once. With a small file, this can mean that when EOF is received back, many of these requests are still outstanding. Responses arriving after we close the file and abandon the file handle are queued in the SFTP packet queue and never collected. This causes transfer speed to drop as a progressively longer queue must be searched for every packet. This change introduces a zombie request-ID list in the SFTP session that is used to recognise these outstanding requests and prevent them being added to the queue. Peter Stuge (23 Apr 2012) - [Rafael Kitover brought this change] Update win32/GNUmakefile to use OpenSSL 1.0.1a libcrypto on win32 now depends on gdi32.dll, so move the OpenSSL LDLIBS block to before the compiler definitions, so that libcrypto gets added first, and then add -lgdi32 into the following common LDLIBS for gcc. Guenter Knauf (23 Apr 2012) - Changed 'Requires' to 'Requires.private'. Only static builds need to link against the crypto libs. - Fixed 'Requires:' names. The 'Requires:' line lists the names of the .pc files. - Added 'Requires:' line to libssh2.pc. This is necessary so that other libs which lookup libssh2 info via pkg-config can add the right crypto lib dependencies. - Updated dependency lib versions. Peter Stuge (18 Apr 2012) - configure.ac: Add option to disable build of the example applications Examples are built by default. Any of the following options on the configure command line will skip building them: --disable-examples-build --enable-examples-build=no --enable-examples-build=false - userauth.c: fread() from public key file to correctly detect any errors If the filename parameter for file_read_publickey() was the name of a directory instead of a file then libssh2 would spin trying to fgetc() from the FILE * for the opened directory when trying to determine the length of the encoded public key, since fgetc() can't report errors. Use fread() instead to correctly detect this error condition along with many others. This fixes the problem reported in http://www.libssh2.org/mail/libssh2-devel-archive-2012-04/0021.shtml Reported-by: Oleksiy Zagorskyi - Return LIBSSH2_ERROR_SOCKET_DISCONNECT on EOF when reading banner Guenter Knauf (17 Apr 2012) - Fixed copyright year. - Updated dependency lib versions in static makefiles. Daniel Stenberg (6 Apr 2012) - version: bump to 1.4.2 We're on the 1.4.2 track now (at least) Version 1.4.1 (4 Apr 2012) Daniel Stenberg (4 Apr 2012) - RELEASE-NOTES: updated for 1.4.1 release - always do "forced" window updates When calling _libssh2_channel_receive_window_adjust() internally, we now always use the 'force' option to prevent libssh2 to avoid sending the update if the update isn't big enough. It isn't fully analyzed but we have seen corner cases which made a necessary window update not get send due to this and then the other side doesn't send data our side then sits waiting for forever. - channel_read: force window adjusts! if there's not enough room to receive the data that's being requested, the window adjustment needs to be sent to the remote and thus the force option has to be used. _libssh2_channel_receive_window_adjust() would otherwise "queue" small window adjustments for a later packet but that is really terribly for the small buffer read that for example is the final little piece of a very large file as then there is no logical next packet! Reported by: Armen Babakhanian Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2012-03/0130.shtml - [Paul Howarth brought this change] aes: the init function fails when OpenSSL has AES support The internal init function only worked fine when the configure script didn't detect the OpenSSL AES_CTR function! Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2012-03/0111.shtml Reported by: Paul Howarth - [Matthew Booth brought this change] transport_send: Finish in-progress key exchange before sending data _libssh2_channel_write() first reads outstanding packets before writing new data. If it reads a key exchange request, it will immediately start key re-exchange, which will require sending a response. If the output socket is full, this will result in a return from _libssh2_transport_read() of LIBSSH2_ERROR_EAGAIN. In order not to block a write because there is no data to read, this error is explicitly ignored and the code continues marshalling a packet for sending. When it is sent, the remote end immediately drops the connection because it was expecting a continuation of the key exchange, but got a data packet. This change adds the same check for key exchange to _libssh2_transport_send() that is in _libssh2_transport_read(). This ensures that key exchange is completed before any data packet is sent. - channel_write: acknowledge transport errors When draining data off the socket with _libssh2_transport_read() (which in turn has to be done so that we can be sure to have read any possible window-increasing packets), this code previously ignored errors which could lead to nasty loops. Now all error codes except EAGAIN will cause the error to be returned at once. Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2012-03/0068.shtml Reported by: Matthew Booth - [Steven Dake brought this change] In examples/x11.c, Make sure sizeof passed to read operation is correct sizeof(buf) expands to 8 or 4 (since its a pointer). This variable may have been static in the past, leading to this error. Signed-off-by: Steven Dake - [Steven Dake brought this change] Fix suspicious sizeof usage in examples/x11.c In the x11 example, sizeof(buf) = 8UL (on x86_64), when this should probably represent the buffer size available. I am not sure how to test that this change is actually correct, however. Signed-off-by: Steven Dake - sftp_packet_read: follow-up fix for EAGAIN/window adjust The commit in 7194a9bd7ba45 wasn't complete. This change makes sure variables are initialized properly before used in the EAGAIN and window adjust cases. - sftp_packet_add: use named error code instead of number - sftp_packet_add: verify the packet before accepting it In order to bail out as quickly as possible when things are wrong and out of sync, make sure the SFTP message is one we understand. - SFTP: preserve the original error code more Lots of places in the code translated the original error into the more generic LIBSSH2_ERROR_SOCKET_TIMEOUT but this turns out to distort the original error reason a lot and makes tracking down the real origin of a problem really hard. This change makes the original error code be preserved to a larger extent when return up to the parent function. - sftp_packet_read: adjust window size as necessary Commit 03ca9020756 tried to simplify the window sizing logic but broke SFTP readdir as there was no window sizing code left there so large directory listings no longer worked. This change introduces window sizing logic to the sftp_packet_read() function so that it now tells the remote about the local size having a window size that suffice when it is about to ask for directory data. Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2012-03/0069.shtml Reported by: Eric - [Steven Dake brought this change] Tell C compiler we don't care about return code of libssh2_init The call of libssh2_init returns a return code, but nothing could be done within the _libssh2_init_if_needed execution path. Signed-off-by: Steven Dake - [Steven Dake brought this change] Add comment indicating a resource leak is not really a resource leak While possibly obvious to those investigating the code, coverity complains about this out of scope leak. Signed-off-by: Steven Dake - [Steven Dake brought this change] Use safer snprintf rather then sprintf in scp_send() Signed-off-by: Steven Dake - [Steven Dake brought this change] Use safer snprintf rather then sprintf in scp_recv() While the buffer is indeed allocated to a safe length, better safe then sorry. Signed-off-by: Steven Dake - [Steven Dake brought this change] use snprintf in knownhost_writeline() rather then sprintf Although the function checks the length, if the code was in error, there could potentially be a buffer overrun with the use of sprintf. Instead replace with snprintf. Signed-off-by: Steven Dake - [Steven Dake brought this change] Add tracing to print packets left on session at libssh2_session_free Signed-off-by: Steven Dake Peter Stuge (2 Mar 2012) - Define and use LIBSSH2_INVALID_SOCKET instead of INVALID_SOCKET INVALID_SOCKET is a special value in Windows representing a non-valid socket identifier. We were #defining this to -1 on non-Windows platforms, causing unneccessary namespace pollution. Let's have our own identifier instead. Thanks to Matt Lawson for pointing this out. - nw/Makefile.netware: Fix project name typo to avoid needless confusion - example/x11: Set raw terminal mode manually instead of with cfmakeraw() OpenSolaris has no cfmakeraw() so to make the example more portable we simply do the equivalent operations on struct termios ourselves. Thanks to Tom Weber for reporting this problem, and finding a solution. Daniel Stenberg (17 Feb 2012) - sftp_write: cannot return acked data *and* EAGAIN Whenever we have acked data and is about to call a function that *MAY* return EAGAIN we must return the number now and wait to get called again. Our API only allows data *or* EAGAIN and we must never try to get both. Peter Stuge (13 Feb 2012) - example/x11: Build only when sys/un.h is found by configure The example can't be built on systems without AF_UNIX sockets. Daniel Stenberg (10 Feb 2012) - [Alexander Lamaison brought this change] Simplified sftp_read. Removed the total_read variable that originally must have tracked how much data had been written to the buffer. With non-blocking reads, we must return straight away once we have read data into the buffer so this variable served not purpose. I think it was still hanging around in case the initial processing of 'leftover' data meant we wrote to the buffer but this case, like the others, must return immediately. Now that it does, the last remaining need for the variable is gone. - [Alexander Lamaison brought this change] Cleaned up sftp_read and added more explanation. Replaced the gotos which were implementing the state machine with a switch statement which makes the states more explicit. - sftp_read: avoid data *and* EAGAIN Whenever we have data and is about to call a function that *MAY* return EAGAIN we must return the data now and wait to get called again. Our API only allows data *or* EAGAIN and we must never try to get both. Peter Stuge (2 Feb 2012) - Add a tcpip-forward example which demonstrates remote port forwarding - libssh2.h: Add missing prototype for libssh2_session_banner_set() - example/subsystem_netconf.c: Return error when read buffer is too small Also remove a little redundancy in the read loop condition. - example/subsystem_netconf.c: Add a missing newline in an error message - Fix undefined reference to _libssh_error in libgcrypt backend Commit 209de22299b4b58e582891dfba70f57e1e0492db introduced a function call to a non-existing function, and since then the libgcrypt backend has not been buildable. Version 1.4.0 (31 Jan 2012) Daniel Stenberg (31 Jan 2012) - RELEASE-NOTES: synced with 6bd584d29 for 1.4.0 - s/1.3.1/1.4.0 We're bumping the minor number - [Jernej Kovacic brought this change] libssh2_session_supported_algs: fix compiler warning - [Jernej Kovacic brought this change] session_supported_algs docs: added an example - [Gellule Xg brought this change] sftp-seek: clear EOF flag Set the EOF flag to False when calling seek64 to be able to get some data back on a following read - [Peter Krempa brought this change] userauth: Provide more informations if ssh pub key extraction fails If the function that extracts/computes the public key from a private key fails the errors it reports were masked by the function calling it. This patch modifies the key extraction function to return errors using _libssh_error() function. The error messages are tweaked to contain reference to the failed operaton in addition to the reason. * AUTHORS: - add my name * libgcrypt.c: _libssh2_pub_priv_keyfile(): - return a more verbose error using _libssh2_error() func. * openssl.c: - modify call graph of _libssh2_pub_priv_keyfile() to use _libssh2_error for error reporting(); * userauth.c: - tweak functions calling _libssh2_pub_priv_keyfile() not to shadow error messages - TODO: remove issues we (sort of) did already - ssh2_exec: skip error outputs for EAGAIN Since the example uses non-blocking mode, it will just flood the output with this "nonsense" error. Guenter Knauf (30 Nov 2011) - Some NetWare makefile tweaks. Daniel Stenberg (18 Nov 2011) - LIBSSH2_SFTP_PACKET_MAXLEN: increase to 80000 Some SFTP servers send SFTP packets larger than 40000. Since the limit is only present to avoid insane sizes anyway, we can easily bump it. The define was formerly in the public header libssh2_sftp.h but served no external purpose and was moved into the source dir. Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2011-11/0004.shtml Reported by: Michael Harris Alexander Lamaison (18 Nov 2011) - [Peter Krempa brought this change] knownhost_check(): Don't dereference ext if NULL is passed Documentation for libssh2_knownhost_checkp() and related functions states that the last argument is filled with data if non-NULL. "knownhost if set to non-NULL, it must be a pointer to a 'struct libssh2_knownhost' pointer that gets filled in to point to info about a known host that matches or partially matches." In this function ext is dereferenced even if set to NULL, causing segfault in applications not needing the extra data. Daniel Stenberg (11 Nov 2011) - [Peter Krempa brought this change] knownhost_add: Avoid dereferencing uninitialized memory on error path. In function knownhost_add, memory is alocated for a new entry. If normal alocation is used, memory is not initialized to 0 right after, but a check is done to verify if correct key type is passed. This test is done BEFORE setting the memory to null, and on the error path function free_host() is called, that tries to dereference unititialized memory, resulting into a glibc abort(). * knownhost.c - knownhost_add(): - move typemask check before alloc - windows build: add define to avoid compiler warning A recent mingw compiler has started to complain on "#warning Please include winsock2.h before windows.h" unless the magic define is set first. Reported by: Vincent Torri Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2011-10/0064.shtml Henrik Nordstrom (31 Oct 2011) - [Vincent Torri brought this change] Correct Windows include file name case, simplifying cross-compilation When cross compiling to Windows, libssh2.h include Windows header files with upper case filenames : BaseTsd.h and WinSock2.h. These files have lowercase names with mingw-w64 (iirc, it's the same with mingw). And as on Windows, being lowercase or uppercase does not matter. Daniel Stenberg (25 Oct 2011) - [Jernej Kovacic brought this change] libssh2_session_supported_algs: added - [Kamil Dudka brought this change] example/sftp_RW_nonblock: do not ignore LIBSSH2_ERROR_EAGAIN Bug: https://bugzilla.redhat.com/745420 Peter Stuge (5 Oct 2011) - example/ssh2_agent: Print host key fingerprint before authentication Also moves the comment about not being authenticated to before the agent authentication takes place, so that it better matches the code. Daniel Stenberg (29 Sep 2011) - OpenSSL EVP: fix threaded use of structs Make sure we don't clear or reset static structs after first init so that they work fine even when used from multiple threads. Init the structs in the global init. Help and assistance by: John Engstrom Fixes #229 (again) - openssl: don't init static structs differently make_ctr_evp() is changed to take a struct pointer, and then each _libssh2_EVP_aes_[keylen]_ctr function is made to pass in their own static struct Reported by: John Engstrom Fixes #229 Guenter Knauf (27 Sep 2011) - Removed obsolete include path. Daniel Stenberg (21 Sep 2011) - read_state: clear the state variable better Set read_state back to idle before trying to send anything so that if the state somehow is wrongly set. Also, avoid such a case of confusion by resetting the read_state when an sftp handle is closed. - sftp_read: remove leftover fprintf Reported by: Alexander Lamaison - sftp.h: fix the #ifdef to prevent multiple inclusions - sftp_read: use a state variable to avoid bad writes When a channel_write call has gotten an EAGAIN back, we try harder to continue the same write in the subsequent invoke. - window_size: explicit adjustments only Removed the automatic window_size adjustments from _libssh2_channel_read() and instead all channel readers must now make sure to enlarge the window sizes properly themselves. libssh2_channel_read_ex() - the public function, now grows the window size according to the requested buffer size. Applications can still opt to grow the window more on demand. Larger windows tend to give higher performance. sftp_read() now uses the read-ahead logic to figure out a window_size. - libssh2.h: bump the default window size to 256K - libssh2_userauth_keyboard_interactive.3: fix man warning It seemed to occur due to the excessive line length - [Mikhail Gusarov brought this change] Add missing .gitignore entries - [Mikhail Gusarov brought this change] Add manpage syntax checker to 'check' target In virtually every libssh2 release Debian's lintian catches syntax errors in manpages. Prevent it by checking manpages as a part of testsuite. - libssh2_banner_set.3: fix nroff syntax mistake Guenter Knauf (10 Sep 2011) - Use predefined resource compiler macro. - Added casts to silent compiler warnings. - Fixed uint64_t printf. - Fixed macro function signatures. - NetWare makefile tweaks. - Removed unused var. - Added 2 samples not mentioned. - Dont build x11 sample with MinGW. - Fixed executable file description. - Removed unused var. - Kill stupid gcc 3.x uninitialized warning. - Build all examples. - More MinGW makefile tweaks. Renamed *.mingw makefiles to GNUmakefile since GNU make picks these up automatically, and therefore win32/Makefile removed. - Removed forgotten WINSOCK_VERSION defines. Daniel Stenberg (9 Sep 2011) - libssh2_session_startup(3) => libssh2_session_handshake(3) Propagate for the current function in docs and examples. libssh2_session_startup() is deprecated. - libssh2_banner_set => libssh2_session_banner_get Marked the old function as deprecated. Added the new name in the correct name space with the same arguments and functionality. - new function: libssh2_session_banner_get Returns the banner from the server handshake Fixes #226 - libssh2.h: bump version to 1.4.0 for new function(s) - remove embedded CVS/svn tags - [liuzl brought this change] API add:libssh2_sftp_get_channel Return the channel of sftp, then caller can control the channel's behavior. Signed-off-by: liuzl - _libssh2_channel_read: react on errors from receive_window_adjust Previously the function would ignore all errors except for EAGAIN. - sftp_read: extend and clarify the documentation - sftp_read: cap the read ahead maximum amount Now we only go up to LIBSSH2_CHANNEL_WINDOW_DEFAULT*30 bytes SFTP read ahead, which currently equals 64K*30 == 1966080 bytes. - _libssh2_channel_read: fix non-blocking window adjusting If EAGAIN is returned when adjusting the receive window, we must not read from the transport directly until we've finished the adjusting. Guenter Knauf (8 Sep 2011) - Fix for systems which need sys/select.h. - The files were not gone but renamed ... Daniel Stenberg (6 Sep 2011) - sftp_read: added documenting comment Taken from some recent email conversations I added some descriptions of the logic in sftp_read() to aid readers. - 1.3.1: start the work Version 1.3.0 (6 Sep 2011) Daniel Stenberg (6 Sep 2011) - Makefile.am: the Makefile.win32 files are gone - RELEASE-NOTES: updated for 1.3.0 - sftp_read: a short read is not end of file A returned READ packet that is short will now only reduce the offset. This is a temporary fix as it is slightly better than the previous approach but still not very good. - [liuzl brought this change] _libssh2_packet_add: adjust window size when truncating When receiving more data than what the window size allows on a particular channel, make sure that the window size is adjusted in that case too. Previously it would only adjust the window in the non-error case. Guenter Knauf (29 Aug 2011) - Silent compiler warning with MinGW64. - Fixed link to native Win32 awk tool. - Renamed MinGW makefiles. - Some MinGW makefile tweaks. Enable build without GNU tools and with MinGW64 compiler. - Fixed aes_ctr_do_cipher() signature. Daniel Stenberg (26 Aug 2011) - [liuzl brought this change] libssh2_sftp_seek64: flush packetlist and buffered data When seeking to a new position, flush the packetlist and buffered data to prevent already received or pending data to wrongly get used when sftp-reading from the new offset within the file. - sftp_read: advance offset correctly for buffered copies In the case where a read packet has been received from the server, but the entire contents couldn't be copied to the user-buffer, the data is instead buffered and copied to the user's buffer in the next invocation of sftp_read(). When that "extra" copy is made, the 'offset' pointer was not advanced accordingly. The biggest impact of this flaw was that the 'already' variable at the top of the function that figures out how much data "ahead" that has already been asked for would slowly go more and more out of sync, which could lead to the file not being read all the way to the end. This problem was most noticable in cases where the application would only try to read the exact file size amount, like curl does. In the examples libssh2 provides the sftp read function is most often called with a fixed size large buffer and then the bug would not appear as easily. This bug was introduced in the SFTP rewrite in 1.2.8. Bug: http://curl.haxx.se/mail/lib-2011-08/0305.html http://www.libssh2.org/mail/libssh2-devel-archive-2011-08/0085.shtml - wrap some long lines < 80 columns - LIBSSH2_RECV: fix typo, use the RECV_FD macro - subsystem_netconf.c: fix compiler warnings - [Henrik Nordstrom brought this change] Custom callbacks for performing low level socket I/O - version bump: start working towards 1.3.0 Version 1.2.9 (16 Aug 2011) Daniel Stenberg (16 Aug 2011) - RELEASE-NOTES: synced with 95d69d3a81261 - [Henrik Nordstrom brought this change] Document prototypes for macro defined functions - [Henrik Nordstrom brought this change] Avoid reuse after free when closing X11 channels - _libssh2_channel_write: handle window_size == 0 better When about to send data on the channel and the window size is 0, we must not just return 0 if the transport_read() function returned EAGAIN as it then causes a busy-loop. Bug: http://libssh2.org/mail/libssh2-devel-archive-2011-08/0011.shtml - gettimeofday: fix name space pollution For systems without its own gettimeofday() implementation, we still must not provide one outside our namespace. Reported by: Bill Segall Dan Fandrich (5 Aug 2011) - libssh2.pc.in: Fixed spelling in pkgconfig file Peter Stuge (17 Jul 2011) - example/subsystem_netconf.c: Add missing #include - example/subsystem_netconf.c: Discard ]]>]]> and return only XML response - example/subsystem_netconf.c: Fix uninitialized variable bug - example: Add subsystem_netconf.c This example demonstrates how to use libssh2 to send a request to the NETCONF subsystem available e.g. in JunOS. See also http://tools.ietf.org/html/draft-ietf-netconf-ssh-06 Daniel Stenberg (16 Jul 2011) - man page cleanups: non-existing functions need no man pages - libssh2_new_host_entry.3: removed This is just junk leftovers. - userauth_keyboard_interactive: fix buffer overflow Partly reverse 566894494b4972ae12 which was simplifying the code far too much and ended up overflowing a buffer within the LIBSSH2_SESSION struct. Back to allocating the buffer properly like it used to do. Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2011-06/0032.shtml Reported by: Alfred Gebert - keyboard-interactive man page: cleaned up - [Alfred Gebert brought this change] _libssh2_recv(): handle ENOENT error as EAGAIN A sftp session failed with error "failure establishing ssh session" on Solaris and HP-UX. Sometimes the first recv() function call sets errno to ENOENT. In the man pages for recv of Solaris and HP-UX the error ENOENT is not documented. I tested Solaris SPARC and x86, HP-UX i64, AIX, Windows and Linux. - agent_list_identities: fix out of scope access An auto variable out of scope was being referenced and used. fixes #220 - _libssh2_wait_socket: fix timeouts for poll() uses - windows: inclusion fix include winsock2.h for all windows compilers - keyb-interactive: add the fixed buffer Belongs to commit 5668944 - code cleanup: don't use C99/c++ comments We aim for C89 compliance - keyb-interactive: allow zero length fields Allow zero length fields so they don't cause malloc(0) calls Avoid free()ing NULL pointers Avoid a malloc of a fixed 5 byte buffer. - libssh2_channel_process_startup.3: clean up Remove the references to the macro-fied shortcuts as they have their own individual man pages. Made the prototype different and more readable. - man page: fix .BR lines We don't use \fI etc on .BR lines - userauth_keyboard_interactive: skip code on zero length auth - libssh2_channel_forward_accept.3: mention how to get error Since this returns a pointer, libssh2_session_last_errno() must be used to get the actual error code and it wasn't that clear before. - timeout docs: mention they're added in 1.2.9 - sftp_write_sliding.c: indent fix Use the standard indenting and removed CVS leftover comment - [zl liu brought this change] sftp_write_sliding: send the complete file When reaching the end of file there can still be data left not sent. - [Douglas Masterson brought this change] session_startup: init state properly libssh2_session_startup() didn't set the state correctly so it could get confused. Fixes #218 - timeout: added man pages - BLOCK_ADJUST_ERRNO: move rc to right level We can't declare the variable within the block and use it in the final do-while() expression to be properly portable C89. - [Matt Lilley brought this change] adds a timeout to blocking calls Fixes bug #160 as per Daniel's suggestion Adds libssh2_session_set_timeout() and libssh2_session_get_timeout() - SCP: fix incorrect error code After an error occurs in libssh2_scp_recv() or libssh2_scp_send(), the function libssh2_session_last_error() would return LIBSSH2_ERROR_SOCKET_NONE on error. Bug: http://trac.libssh2.org/ticket/216 Patch by: "littlesavage" Fixes #216 Guenter Knauf (19 Apr 2011) - Updated default (recommended) dependency versions. Daniel Stenberg (17 Apr 2011) - libssh2_session_block_directions: fix mistake The last LIBSSH2_SESSION_BLOCK_INBOUND should be LIBSSH2_SESSION_BLOCK_OUTBOUND And I shortened the short description Reported by: "drswinghead" - msvcproj: added libs and debug stuff Added libraries needed to link whether using openssl dynamically or statically Added LIBSSH2DEBUG define to debug versions to enable tracing URL: http://trac.libssh2.org/ticket/215 Patch by: Mark Smith - sftp_write: clean offsets on error When an error has occurred on FXP_WRITE, we must make sure that the offset, sent offset and acked counter are reset properly. - example/.gitignore: ignore built binaries - sftp_write: flush the packetlist on error When an error occurs during write, flush the entire list of pending outgoing SFTP packets. - keepalive: add first basic man pages Someone on IRC pointed out that we don't have these documented so I wrote up a first set based on the information in the wiki: http://trac.libssh2.org/wiki/KeepAlive - scp_write_nonblock.c: remove pointless check libssh2_channel_write() cannot return a value that is larger than the input length value Mikhail Gusarov (9 Apr 2011) - s/\.NF/.nf/ to fix wrong macro name caught by man --warnings Daniel Stenberg (6 Apr 2011) - version: bump to 1.2.9_dev Also update the copyright year range to include 2011 - configure: fix $VERSION Stop using the $VERSION variable as it seems to be magically used by autoconfig itself and thus gets set to the value set in AC_INIT() without us wanting that. $LIBSSH2VER is now the libssh2 version as detected. Reported by: Paul Howarth Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2011-04/0008.shtml - maketgz: use git2news.pl by the correct name Version 1.2.8 (4 Apr 2011) Daniel Stenberg (4 Apr 2011) - RELEASE-NOTES: synced with fabf1a45ee - NEWS: auto-generated from git Starting now, the NEWS file is generated from git using the git2news.pl script. This makes it always accurate and up-to-date, even for daily snapshots etc. - sftp_write: handle FXP_WRITE errors When an sftp server returns an error back on write, make sure the function bails out and returns the proper error. - configure: stop using the deprecated AM_INIT_AUTOMAKE syntax Alexander Lamaison (13 Mar 2011) - Support unlimited number of host names in a single line of the known_hosts file. Previously the code assumed either a single host name or a hostname,ip-address pair. However, according to the spec [1], there can be any number of comma separated host names or IP addresses. [1] http://www.openbsd.org/cgi-bin/man.cgi?query=sshd&sektion=8 Daniel Stenberg (26 Feb 2011) - libssh2_knownhost_readfile.3: clarify return value This function returns the number of parsed hosts on success, not just zero as previously documented. Peter Stuge (26 Feb 2011) - Don't save allocated packet size until it has actually been allocated The allocated packet size is internal state which needs to match reality in order to avoid problems. This commit fixes #211. Daniel Stenberg (21 Feb 2011) - [Alfred Gebert brought this change] session_startup: manage server data before server identification Fix the bug that libssh2 could not connect if the sftp server sends data before sending the version string. http://tools.ietf.org/html/rfc4253#section-4.2 "The server MAY send other lines of data before sending the version string. Each line SHOULD be terminated by a Carriage Return and Line Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients MUST be able to process such lines." - [Alfred Gebert brought this change] fullpacket: decompression only after init The buffer for the decompression (remote.comp_abstract) is initialised in time when it is needed. With this fix decompression is disabled when the buffer (remote.comp_abstract) is not initialised. Bug: http://trac.libssh2.org/ticket/200 - _libssh2_channel_read: store last error When the transport layer returns EAGAIN this function didn't call _libssh2_error() which made the last_error not get set. - sftp_write: clarified the comment header - sftp_read: avoid wrapping counter to insanity As pointed out in bug #206, if a second invoke of libssh2_sftp_read() would shrink the buffer size, libssh2 would go nuts and send out read requests like crazy. This was due to an unsigned variable turning "negative" by some wrong math, and that value would be the amount of data attempt to pre-buffer! Bug: http://trac.libssh2.org/ticket/206 - sftp_packet_read: use 32bit variables for 32bit data - libssh2_sftp_stat_ex.3: cleaned up, extended Removed the macros from it as they have their own man pages. Added the LIBSSH2_SFTP_ATTRIBUTES struct in here for easier reference. - sftp_readdir: return error if buffer is too small If asked to read data into a buffer and the buffer is too small to hold the data, this function now returns an error instead of as previously just copy as much as fits. - sftp_symlink: return error if receive buffer too small and clean up some variable type mismatches Discussion: http://www.libssh2.org/mail/libssh2-devel-archive-2011-01/0001.shtml - docs: clarify what happens with a too small buffer This flaw is subject to change, but I figured it might be valuable to users of existing code to know how it works. - channel_request_pty_size: fix reqPTY_state The state variable isn't properly set so every other call to the function fails! Bug: http://libssh2.org/mail/libssh2-devel-archive-2010-12/0096.shtml Reported by: Steve Legg - data size: cleanup Fix 64bit warnings by using (s)size_t and dedicated uint32_t types more. - [Pierre Joye brought this change] ssize_t: proper typedef with MSVC compilers As discussed on the mailing list, it was wrong for win64 and using the VC-provided type is the safest approach instead of second- guessing which one it should be. Guenter Knauf (22 Dec 2010) - Updated OpenSSL version. - Expanded tabs to spaces. Peter Stuge (21 Dec 2010) - [Joey Degges brought this change] _libssh2_ntohu64: fix conversion from network bytes to uint64 Cast individual bytes to uint64 to avoid overflow in arithmetic. Daniel Stenberg (20 Dec 2010) - libssh2_userauth_list: language fix "faily" is not a good English word, and I also cleaned up some other minor mistakes - crypto: unify the generic functions Added crypto.h that is the unified header to include when using crypto functionality. It should be the only header that needs to adapt to the underlying crypto library in use. It provides the set of prototypes that are library agnostic. - [Mark Smith brought this change] userauth: derive publickey from private Pass a NULL pointer for the publickey parameter of libssh2_userauth_publickey_fromfile and libssh2_userauth_hostbased_fromfile functions. In this case, the functions recompute the public key from the private key file data. This is work done by Jean-Louis CHARTON , then adapted by Mark Smith and slightly edited further by me Daniel. WARNING: this does leave the feature NOT WORKING when libssh2 is built to use libgcrypt instead of OpenSSL simply due to lack of implementation. - ssh2_echo: Value stored to 'exitcode' is never read - _libssh2_packet_add: fix SSH_MSG_DEBUG weirdness I believe I may have caused this weird typo style error when I cleaned up this function a while ago. Corrected now. - uint32: more longs converted to proper types I also moved the MAC struct over to the mac.h header file and made sure that the users of that struct include that file. - SFTP: more types to uint32_t The 'num_names' field in the SSH_FXP_NAME response is an unsigned 32bit value so we make sure to treat it like that. - SFTP: request_ids are uint32_t I went over the code and made sure we use uint32_t all over for the request_id data. It is an unsigned 32bit value on the wire. - SFTP: store request_id separately in packets By using a new separate struct for incoming SFTP packets and not sharing the generic packet struct, we can get rid of an unused field and add a new one dedicated for holding the request_id for the incoming package. As sftp_packet_ask() is called fairly often, a "mere" integer comparison is MUCH faster than the previous memcmp() of (typically) 5 bytes. - libssh2_sftp_open_ex: man page extended and cleaned up I added the missing documentation for the 'flags' argument. - SFTP: unify the READ/WRITE chunk structs - SFTP: fix memory leaks Make sure that we cleanup remainders when the handle is closed and when the subsystem is shutdown. Existing flaw: if a single handle sends packets that haven't been replied to yet at the time when the handle is closed, those packets will arrive later and end up in the generic packet brigade queue and they will remain in there until flushed. They will use unnecessary memory, make things slower and they will ruin the SFTP handling if the request_id counter ever wraps (highly unlikely to every happen). - sftp_close_handle: packet list is generic Fix comment, simplify the loop logic - sftp_read: pipeline reads The SFTP read function now does transfers the same way the SFTP write function was made to recently: it creates a list of many outgoing FXP_READ packets that each asks for a small data chunk. The code then tries to keep sending read request while collecting the acks for the previous requests and returns the received data. - sftp_write: removed unused variable - _libssh2_channel_close: don't call transport read if disconnected The loop that waits for remote.close to get set may end up looping forever since session->socket_state gets set to LIBSSH2_SOCKET_DISCONNECTED by the packet_add() function called from the transport_read() function and after having been set to LIBSSH2_SOCKET_DISCONNECTED, the transport_read() function will only return 0. Bug: http://trac.libssh2.org/ticket/198 - libssh2_sftp_seek64: new man page Split off libssh2_sftp_seek64 from the libssh2_sftp_seek man page, and mentioned that we consider the latter deprecated. Also added a mention about the dangers of doing seek during writing or reading. - sftp_seek: fix The new SFTP write code caused a regression as the seek function no longer worked as it didn't set the write position properly. It should be noted that seeking is STRONGLY PROHIBITED during upload, as the upload magic uses two different offset positions and the multiple outstanding packets etc make them sensitive to change in the midst of operations. This functionality was just verified with the new example code sftp_append. This bug was filed as bug #202: Bug: http://trac.libssh2.org/ticket/202 - sftp_append: new example doing SFTP append - MAX_SFTP_OUTGOING_SIZE: 30000 I ran SFTP upload tests against localhost. It showed that to make the app reach really good speeds, I needed to do a little code tweak and change MAX_SFTP_OUTGOING_SIZE from 4000 to 30000. The tests I did before with the high latency tests didn't show any real difference whatever I had that size set to. This number is the size in bytes that libssh2 cuts off the large input buffer and sends off as an individual sftp packet. - sftp_write_sliding.c: new example This is an example that is very similar to sftp_write_nonblock.c, with the exception that this uses 1 - a larger upload buffer 2 - a sliding buffer mechnism to allow the app to keep sending lots of data to libssh2 without having to first drain the buffer. These are two key issues to make libssh2 SFTP uploads really perform well at this point in time. - cpp: s/#elsif/#elif This looks like a typo as #elsif is not really C... - _libssh2_channel_write: revert channel_write() use The attempts made to have _libssh2_channel_write() accept larger pieces of data and split up the data by itself into 32700 byte chunks and pass them on to channel_write() in a loop as a way to do faster operations on larger data blocks was a failed attempt. The reason why it is difficult: The API only allows EAGAIN or a length to be returned. When looping over multiple blocks to get sent, one block can get sent and the next might not. And yet: when transport_send() has returned EAGAIN we must not call it again with new data until it has returned OK on the existing data it is still working on. This makes it a mess and we do get a much easier job by simply returning the bytes or EAGAIN at once, as in the EAGAIN case we can assume that we will be called with the same arguments again and transport_send() will be happy. Unfortunately, I think we take a small performance hit by not being able to do this. - ssh2_echo: new example This is a new example snippet. The code is largely based on ssh2_exec, and is written by Tommy Lindgren. I edited it into C90 compliance and to conform to libssh2 indent style and some more. - send_existing: return after send_existing When a piece of data is sent from the send_existing() function we must make the parent function return afterwards. Otherwise we risk that the parent function tries to send more data and ends up getting an EGAIN for that more data and since it can only return one return code it doesn't return info for the successfully sent data. As this change is a regression I now added a larger comment explaining why it has to work like this. - _libssh2_channel_write: count resent data as written In the logic that resends data that was kept for that purpose due to a previous EAGAIN, the data was not counted as sent causing badness. Peter Stuge (13 Nov 2010) - Use fprintf(stderr, ) instead of write(2, ) for debugging - session/transport: Correctly handle when _libssh2_send() returns -EAGAIN - src/agent.c: Simplify _libssh2_send() error checking ever so slightly Daniel Stenberg (12 Nov 2010) - send/recv: use _libssh2_recv and _libssh2_send now Starting now, we unconditionally use the internal replacement functions for send() and recv() - creatively named _libssh2_recv() and _libssh2_send(). On errors, these functions return the negative 'errno' value instead of the traditional -1. This design allows systems that have no "natural" errno support to not have to invent it. It also means that no code outside of these two transfer functions should use the errno variable. - channel_write: move some logic to _libssh2_channel_write Some checks are better done in _libssh2_channel_write just once per write instead of in channel_write() since the looping will call the latter function multiple times per _libssh2_channel_write() invoke. - sftp_write: handle "left over" acked data The SFTP handle struct now buffers number of acked bytes that haven't yet been returned. The way this is used is as following: 1. sftp_write() gets called with a buffer of let say size 32000. We split 32000 into 8 smaller packets and send them off one by one. One of them gets acked before the function returns so 4000 is returned. 2. sftp_write() gets called again a short while after the previous one, now with a much smaller size passed in to the function. Lets say 8000. In the mean-time, all of the remaining packets from the previous call have been acked (7*4000 = 28000). This function then returns 8000 as all data passed in are already sent and it can't return any more than what it got passed in. But we have 28000 bytes acked. We now store the remaining 20000 in the handle->u.file.acked struct field to add up in the next call. 3. sftp_write() gets called again, and now there's a backlogged 20000 bytes to return as fine and that will get skipped from the beginning of the buffer that is passed in. - sftp_write: polished and simplified Removed unnecessary struct fields and state changes within the function. Made the loop that checks for ACKs only check chunks that were fully sent. - SCP: on failure, show the numerical error reason By calling libssh2_session_last_errno() - SFTP: provide the numerical error reason on failure - SCP: clean up failure treatment When SCP send or recv fails, it gets a special message from the server with a warning or error message included. We have no current API to expose that message but the foundation is there. Removed unnecessary use of session struct fields. - sftp_write: enlarge buffer to perform better - packets: code cleanup I added size checks in several places. I fixed the code flow to be easier to read in some places. I removed unnecessary zeroing of structs. I removed unused struct fields. - LIBSSH2_CALLBACK_MACERROR: clarify return code use - _libssh2_userauth_publickey: avoid shadowing - packet: avoid shadowing global symbols - sftp_readdir: avoid shadowing - shadowing: don't shadow the global compress - _libssh2_packet_add: turn ifs into a single switch - _libssh2_packet_add: check SSH_MSG_GLOBAL_REQUEST packet - _libssh2_packet_add: SSH_MSG_DEBUG length checks Verify lengths before using them. Read always_display from the correct index. Don't copy stuff around just to provide zero-termination of the strings. - _libssh2_packet_add: SSH_MSG_IGNORE skip memmove There's no promise of a zero termination of the data in the callback so no longer perform ugly operation in order to provide it. - _libssh2_packet_add: SSH_MSG_DISCONNECT length checks Verify lengths before trying to read data. - indent: break lines at 80 columns - SSH_MSG_CHANNEL_OPEN_FAILURE: used defined values We don't like magic numbers in the code. Now the acceptable failure codes sent in the SSH_MSG_CHANNEL_OPEN_FAILURE message are added as defined values in the private header file. - sftp_write: don't return EAGAIN if no EAGAIN was received This function now only returns EAGAIN if a lower layer actually returned EAGAIN to it. If nothing was acked and no EAGAIN was received, it will now instead return 0. - _libssh2_wait_socket: detect nothing-to-wait-for If _libssh2_wait_socket() gets called but there's no direction set to wait for, this causes a "hang". This code now detects this situation, set a 1 second timeout instead and outputs a debug output about it. - decomp: remove the free_dest argument Since the decompress function ALWAYS returns allocated memory we get a lot simpler code by removing the ability to return data unallocated. - decomp: cleaned off old compression stuff I cleared off legacy code from when the compression and decompression functions were a single unified function. Makes the code easier to read too. - [TJ Saunders brought this change] decomp: increase decompression buffer sizes - [TJ Saunders brought this change] zlib: Add debug tracing of zlib errors - sftp_packet_read: handle partial reads of the length field SFTP packets come as [32 bit length][payload] and the code didn't previously handle that the initial 32 bit field was read only partially when it was read. - [Jasmeet Bagga brought this change] kex_agree_hostkey: fix NULL pointer derefence While setting up the session, ssh tries to determine the type of encryption method it can use for the session. This requires looking at the keys offered by the remote host and comparing these with the methods supported by libssh2 (rsa & dss). To do this there is an iteration over the array containing the methods supported by libssh2. If there is no agreement on the type of encryption we come to the 3rd entry of the hostkeyp array. Here hostkeyp is valid but *hostkep is NULL. Thus when we dereference that in (*hostkeyp)->name there is a crash - _libssh2_transport_send: remove dead assignment 'data' isn't accessed beyond this point so there's no need to assign it. - scp_recv: remove dead assignment Instead of assigning a variable we won't read, we now use the more explicit (void) prefix. - sftp_write: removed superfluous assignment - bugfix: avoid use of uninitialized value - sftp_packet_require: propagate error codes better There were some chances that they would cause -1 to get returned by public functions and as we're hunting down all such occurances and since the underlying functions do return valuable information the code now passes back proper return codes better. - [Alfred Gebert brought this change] fix memory leaks (two times cipher_data) for each sftp session - libssh2_userauth_authenticated: make it work as documented The man page clearly says it returns 1 for "already authenticated" but the code said non-zero. I changed the code to use 1 now, as that is also non-zero but it gets the benefit that it now matches the documentation. Using 1 instead of non-zero is better for two reasons: 1. We have the opportunity to introduce other return codes in the future for things like error and what not. 2. We don't expose the internal bitmask variable value. - userauth_keyboard_interactive: fix indent - [Alfred Gebert brought this change] fix memory leak in userauth_keyboard_interactive() First I wanted to free the memory in session_free() but then I had still memory leaks because in my test case the function userauth_keyboard_interactive() is called twice. It is called twice perhaps because the server has this authentication methods available: publickey,gssapi-with-mic,keyboard-interactive The keyboard-interactive method is successful. - dist: include sftp.h in dist archives Simon Josefsson (27 Oct 2010) - Update header to match new function prototype, see c48840ba88. Daniel Stenberg (26 Oct 2010) - bugfixes: the transport rearrange left some subtle flaws now gone - libssh2_userauth_publickey_fromfile_ex.3: cleaned up looks - libssh2_userauth_publickey: add man page I found an undocumented public function and we can't have it like that. The description here is incomplete, but should serve as a template to allow filling in... - libssh2_sftp_write.3: added blurb about the "write ahead" Documented the new SFTP write concept - sftp_close_handle: free any trailing write chunks - _libssh2_channel_write: fix warnings - SFTP: bufgix, move more sftp stuff to sftp.h The sftp_write function shouldn't assume that the buffer pointer will be the same in subsequent calls, even if it assumes that the data already passed in before haven't changed. The sftp structs are now moved to sftp.h (which I forgot to add before) - SFTP: use multiple outgoing packets when writing sftp_write was rewritten to split up outgoing data into multiple packets and deal with the acks in a more asynchronous manner. This is meant to help overcome latency and round-trip problems with the SFTP protocol. - TODO: implemented a lot of the ideas now - _libssh2_channel_write: removed 32500 size limit Neither _libssh2_channel_write nor sftp_write now have the 32500 size limit anymore and instead the channel writing function now has its own logic to send data in multiple calls until everything is sent. - send_existing: don't tell parent to return when drained That will just cause unnecessary code execution. - _libssh2_channel_write: general code cleanup simplified the function and removed some unused struct fields - _libssh2_transport_send: replaces _libssh2_transport_write The new function takes two data areas, combines them and sends them as a single SSH packet. This allows several functions to allocate and copy less data. I also found and fixed a mixed up use of the compression function arguments that I introduced in my rewrite in a recent commit. - scp_write_nonblock: use select() instead of busyloop Make this example nicer by not busylooping. - send_existing: clear olen when the data is sent off - _libssh2_transport_write: allow 256 extra bytes around the packet - _libssh2_transport_write: remade to send without malloc - compress: compression disabled by default We now allow libssh2_session_flag() to enable compression with a new flag and I added documentation for the previous LIBSSH2_FLAG_SIGPIPE flag which I wasn't really aware of! - comp: split the compress function It is now made into two separate compress and decompress functions. In preparation for upcoming further modficications. Dan Fandrich (20 Oct 2010) - Added header file to allow compiling in older environments Daniel Stenberg (20 Oct 2010) - TODO: add a possible new API for SFTP transfers - TODO: "New Transport API" added - TODO: add buffering plans Simon Josefsson (13 Oct 2010) - Mention libssh2_channel_get_exit_signal and give kudos. - [Tommy Lindgren brought this change] Add libssh2_channel_get_exit_signal man page. Signed-off-by: Simon Josefsson - [Tommy Lindgren brought this change] Add libssh2_channel_get_exit_signal. Signed-off-by: Simon Josefsson - Add libssh2_free man page and fix typo. - Add libssh2_free. Daniel Stenberg (11 Oct 2010) - scp_recv: improved treatment of channel_read() returning zero As a zero return code from channel_read() is not an error we must make sure that the SCP functions deal with that properly. channel_read() always returns 0 if the channel is EOFed already so we check for EOF after 0-reads to be able to return error properly. - libssh2_session_methods.3: detail what can be asked for - compression: send zlib before none As the list of algorithms in a preferred order we should send zlib before none to increase the chances that the server will let us do compression. - compress: faster check, better return codes In the transport functions we avoid a strcmp() now and just check a boolean instead. The compress/decompress function's return code is now acknowledged and used as actual return code in case of failures. - libssh2_session_handshake: replaces libssh2_session_startup() The function libssh2_session_startup() is now considered deprecated due to the portability issue with the socket argument. libssh2_session_handshake() is the name of the replacement. - libssh2_socket_t: now externally visible In preparation for upcominig changes, the libssh2_socket_t type is now typedef'ed in the public header. - _libssh2_transport_drain: removed This function proved not to be used nor useful. - _libssh2_channel_write: don't iterate over transport writes When a call to _libssh2_transport_write() succeeds, we must return from _libssh2_channel_write() to allow the caller to provide the next chunk of data. We cannot move on to send the next piece of data that may already have been provided in this same function call, as we risk getting EAGAIN for that and we can't return information both about sent data as well as EAGAIN. So, by returning short now, the caller will call this function again with new data to send. - _libssh2_transport_write: updated documentation blurb - _libssh2_transport_write: remove fprintf remainder Mistake from previous debugging - session: improved errors Replaced -1/SOCKET_NONE errors with appropriate error defines instead. Made the verbose trace output during banner receiving less annoying for non-blocking sessions. - crypt_init: use correct error define - _libssh2_error: hide EAGAIN for non-blocking sessions In an attempt to make the trace output less cluttered for non-blocking sessions the error function now avoids calling the debug function if the error is the EAGAIN and the session is non-blocking. - agent: use better error defines - comp_method_zlib_init: use correct error defines - transport: better error codes LIBSSH2_SOCKET_NONE (-1) should no longer be used as error code as it is (too) generic and we should instead use specific and dedicated error codes to better describe the error. - channel: return code and _libssh2_error cleanup Made sure that all transport_write() call failures get _libssh2_error called. - _libssh2_channel_write: limit to 32700 bytes The well known and used ssh server Dropbear has a maximum SSH packet length at 32768 by default. Since the libssh2 design current have a fixed one-to-one mapping from channel_write() to the packet size created by transport_write() the previous limit of 32768 in the channel layer caused the transport layer to create larger packets than 32768 at times which Dropbear rejected forcibly (by closing the connection). The long term fix is of course to remove the hard relation between the outgoing SSH packet size and what the input length argument is in the transport_write() function call. - libssh.h: add more dedicated error codes - SCP: allow file names with bytes > 126 When parsing the SCP protocol and verifying that the data looks like a valid file name, byte values over 126 must not be consider illegal since UTF-8 file names will use such codes. Reported by: Uli Zappe Bug: http://www.libssh2.org/mail/libssh2-devel-archive-2010-08/0112.shtml Dan Fandrich (25 Aug 2010) - Document the three sftp stat constants Guenter Knauf (18 Aug 2010) - Fixed Win32 makefile which was now broken at resource build. - It is sufficient to pipe stderr to NUL to get rid of the nasty messages. - [Author: Guenter Knauf brought this change] Removed Win32 ifdef completely for sys/uio.h. No idea why we had this ifdef at all but MSVC, MingW32, Watcom and Borland all have no sys/uio.h header; so if there's another Win32 compiler which needs it then it should be added explicitely instead of this negative list. - New files should also be added to Makefile.am. Otherwise they will never be included with release and snapshot tarballs ... Daniel Stenberg (18 Aug 2010) - version: bump to 1.2.8_DEV Version 1.2.7 (17 Aug 2010) Daniel Stenberg (17 Aug 2010) - release: updated to hold 1.2.7 info Guenter Knauf (17 Aug 2010) - Use the new libssh2.rc file. - Added resource file for libssh2.dll (shamelessly stolen from libcurl). - Updated Win32 MSVC dependencies versions. - Added include for sys/select.h to get fd.set on some platforms. - Added Watcom makefile borrowed from libcurl. This makefile compiles already all files fine for static lib, but needs final touch when I have OpenSSL fully working with shared libs and Watcom. - Added copyright define to libssh2.h and use it for binary builds. - Moved version defines up in order to include from .rc file. Blocked rest of header with ifndef so its possible to let the rc compiler only use the version defines. - Some minor makefile tweaks. Daniel Stenberg (2 Aug 2010) - example: treat the libssh2_channel_read() return code properly A short read is not an error. Only negative values are errors! - libssh2_wait_socket: reset error code to "leak" EAGAIN less Since libssh2 often sets LIBSSH2_ERROR_EAGAIN internally before _libssh2_wait_socket is called, we can decrease some amount of confusion in user programs by resetting the error code in this function to reduce the risk of EAGAIN being stored as error when a blocking function returns. - _libssh2_wait_socket: poll needs milliseconds As reported on the mailing list, the code path using poll() should multiple seconds with 1000 to get milliseconds, not divide! Reported by: Jan Van Boghout - typedef: make ssize_t get typedef without LIBSSH2_WIN32 The condition around the ssize_t typedef depended on both LIBSSH2_WIN32 *and* _MSC_VER being defined when it should be enough to depend on _MSC_VER only. It also makes it nicer so libssh2-using code builds fine without having custom defines. - [John Little brought this change] session_free: free more data to avoid memory leaks - channel_free: ignore problems with channel_close() As was pointed out in bug #182, we must not return failure from _libssh2_channel_free() when _libssh2_channel_close() returns an error that isn't EAGAIN. It can effectively cause the function to never go through, like it did now in the case where the socket was actually closed but socket_state still said LIBSSH2_SOCKET_CONNECTED. I consider this fix the right thing as it now also survives other errors, even if making sure socket_state isn't lying is also a good idea. - publickey_list_free: no return value from a void function Fixed a compiler warning I introduced previously when checking input arguments more. I also added a check for the other pointer to avoid NULL pointer dereferences. - [Lars Nordin brought this change] openssl: make use of the EVP interface Make use of the EVP interface for the AES-funktion. Using this method supports the use of different ENGINES in OpenSSL for the AES function (and the direct call to the AES_encrypt should not be used according to openssl.org) Peter Stuge (23 Jun 2010) - [Tor Arntsen brought this change] Don't overflow MD5 server hostkey Use SHA_DIGEST_LENGTH and MD5_DIGEST_LENGTH in memcpy instead of hardcoded values. An incorrect value was used for MD5. - Fix message length bugs in libssh2_debug() There was a buffer overflow waiting to happen when a debug message was longer than 1536 bytes. Thanks to Daniel who spotted that there was a problem with the message length passed to a trace handler also after commit 0f0652a3093111fc7dac0205fdcf8d02bf16e89f. - Make libssh2_debug() create a correctly terminated string Also use FILE *stderr rather than fd 2, which can very well be something completely different. Daniel Stenberg (23 Jun 2010) - [TJ Saunders brought this change] handshake: Compression enabled at the wrong time In KEXINIT messages, the client and server agree on, among other things, whether to use compression. This method agreement occurs in src/kex.c's kex_agree_methods() function. However, if compression is enabled (either client->server, server->client, or both), then the compression layer is initialized in kex_agree_methods() -- before NEWKEYS has been received. Instead, the initialization of the compression layer should happen after NEWKEYS has been received. This looks to occur insrc/kex.c's diffie_hellman_sha1(), which even has the comment: /* The first key exchange has been performed, switch to active crypt/comp/mac mode */ There, after NEWKEYS is received, the cipher and mac algorithms are initialized, and that is where the compression should be initialized as well. The current implementation fails if server->client compression is enabled because most server implementations follow OpenSSH's lead, where compression is initialized after NEWKEYS. Since the server initializes compression after NEWKEYS, but libssh2 initializes compression after KEXINIT (i.e. before NEWKEYS), they are out of sync. Reported in bug report #180 - [TJ Saunders brought this change] userauth_hostbased_fromfile: packet length too short The packet length calculated in src/userauth.c's userauth_hostbased_fromfile() function is too short by 4 bytes; it forgets to add four bytes for the length of the hostname. This causes hostbased authentication to fail, since the server will read junk data. verified against proftpd's mod_sftp module - _libssh2_userauth_publickey: reject method names longer than the data This functions get the method length by looking at the first 32 bit of data, and I now made it not accept method lengths that are longer than the whole data set is, as given in the dedicated function argument. This was detected when the function was given bogus public key data as an ascii string, which caused the first 32bits to create a HUGE number. - NULL resistance: make more public functions survive NULL pointer input Sending in NULL as the primary pointer is now dealt with by more public functions. I also narrowed the userauth.c code somewhat to stay within 80 columns better. - agent: make libssh2_agent_userauth() work blocking properly previously it would always work in a non-blocking manner Peter Stuge (17 Jun 2010) - Fix underscore typo for 64-bit printf format specifiers on Windows Commit 49ddf447ff4bd80285f926eac0115f4e595f9425 was missing underscores. Daniel Stenberg (16 Jun 2010) - libssh2_session_callback_set: extended the man page - [John brought this change] LIBSSH2_DEBUG: macro uses incorrect function variable The LIBSSH2_DEBUG macro, defined in libssh2_priv.h, incorrectly uses the function variable ssh_msg_disconnect when it should use ssh_msg_debug. This shows that the LIBSSH2_CALLBACK_DEBUG callback never has worked... - warning: fix a compiler warning 'pointer differs in signedness' As reported in bug #177 - portability: introduce LIBSSH2_INT64_T_FORMAT for 64bit printf()s As pointed out in bug #177, some of the Windows compilers use %I64 to output 64 bit variables with the printf family. - debug: avoid sending NULL to sprintf %s Via the _libssh2_debug() macro/function. Pointed out by john in bug report - sftp docs: show macro on macro page, only function on function page The individual man pages for macros now show the full convenience macro as defined, and then the man page for the actual function only shows the function. - code police: make the code use less than 80 columns - libssh2_channel_write_ex: remove macros, added wording on buffer size - libssh2_sftp_write: document buffer size and changed some ordering - libssh2_channel_write_stderr: show how the macro is defined - libssh2_channel_write: show how the macro is defined - SFTP: limit write() to not produce overly large packets sftp_write() now limits how much data it gets at a time even more than before. Since this function creates a complete outgoing packet based on what gets passed to it, it is crucial that it doesn't create too large packets. With this method, there's also no longer any problem to use very large buffers in your application and feed that to libssh2. I've done numerous tests now with uploading data over SFTP using 100K buffers and I've had no problems with that. - scp_write_nonblock: add transfer time info Using the same timing logic and output format as sftp_write_nonblock allows us to very easily run benchmarks on SCP vs SFTP uploads using libssh2. - sftp_write_nonblock: select() on socket, use *BIG* buffer, time transfer The select() is just to make it nicer so that it doesn't crazy-loop on EAGAIN. The buffer size thing is mostly to verify that this really work as supposed. Transfer timing is just a minor thing, but it can just as well be there and help us time and work on performance easier using out of the box examples. - agent: use _libssh2_error() when returning errors As pointed out in bug report #173, this module basically never used _libssh2_error() which made it work inconstently with other parts of the libssh2 code base. This is my first take at making this code more in line with the rest. - inputchecks: make lots of API functions check for NULL pointers If an application accidentally provides a NULL handle pointer to the channel or sftp public functions, they now return an error instead of segfaulting. - libssh2_channel_eof: clarify that it returns negative on errors - SFTP: keep the sftp error code as 32 bit 'last_errno' holds to the error code from the SFTP protocol and since that is 32 bits on the wire there's no point in using a long for this internally which is larger on some platforms. - agent: make the code better deal with unexpected code flows agent->ops gets initialized by the libssh2_agent_connect() call but we need to make sure that we don't segfault even if a bad sequence of function calls is used. Alexander Lamaison (10 Jun 2010) - Better handling of invalid key files. Passing an invalid public key to libssh2_userauth_publickey_fromfile_ex triggered an assertion. Replaced this with a runtime check that rejects obviously invalid key data. Daniel Stenberg (10 Jun 2010) - version: we start working on 1.2.7 now Version 1.2.6 (10 Jun 2010) Daniel Stenberg (10 Jun 2010) - NEWS: add the 1.2.6 release details - RELEASE-NOTES: 1.2.6 details added Guenter Knauf (10 Jun 2010) - fixed libssh2.dsw to use the generated libssh2.dsp; removed old *.dsp files. - moved MSVC strdup define to libssh2_config.h which we include already. - added missing source files to src/NMakefile. Daniel Stenberg (8 Jun 2010) - libssh2_poll: refer to poll(3) and select(3) instead - example: fix strdup() for MSVC compiles MSVC has a _strdup() that we better use. This was reported in bug - SFTP: fail init SFTP if session isn't authenticated Alexander Lamaison filed bug #172 (http://trac.libssh2.org/ticket/172), and pointed out that SFTP init would do bad if the session isn't yet authenticated at the time of the call, so we now check for this situation and returns an error if detected. Calling sftp_init() at this point is bad usage to start with. - direct_tcpip: bring back inclusion of libssh2_config.h In order to increase portability of this example, I'm bringing the inclusion of libssh2_config.h back, and I also added an require that header for this example to compile. I also made all code lines fit within 80 columns. Guenter Knauf (3 Jun 2010) - cast away a warning. - moved CRT_SECURE_NO_DEPRECATE define up so its defined before the winsock headers are included. - fixed platform detection for MingW32 test makefile. - MingW32 has gettimeofday() implemented, so proper ifdef this function here. - removed MSVC ifdef since seems we can use __int64 still with latest headers. - changed copyright notice for MinW32 and NetWare binaries. - cleaned up MSVC ifdefs which where spreaded over 3 places. - added uint8_t typedef for NetWare CLIB platform. - if the function declaration gets changed the header should be changed too. - this is MSVC specific and doesnt apply for all Win32 compilers; the uint8_t typedef clashes with MingW32 headers. - updated MingW32 makefiles for latest dependency lib versions. - updated NetWare makefiles for latest dependency lib versions. Dan Fandrich (30 May 2010) - Fixed compiling with libgcrypt A change of parameter types from unsigned long to size_t was missed in the prototype in libgcrypt.h Daniel Stenberg (28 May 2010) - statvfs: use libssh2_sftp_statvfs only, no "_ex" As the long-term goal is to get rid of the extensive set of macros from the API we can just as well start small by not adding new macros when we add new functions. Therefore we let the function be libssh2_sftp_statvfs() plainly without using an _ex suffix. I also made it use size_t instead of unsigned int for the string length as that too is a long-term goal for the API. - [Grubsky Grigory brought this change] DSP: output lib name typo - [Grubsky Grigory brought this change] win32: provide a uint8_t typedef for better building on windows - agent: win32: fix bad _libssh2_store_str call As pointed out by Grubsky Grigory , I made a mistake when I added the _libssh2_store_str() call before and I made a slightly different patch than what he suggested. Based purely on taste. Peter Stuge (24 May 2010) - [Joey Degges brought this change] Add libssh2_sftp_statvfs() and libssh2_sftp_fstatvfs() These can be used to get file system statistics from servers that support the statvfs@openssh.com and fstatvfs@openssh.com extensions. Alexander Lamaison (22 May 2010) - [Jose Baars brought this change] VMS specific: make sure final release can be installed over daily build - [Jose Baars brought this change] VMS: small improvement to the man2help utilities Peter Stuge (22 May 2010) - [Joey Degges brought this change] libssh2_exit and libssh2_sftp_readdir man page fixes Daniel Stenberg (21 May 2010) - spelling: s/sue/use Alexander Lamaison (21 May 2010) - Change magic port number for generic knownhost check. libssh2_knownhost_checkp took 0 as a magic port number that indicated a 'generic' check should be performed. However, 0 is a valid port number in its own right so this commit changes the magic value to any negative int. Mikhail Gusarov (5 May 2010) - Add re-discovered copyright holders to COPYING - Restoring copyright statements from pre-git era Eli Fant has contributed fragmenting SFTP requests - Restoring my copyright statements from pre-git era keyboard_interactive, 'exit-status' information packet, non-atomic read/write under FreeBSD, multi-channel operation bugfixes. Daniel Stenberg (3 May 2010) - pedantic: make the code C90 clean Peter Stuge (3 May 2010) - Do proper keyboard-interactive user dialog in the sftp.c example Daniel Stenberg (3 May 2010) - added to tarball: libssh2_knownhost_checkp.3 - knownhost: support [host]:port in knownhost file OpenSSH has ways to add hosts to the knownhosts file that include a specific port number which makes the key associated with only that specific host+port pair. libssh2 previously did not support this, and I was forced to add a new function to the API to properly expose this ability to applications: libssh2_knownhost_checkp() To *add* such hosts to the knownhosts file, you make sure to pass on the host name in that manner to the libssh2_knownhost_addc() function. - init/exit: mention these were added in 1.2.5 - libssh2_knownhost_check docs: correct the prototype - examples: avoid use of uninitialized variable 'sock' - KEX: stop pretending we negotiate language There was some stub-like parts of an implementation for implementing kex language negotiation that caused clang-analyzer to warn and as it did nothing I've now removed the dead code. - Uninitialized argument - sftpdir: removed dead assignment - Makefile.am: include the VMS-specific config header as well - [Jose Baars brought this change] Add VMS specific libssh2_config.h - fix Value stored to 's' is never read warning and moved variable declaration of s to be more local - kexinit: simplify the code and avoid scan-build warning Previously it would say "Value stored to 's' is never read" due fourth increment of 's'. Alexander Lamaison (28 Apr 2010) - Removed unecessary brackets. - Changed sftp_attrsize macro to a static function. Daniel Stenberg (28 Apr 2010) - release: include the VMS-specific files - sftp_attrsize: protect the macro argument with proper parentheses - ssh2_agent: avoid using 'session' uninitialized on failures - examples: remove assignments of variable rc that's never used - publickey_init: remove useless variable increment - hostkey_method_ssh_rsa_init: remove useless variable increment - packet_x11_open: removed useless variable increment and made the declaration of a variable more local - packet_queue_listener: removed useless variable increment and made the declaration of a variable more local - sftp_read: move a read_responses array to where its used I find that this increases readability since the array is used only in the function call just immediately below and nowhere else. - sftp_readdir: turn a small array static const and move it - sftp_attrsize: converted function to a macro This way, the macro can evaluate a static number at compile time for two out of four uses, and it probably runs faster for the other two cases too. - sftp_open: deal with short channel_write calls This was an old TODO that just wasn't done before. If channel_write returns short, that is not an error. - sftp_open: clean up, better check of input data The clang-analyzer report made it look into this function and I've went through it to remove a potential use of an uninitialized variable and I also added some validation of input data received from the server. In general, lots of more code in this file need to validate the input before assuming it is correct: there are servers out there that have bugs or just have another idea of how to do the SFTP protocol. - bugfix: avoid using the socket if it failed to create one - bugfix: potential use of NULL pointer - libssh2_userauth_password_ex: clarify errors somewhat The errors mentioned in this man page are possible return codes but not necessarily the only return codes that this can return. Also reformatted the typ prototypes somewhat. - examples: fixed and made them more similar The channel read/write functions can return 0 in legitimate cases without it being an error, and we need to loop properly if they return short. - [Jose Baars brought this change] VMS port of libssh2; changes in the libssh2 common code - Makefile: added the two news headers userauth.h and session.h - cleanup: prefer the internal functions To get the blocking vs non-blocking to work as smooth as possible and behave better internally, we avoid using the external interfaces when calling functions internally. Renamed a few internal functions to use _libssh2 prefix when not being private within a file, and removed the libssh2_ for one that was private within the file. - session_free: remove dead code - libssh2_publickey_init: fixed to work better non-blocking This was triggered by a clang-analyzer complaint that turned out to be valid, and it made me dig deeper and fix some generic non- blocking problems I disovered in the code. While cleaning this up, I moved session-specific stuff over to a new session.h header from the libssh2_priv.h header. - channel: reduce duplicated free and returns Simplified the code by trying to free data and return on a single spot. - channel: make variables more local By making 'data' and 'data_len' more local in several places in this file it will be easier to spot how they are used and we'll get less risks to accidentally do bad things with them. Mikhail Gusarov (24 Apr 2010) - Fix typos in manpages, catched by Lintian Daniel Stenberg (24 Apr 2010) - channel_request_pty: simplify the code clang-analyzer pointed out how 'data' could be accessed as a NULL pointer if the wrong state was set, and while I don't see that happen in real-life the code flow is easier to read and follow by moving the LIBSSH2_FREE() call into the block that is supposed to deal with the data pointer anyway. - libssh2_channel_process_startup: simplify the code clang-analyzer pointed out how 'data' could be accessed as a NULL pointer if the wrong state was set, and while I don't see that happen in real-life the code flow is easier to read and follow by moving the LIBSSH2_FREE() call into the block that is supposed to deal with the data pointer anyway. - sftp_close_handle: add precation to not access NULL pointer clang-analyzer pointed this out as a "Pass-by-value argument in function call is undefined" but while I can't see exactly how this can ever happen in reality I think a little check for safety isn't such a bad thing here. - scp_write_nonblock: Value stored to 'nread' is never read - scp_write: Value stored to 'ptr' is never read - scp_write_nonblock: Value stored to 'ptr' is never read - sftp_mkdir: less silly output but show failures - [Jose Baars brought this change] VMS port of libssh2 including VMS specific build procedures - two variable types changes, made lines less than 80 columns The two variable type changes are only to match type variable fields actually read from the binary protocol. - remove check for negative padding_length It was silly, since it is read as an unsigned char... - hostkey_method_ssh_dss_init: Value stored to 's' is never read - libssh2_banner_set: avoid unnecessary increment and explain code - agent_transact_unix: remove unused variable - remove two unnecessary increments - more code converted to use _libssh2_store_*() - libssh2_publickey_list_fetch: removed unused variables - libssh2_publickey_init: remove unused variables - libssh2_scp_send64: added to API to provide large file transfers The previously existing libssh2_scp_send_ex() function has no way to send files that are larger than 'size_t' which on 32bit systems mean 4GB. This new API uses a libssh2_int64_t type and should thus on most modern systems be able to send enormous files. - sftp_init: remove unused variables and assignments - libssh2_knownhost_check: Value stored to 'keylen' is never read - hostkey: fix compiler warning - remove unused variable - data types: convert more to use size_t and uint32_t - channel: variable type cleanups - cleanups: better binary packet gen, size_t fixes and PACKET_* removal I'll introduce a new internal function set named _libssh2_store_u32 _libssh2_store_u64 _libssh2_store_str That can be used all through the library to build binary outgoing packets. Using these instead of the current approach removes hundreds of lines from the library while at the same time greatly enhances readability. I've not yet fully converted everything to use these functions. I've converted LOTS of 'unsigned long' to 'size_t' where data/string lengths are dealt with internally. This is The Right Thing and it will help us make the transition to our size_t-polished API later on as well. I'm removing the PACKET_* error codes. They were originally introduced as a set of separate error codes from the transport layer, but having its own set of errors turned out to be very awkward and they were then converted into a set of #defines that simply maps them to the global libssh2 error codes instead. Now, I'l take the next logical step and simply replace the PACKET_* defines with the actual LIBSSH2_ERROR_* defines. It will increase readability and decrease confusion. I also separated packet stuff into its own packet.h header file. - clarified the return code - rename libssh2_error to the correct _libssh2_error We reserve ^libssh2_ for public symbols and we use _libssh2 as prefix for internal ones. I fixed the intendation of all these edits with emacs afterwards, which then changed it slightly more than just _libssh2_error() expressions but I didn't see any obvious problems. - data type cleanup: made lots of code use size_t etc A lot of code used 'unsigned long' and the likes when it should rather just use plain 'int' or use size_t for data lengths. - wait_socket: make c89 compliant and use two fd_sets for select() - sftp_readdir: always zero terminate, detail the return code I also added a description for the 'longentry' field which was previously undocumented! - sftp_readdir: simplified and bugfixed This function no longer has any special purpose code for the single entry case, as it was pointless. The previous code would overflow the buffers with an off-by-one in case the file name or longentry data fields received from the server were exactly as long as the buffer provided to libssh2_sftp_readdir_ex. We now make sure that libssh2_sftp_readdir_ex() ALWAYS zero terminate the buffers it fills in. The function no longer calls the libssh2_* function again, but properly uses the internal sftp_* instead. - channel/transport: we now drain the outgoing send buffer when we ignore EAGAIN When we ignore the EAGAIN from the transport layer within channel_write, we now drain the outgoing transport layer buffer so that remainders in that won't cause any problems in the next invoke of _libssh2_transport_write() - channel_write: if data has been sent, don't return EAGAIN When sending data in a loop, we must not return EAGAIN if we managed to send data in an earlier round. This was reported in bug #126 => http://libssh2.stuge.se/ticket/126 Simon Josefsson (14 Apr 2010) - Fix OpenSSL AES-128-CTR detection. Patch from Paul Howarth . Daniel Stenberg (13 Apr 2010) - version in header file now says 1.2.6-DEV - 1.2.6: clean the RELEASE-NOTES for next release round - NEWS: add the stuff from the version 1.2.5 RELEASE-NOTES Version 1.2.5 (13 Apr 2010) Daniel Stenberg (13 Apr 2010) - channel_close: no longer wait for the SSH_MSG_CHANNEL_CLOSE message As the packet may simply not arrive we cannot have the close function wait for it unconditionally. - less code duplication in the poll vs select code flows libssh2_keepalive_send and libssh2_session_block_directions are now used outside of the #ifdef blocks. - make it C90 compliant - updated with all changes and bugs since 1.2.4 - Added LIBSSH2_SFTP_S_IS***() macros and updated docs libssh2_sftp_fstat_ex.3 is now extended quite a lot to describe a lot of the struct and the bits it uses and how to test for them. - sftp_init() deal with _libssh2_channel_write() returns short When _libssh2_channel_write() is asked to send off 9 bytes, the code needs to deal with the situation where less than 9 bytes were sent off and prepare to send the remaining piece at a later time. - handle a NULL password as if it was "" libssh2_userauth_publickey_fromfile_ex() takes a "passphrase" but didn't deal with it being set to NULL. - Reduce used window sizes by factor 10 As reported in bug report #166 http://libssh2.stuge.se/ticket/166 by 'ptjm', the maximum window size must be less crazy for libssh2 to do better with more server implementations. I did not do any testing to see how this changes raw SCP performance, but the maximum window size is still almost 4MB. This also has the upside that libssh2 will use less memory. Peter Stuge (28 Mar 2010) - Correctly clear blocking flag after sending multipart packet commit 7317edab61d2179febc38a2c2c4da0b951d74cbc cleared the outbound blocking bit when send_existing() returned PACKET_NONE and *ret=0, as opposed to before even calling send_existing(), but because *ret=1 when sending parts 2..n of an existing packet, the bit would only be cleared when calling libssh2_transport_write() for a new packet. Clear the direction flag after the final part of a packet has been sent. Daniel Stenberg (24 Mar 2010) - Added man page for libssh2_knownhost_addc() Added mention in libssh2_knownhost_add() docs that libssh2_knownhost_addc() is the preferred function now. - at next soname bump remove libssh2_knownhost_add() - ignore TAGS ("make tags" makes them) - fix memory leak we must not assign the pointer a NULL since it keeps allocated data and at least parts of an error string - fixed the pattern for avoiding the poll check added some comments about known problems with poll on darwin - avoid checking for poll on some systems darwin and interix are known to have broken poll implementations so we skip the check on those and thus have them use select unconditionally - ignore libssh2.dsp Simon Josefsson (23 Mar 2010) - Fix logic in "on-the-fly" crypto init. - Make sure keepalive is working even when poll is used. - [Paul Querna brought this change] Use poll when available on blocking API. Signed-off-by: Simon Josefsson Peter Stuge (20 Mar 2010) - Fix speling Daniel Stenberg (19 Mar 2010) - fix NULL dereference when window adjusting a non-existing channel Suyog Jadhav pointed out that when receiving a window adjust to a channel not found, the code would reference a NULL pointer. Now it will instead output a message about that fact. Simon Josefsson (19 Mar 2010) - Fix build problem. - Eat our own dog food, call libssh2_init and libssh2_exit in the examples. - Fix init/exit logic. Add self-test of it. Daniel Stenberg (19 Mar 2010) - fix typo Simon Josefsson (19 Mar 2010) - Add man page for libssh2_init and libssh2_exit. Fix libssh2_exit prototype. - Shorten constant a bit. More documentation. - Fix namespace pollution. - Add global init/exit points, to do crypto initialization in one place. By Lars Nordin. Daniel Stenberg (14 Mar 2010) - libssh2 is released under the Modifed BSD license, not GPL Alexander Lamaison (14 Mar 2010) - Add libssh2_knownhost_addc to handle comments. Comments in known_hosts file were not handle properly. They were parsed as part of the key causing key matching to return a mismatch if the entry had a comment. This adds a new API function that takes an optional comment and changes libssh2_knownhost_readline to parse the comment as pass it to the new function. Fixes #164. - Fix gettimeofday to compile with Visual C++ 6. Reported by Steven Van Ingelgem. Simon Josefsson (10 Mar 2010) - Add. - keepalive.c: Fix libssh2_error usage. - Fix typo in last commit. - Tidy up build option notice. - Add entry about keep alive stuff. - Add keep-alive support. Alexander Lamaison (7 Mar 2010) - Untabify. - Fix memory leak in libssh2_knownhost_add. Daniel Stenberg (6 Mar 2010) - change 'int' to 'libssh2_socket_t' in the public API for sockets - reduce code duplication and return underlying error better - acknowledge when _libssh2_packet_requirev() returns error when _libssh2_packet_requirev() returns an error when waiting for SSH_MSG_USERAUTH_SUCCESS or SSH_MSG_USERAUTH_FAILURE, it is an error and it should be treated as such - wrap long lines - polished the phrasing in two error strings - silence picky compiler warnings - silence picky compiler warnings - removed libssh2_error()'s forth argument libssh2_error() no longer allocates a string and only accepts a const error string. I also made a lot of functions use the construct of return libssh2_error(...) instead of having one call to libssh2_error() and then a separate return call. In several of those cases I then also changed the former -1 return code to a more detailed one - something that I think will not change behaviors anywhere but it's worth keeping an eye open for any such. - repaired --enable-debug Simon Josefsson (1 Mar 2010) - Make ./configure output a summary of build options. Daniel Stenberg (1 Mar 2010) - let the err_msg in the session struct be const too Simon Josefsson (1 Mar 2010) - Revert #ifdef change that pulled in AES-CTR code when explicitly disabled. Daniel Stenberg (1 Mar 2010) - fix #ifdefs - make function match the new proto Simon Josefsson (1 Mar 2010) - Improve AES-CTR check. Daniel Stenberg (1 Mar 2010) - use const to silence a bazillion warnings Simon Josefsson (1 Mar 2010) - Use AES-CTR from OpenSSL when available. Reported by Lars Nordin . - Make it possible to disable DSA. Patch from Lars Nordin . Peter Stuge (1 Mar 2010) - Send and receive channel EOF before sending SSH_MSG_CHANNEL_CLOSE Sending SSH_MSG_CHANNEL_CLOSE without channel EOF is explicitly allowed in RFC 4254, but some non-conforming servers will hang or time out when the channel is closed before EOF. Other common clients send and receive EOF before closing, there are no drawbacks, and some servers need it to work correctly. Alexander Lamaison (26 Feb 2010) - Style improvements to knownhost error handling. Made improvements as suggested by Peter Stuge: http://www.libssh2.org/mail/libssh2-devel-archive-2010-02/0161.shtml. - Call libssh2_error for every knownhost API failure. The libssh2 API calls should set the last error code and a message when returning a failure by calling libssh2_error. This changeset adds these calls to the libssh2_knownhost_* API as well as libssh2_base64_decode. This change also makes libssh2_error into a function rather than a macro. Its implementation is moved to misc.c. This function returns the error code passed to it allowing callers to return the error value directly without duplicating the error code. - Fix LIBSSH2_ALLOC checks. These appear to be cut-and paste errors where the wrong variable is checked for NULLness after calling LIBSSH2_ALLOC. Simon Josefsson (23 Feb 2010) - Silence compiler warning. - Make it portable; test uses = for string comparison (not ==). Indent. Alexander Lamaison (22 Feb 2010) - libssh2_knownhost_del: fix write to freed memory. When removing a known host, libssh2_knownhost_del would remove the node from the linked list, free its memory and then overwrite the struct parameter (which indicated which node to remove) with 0. However, this struct is actually allocated within the just-freed node meaning we're writing to freed memory. This made Windows very upset. The fix is simply to overwrite the struct first before freeing the memory. Daniel Stenberg (21 Feb 2010) - show more verbose error when SCP send fails - libssh2_socket_t is done, a library-free function is needed - clarify that this frees all data associated with a session - improved error handling - add missing libssh2_error() calls To make sure the public API is functional and that the BLOCK_ADJUST_ERRNO() macro works correctly we MUST make sure to call libssh2_error() when we return errors. - fix memory leak in userauth_keyboard_interactive() Mr anonymous in bug #125 pointed out that the userauth_keyboard_interactive() function does in fact assign the same pointer a second time to a new allocated buffer without properly freeing the previous one, which caused a memory leak. - added missing error codes To allow the libssh2_session_last_error() function to work as documented, userauth_password() now better makes sure to call libssh2_error() everywhere before it returns error. Pointed out by mr anonymous in bug #128 Peter Stuge (16 Feb 2010) - Fix resource and memory leaks in examples as reported by cppcheck Thanks to Ettl Martin for the report and patch. This fixes #132 Daniel Stenberg (15 Feb 2010) - mention the new man pages for macros - added man pages for API macros all #defined macros in the public headers are considered to be part of the API and I've generated individual man pages for each of them to A) make it easier to figure out what each function/macro actually is for so that automated lookups work better and for B) make sure we have all public functions document (both macros and functions) to make it easier for us to work away from all the macros in a future release. - Committed the patch by Yoichi Iwaki in bug #2929647 Committed the patch by Yoichi Iwaki in bug #2929647, which fixed a memory leak when an 'outbuf' was still allocated when a session was freed. - free "outbuf" when killing a session Fix memoary leak: if there was an "output" still allocated when a session was torn down it needs to be freed in session_free() Patch by Yoichi Iwaki in bug #2929647 - the working version name is now 1.2.5_DEV Version 1.2.4 (13 Feb 2010) Daniel Stenberg (13 Feb 2010) - updated info for 1.2.4 Dan Fandrich (10 Feb 2010) - Allow compiling with OpenSSL when AES isn't available. Peter Stuge (9 Feb 2010) - [Dave McCaldon brought this change] Fix Tru64 socklen_t compile issue with example/direct_tcpip.c Building libssh2-1.2.3 on Tru64 fails at line 48 and 166 because socklen_t isn't defined on Tru64 unless _POSIX_PII_SOCKET is defined. This patch updates configure.ac to add -D_POSIX_PII_SOCKET when building on Tru64 platform(s). - [Dave McCaldon brought this change] Resolve compile issues on Solaris x64 and UltraSPARC Solaris builds of libssh2-1.2.3 failed on both x64 and UltraSPARC platforms because of two problems: 1) src/agent.c:145 sun is a reserved word when using the SUNWspro compiler 2) example/direct_tcpip.c:84 INADDR_NONE is not defined Daniel Stenberg (3 Feb 2010) - towards 1.2.4 now Version 1.2.3 (3 Feb 2010) Daniel Stenberg (3 Feb 2010) - Version 1.2.3 (February 3, 2010) - fix building out of source tree by proving better include path when building out of source tree, we provide -I$(top_builddir)/example since the libssh2_config.h gets generated in that dir Peter Stuge (1 Feb 2010) - [Sofian Brabez brought this change] Replace : in hexdump with " " (two spaces) - Detect when the forwarded connection is closed in example/direct_tcpip.c - Fix example/direct_tcpip.c to work also on WIN32 read() and write() are no good for WIN32 sockets, use recv() and send(). - Ignore libssh2_config.h.in and stamp-h2 in example/ and remove .cvsignore - Simplify WIN32 ifdefs in example/direct_tcpip.c to allow standalone compile - Always #define INVALID_SOCKET -1 in libssh2_priv.h when not on win32 Fix broken builds since commit abd9bd0bbe631efeada1f54552c70b54e1c490c1 for all non-win32 platforms. - Include hmac-md5 and hmac-md5-96 only if crypto backend supports MD5 - Use LIBSSH2_HOSTKEY_HASH_SHA1 instead of _MD5 in examples and tests MD5 support is optional and may not always be available, while SHA1 is both required and recommended. - Update mailing list address in configure.ac to @cool.haxx.se - Make example/direct_tcpip.c compile for win32 One warning from FD_SET() remains, it is also in some other examples. - Correctly check for an invalid socket in session_startup() - Small documentation fix after Dave's _USERAUTH_FAILURE improvement - [Dave McCaldon brought this change] Handle SSH_MSG_USERAUTH_FAILURE for password and kbd-int authentication Neither libssh2_userauth_password_ex() nor libssh2_userauth_keyboard_interactive_ex() would return a login failure error if the server responded with a SSH_MSG_USERAUTH_FAILURE, instead you would see whatever previous error had occurred, typically LIBSSH2_ERROR_EAGAIN. This patch changes error code -18 to LIBSSH2_ERROR_AUTHENTICATION_FAILED and makes LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED an alias for LIBSSH2_ERROR_AUTHENTICATION_FAILED. In addition, new logic in userauth_password() properly handles SSH_MSG_USERAUTH_FAILURE and both this function and userauth_keyboard_interactive() now properly return LIBSSH2_ERROR_AUTHENTICATION_FAILED. Simon Josefsson (28 Jan 2010) - Fix. - Also deal with GLOBAL_REQUEST keep-alives. - Make OpenSSH-style keepalive work against libssh2 clients. Daniel Stenberg (27 Jan 2010) - clarified Peter Stuge (26 Jan 2010) - [Dave McCaldon brought this change] Fix trace context lookup in libssh2_debug() The trace context is actually a bitmask so that tracing output can be controlled by setting a bitmask using libssh2_trace(). However, the logic in libssh2_debug() that converted the context to a string was using the context value as an array index. Because the code used a bounds check on the array, there was never a danger of a crash, but you would certainly either get the wrong string, or "unknown". This patch adds a lookup that iterates over the context strings and uses it's index to check for the corresponding bit in the context. - Fix typo in RELEASE-NOTES Daniel Stenberg (20 Jan 2010) - updated for 1.2.3 with all the stuff I found in the log - ignore more generated files - [Dave McCaldon brought this change] Pass user context through libssh2_trace_sethandler() to callback The libssh2_trace_sethandler() call allows the user to handle the output of libssh2 rather than having it written to stderr. This patch updates libssh2_trace_sethandler() to allow a user-defined void* context value to be passed back to the output handler. - [Dave McCaldon brought this change] Add libssh2_trace_sethandler() to the API (even more) - [Dave McCaldon brought this change] Add libssh2_trace_sethandler() to the API - cleanup includes We now produce a local libssh2_config.h file in this dir for the examples to use so I cleaned up the include path at the same time. - generate a libssh2_config.h in the example dir buildconf copies the template to example/ and configure makes sure to generate a proper file from it and the direct_tcpip.c example is the first one to use it - to make sure it builds fine on more paltforms Simon Josefsson (13 Jan 2010) - Remove redundant #includes and reorder sys/types.h include. Daniel Stenberg (10 Jan 2010) - avoid a free(NULL) Simon Josefsson (7 Jan 2010) - Make it simpler to get more debug info. Daiki Ueno (1 Jan 2010) - Simplify the commit 63457dfa using type cast from size_t * to ulong *. Alexander Lamaison (30 Dec 2009) - Fixed memory leak in userauth_publickey(). userauth_publickey_fromfile() reads the key from a file using file_read_publickey() which returns two allocated strings, the decoded key and the key method (such as "ssh-dss"). The latter can be derived from the former but returning both avoids a later allocation while doing so. Older versions of userauth_publickey_fromfile() used this method string directly but when userauth_publickey() was factored out of userauth_publickey_fromfile() it derived the method from the key itself. This resulted in the method being allocated twice. This fix, which maintains the optimisation that avoids an extra allocation, changes userauth_publickey() so it doesn't allocate and derive the method when userauth_pblc_method already has a value. Signed-off-by: Alexander Lamaison Daiki Ueno (25 Dec 2009) - Fix the return value description of libssh2_knownhost_free(). - Fix compiler warnings for size_t pointers on 32-bit Windows. - Define INVALID_SOCKET and use it instead of SOCKET_BAD. Revert the part of previous commit that defines SOCKET_BAD library wide. - Use libssh2_socket_t in the ssh-agent stuff. Define a portability macro SOCKET_BAD which means "invalid socket". - Mark/unmark connection to Pageant is open/close. - Add test to check if the socket is connected. Peter Stuge (24 Dec 2009) - Add libssh2.pc to top-level .gitignore - Fix publickey authentication regression Commit 70b199f47659a74b8778c528beccf893843e5ecb introduced a parsing bug in file_read_publickey() which made the algorithm name contain an extra trailing space character, breaking all publickey authentication. - Add a direct-tcpip example which shows local port forwarding - Add session parameter and LIBSSH2_TRACE_SOCKET to libssh2_trace(3) man page - Add TODO: Expose error messages sent by the server Daiki Ueno (23 Dec 2009) - Fix doc comments. - Add man pages for ssh-agent API. - Don't request userauthlist after authentication. Simon Josefsson (21 Dec 2009) - Add. - [Daiki Ueno brought this change] Add an example to use ssh-agent API. Signed-off-by: Simon Josefsson - [Daiki Ueno brought this change] Add ssh-agent API. Signed-off-by: Simon Josefsson - [Daiki Ueno brought this change] Add callback-based API for publickey auth. Signed-off-by: Simon Josefsson - Move examples from example/simple to example/. - Move examples from example/simple to example/. Daniel Stenberg (17 Dec 2009) - _libssh2_list_insert() fixed to work While this is code not currently in use, it is part of the generic linked list code and since I found the error I thought I'd better fix it since we might bring in this function into the code one day. Simon Josefsson (16 Dec 2009) - Silence compiler warnings. Based on patch by Kamil Dudka in . - [Kamil Dudka brought this change] libgcrypt: simplify code of _libssh2_dsa_sha1_sign Signed-off-by: Simon Josefsson - [Kamil Dudka brought this change] libgcrypt: follow-up for ssh-dss padding fix Signed-off-by: Simon Josefsson Dan Fandrich (15 Dec 2009) - Check for the right environment variable in the test app Simon Josefsson (14 Dec 2009) - Silence warning about unused function parameter. Reported by Steven Van Ingelgem . Daniel Stenberg (10 Dec 2009) - avoid returning data to memory already freed In case of failure we must make sure that the data we return doesn't point to a memory area already freed. Reported anonymously in the bug report #2910103. Peter Stuge (8 Dec 2009) - Use LIBSSH2_TRACE_* internally and remove redundant LIBSSH2_DBG_* - Add LIBSSH2_TRACE_SOCKET context for tracing send() and recv() Helpful in debugging the -39 errors. - Another transport layer fix for bogus -39 (LIBSSH2_ERROR_BAD_USE) errors Commit 683aa0f6b52fb1014873c961709102b5006372fc made send_existing() send more than just the second part of a packet when the kernel did not accept the full packet, but the function still overlooked the SSH protocol overhead in each packet, often 48 bytes. If only the last few bytes of a packet remained, then the packet would erroneously be considered completely sent, and the next call to write more data in the session would return a -39 error. Daniel Stenberg (6 Dec 2009) - move local variable to be more localized - fixed some indent mistakes Peter Stuge (6 Dec 2009) - Fix padding in ssh-dss signature blob encoding DSA signatures consist of two 160-bit integers called r and s. In ssh-dss signature blobs r and s are stored directly after each other in binary representation, making up a 320-bit (40 byte) string. (See RFC4253 p14.) The crypto wrappers in libssh2 would either pack r and s incorrectly, or fail, when at least one integer was small enough to be stored in 19 bytes or less. The patch ensures that r and s are always stored as two 160 bit numbers. - Don't always clear write direction blocking flag When libssh2_transport_write() is called to continue sending a partially sent packet the write direction flag must not be cleared until the previous packet has been completely sent, or the app would hang if the packet still isn't sent completely, since select() gets called by the internal blocking emulation layer in libssh2 but would then not be watching the socket for writability. Clear the flag only once processing of previous packet data is complete and a new packet is about to be prepared. Alexander Lamaison (24 Nov 2009) - Detabify. - [Daniel Stenberg brought this change] Fixed memory leak in sftp_fstat(). Simon Josefsson (17 Nov 2009) - Mark date of 1.2.2 release. - Merge branch 'master' of ssh://git.stuge.se/var/lib/git/libssh2 Version 1.2.2 (16 Nov 2009) Daniel Stenberg (16 Nov 2009) - prepared for 1.2.2 Simon Josefsson (16 Nov 2009) - Improve NEWS items. - Support AES-Counter ciphers. - Silence compiler warning. Reported by Steven Van Ingelgem in . - Mention libssh2-style.el. - Use memmove instead of memcpy on overlapping memory areas. Reported by Bob Alexander in . - Add. - Protect against crash on too small SSH_MSG_IGNORE packets. Reported by Bob Alexander in . - add copyright line doc/alt-openldap11/ANNOUNCEMENT000064400000007376152527227020011671 0ustar00A N N O U N C E M E N T -- OpenLDAP 2.4 The OpenLDAP Project is pleased to announce the availability of OpenLDAP Software 2.4, a suite of the Lightweight Directory Access Protocol (v3) servers, clients, utilities, and development tools. This release contains the following major enhancements: * Slapd(8) enhancements - Syncrepl enhancements, including push-mode and Multi-Provider support - Dynamic configuration enhancements, including online schema editing and full access control - Dynamic monitoring enhancements, including cache usage information * New overlays - Attribute value constraints - Dynamic Directory Services (RFC2589) - Reverse Group Membership maintenance (memberof) * Clients and tools - Full support of request/response controls - New ldapexop tool for arbitrary extend operations - Support of DNS SRV records for default server * Significant performance enhancements throughout the client and server code base * Multiple new features in libldap and liblber * Expanded documentation - Function-complete manual pages - Numerous new examples in the Admin Guide This release includes the following major components: * slapd - a stand-alone LDAP directory server * -lldap - a LDAP client library * -llber - a lightweight BER/DER encoding/decoding library * LDIF tools - data conversion tools for use with slapd * LDAP tools - A collection of command line LDAP utilities * Admin Guide, Manual Pages - associated documentation In addition, there are some contributed components: * LDAPC++ - a LDAP C++ SDK * Various slapd modules and slapi plugins ACKNOWLEDGEMENTS OpenLDAP Software is developed by the OpenLDAP Project. The Project consists of a team of volunteers who use the Internet to coordinate their activities. The Project is an organized activity of the OpenLDAP Foundation. OpenLDAP Software is derived from University of Michigan LDAP, release 3.3. AVAILABILITY This software is available under the OpenLDAP Public License, an non-restrictive, "free", open-source license. Download information is available at: http://www.OpenLDAP.org/software/download/ SUPPORT OpenLDAP Software is user supported: http://www.openldap.org/support/ The OpenLDAP Administrator's Guide, which includes quick start instructions, is available at: http://www.openldap.org/doc/admin/ The project maintains a FAQ which you may find useful: http://www.openldap.org/faq/ In addition, there are also a number of discussion lists related to OpenLDAP Software. A list of mailing lists is available at: http://www.OpenLDAP.org/lists/ To report bugs, please use project's Issue Tracking System: http://www.openldap.org/its/ The OpenLDAP home page containing lots of interesting information and online documentation is available at this URL: http://www.OpenLDAP.org/ SUPPORTED PLATFORMS This release has been ported to many UNIX (and UNIX-like) platforms including Darwin, FreeBSD, Linux, NetBSD, OpenBSD and most commercial UNIX systems. The release has also been ported (in part or in whole) to other platforms including Apple MacOS X, IBM zOS, and Microsoft Windows NT/2000/etc. --- OpenLDAP is a registered trademark of the OpenLDAP Foundation. Copyright 1999-2021 The OpenLDAP Foundation, Redwood City, California, USA. All Rights Reserved. Permission to copy and distribute verbatim copies of this document is granted. doc/alt-openldap11/README000064400000006647152527227020010734 0ustar00OpenLDAP 2.4 README For a description of what this distribution contains, see the ANNOUNCEMENT file in this directory. For a description of changes from previous releases, see the CHANGES file in this directory. This is 2.4 release, it includes significant changes from prior releases. REQUIRED SOFTWARE Building OpenLDAP Software requires a number of software packages to be preinstalled. Additional information regarding prerequisite software can be found in the OpenLDAP Administrator's Guide. Base system (libraries and tools): Standard C compiler (required) Cyrus SASL 2.1.21+ (recommended) OpenSSL 0.9.7+ (recommended) Reentrant POSIX REGEX software (required) SLAPD: BDB and HDB backends require Oracle Berkeley DB 4.4 - 4.8, or 5.0 - 5.1. It is highly recommended to apply the patches from Oracle for a given release. CLIENTS/CONTRIB ware: Depends on package. See per package README. MAKING AND INSTALLING THE DISTRIBUTION Please see the INSTALL file for basic instructions. More detailed instructions can be found in the OpenLDAP Administrator's Guide (see DOCUMENTATION section). DOCUMENTATION The OpenLDAP Administrator's Guide is available in the guide.html file in the doc/guide/admin directory. The guide and a number of other documents are available at . The distribution also includes manual pages for most programs and library APIs. See ldap(3) for details. The OpenLDAP website is available and contains the latest LDAP news, releases announcements, pointers to other LDAP resources, etc.. It is located at . The OpenLDAP Software FAQ is available at . SUPPORT / FEEDBACK / PROBLEM REPORTS / DISCUSSIONS OpenLDAP Software is user supported. If you have problems, please review the OpenLDAP FAQ and archives of the OpenLDAP-software and OpenLDAP-bugs mailing lists . If you cannot find the answer, please enquire on the OpenLDAP-software list. Issues, such as bug reports, should be reported using our Issue Tracking System . Do not use this system for software enquiries. Please direct these to an appropriate mailing list. CONTRIBUTING See for information regarding how to contribute code or documentation to the OpenLDAP Project for inclusion in OpenLDAP Software. While you are encouraged to coordinate and discuss the development activities on the mailing list prior to submission, it is noted that contributions must be submitted using the Issue Tracking System to be considered. --- $OpenLDAP$ This work is part of OpenLDAP Software . Copyright 1998-2021 The OpenLDAP Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. A copy of this license is available in the file LICENSE in the top-level directory of the distribution or, alternatively, at . OpenLDAP is a registered trademark of the OpenLDAP Foundation. doc/alt-openldap11/CHANGES000064400000317417152527227020011047 0ustar00OpenLDAP 2.4 Change Log OpenLDAP 2.4.59 Release (2021/06/03) Fixed libldap TLSv1.3 cipher suites with OpenSSL 1.1.1 (ITS#9521) Fixed libldap double free of LDAP_OPT_DEFBASE (ITS#9530) Fixed slapd syncrepl handling of add+delete on single value attr (ITS#9295) Fixed slapd-mdb cursor init check (ITS#9526) Fixed slapd-mdb deletion of context entry (ITS#9531) Fixed slapd-mdb off-by-one affecting search scope (ITS#9557) Fixed slapo-pcache locking during expiration (ITS#9529) Contrib Fixed slapo-autogroup to not thrash thread context (ITS#9494) Documentation ldap_modify(3) - Delete non-existent mod_next parameter (ITS#9559) OpenLDAP 2.4.58 Release (2021/03/16) Fixed slapd validity checks for issuerAndThisUpdateCheck (ITS#9454) Fixed slapd to alloc new conn struct after freeing old one (ITS#9458) Fixed slapd syncrepl to check all contextCSNs (ITS#9282) Fixed slapd-bdb lockdetect config (ITS#9449) OpenLDAP 2.4.57 Release (2021/01/18) Fixed ldapexop to use correct return code (ITS#9417) Fixed slapd to remove asserts in UUIDNormalize (ITS#9391) Fixed slapd to remove assert in csnValidate (ITS#9410) Fixed slapd validity checks for issuerAndThisUpdateCheck (ITS#9411, ITS#9427) Fixed slapd validity checks for serialNumberAndIssuerCheck (ITS#9404, ITS#9424) Fixed slapd AVA sort with invalid RDN (ITS#9412) Fixed slapd ldap_X509dn2bv to check for invalid BER after RDN count (ITS#9423, ITS#9425) Fixed slapd saslauthz to remove asserts in validation (ITS#9406, ITS#9407) Fixed slapd saslauthz to use slap_sl_free on normalized DN (ITS#9409) Fixed slapd saslauthz SEGV in slap_parse_user (ITS#9413) Fixed slapd modrdn memory leak (ITS#9420) Fixed slapd double-free in vrfilter (ITS#9408) Fixed slapd cancel operation to correctly terminate (ITS#9428) Fixed slapd-ldap fix binds on retry with closed connection (ITS#9400) Fixed slapo-syncprov to ignore duplicate sessionlog entries (ITS#9394) OpenLDAP 2.4.56 Release (2020/11/10) Fixed slapd to remove assert in certificateListValidate (ITS#9383) Fixed slapd to remove assert in csnNormalize23 (ITS#9384) Fixed slapd to better parse ldapi listener URIs (ITS#9379) OpenLDAP 2.4.55 Release (2020/10/26) Fixed slapd normalization handling with modrdn (ITS#9370) Fixed slapd-meta to check ldap_install_tls return code (ITS#9366) Contrib Fixed nssov misplaced semicolon (ITS#8731, ITS#9368) OpenLDAP 2.4.54 Release (2020/10/12) Fixed slapd delta-syncrepl to ignore delete ops on deleted entry (ITS#9342) Fixed slapd delta-syncrepl to be fully serialized (ITS#9330) Fixed slapd delta-syncrepl MOD on zero-length context entry (ITS#9352) Fixed slapd syncrepl to be fully serialized (ITS#8102) Fixed slapd syncrepl to call check_syncprov on fresh consumer (ITS#9345) Fixed slapd syncrepl to propagate errors from overlay_entry_get_ov (ITS#9355) Fixed slapd syncrepl to not create empty ADD ops (ITS#9359) Fixed slapd syncrepl replace usage on single valued attrs (ITS#9295) Fixed slapd-monitor fix monitor_back_register_database for empty suffix DB (ITS#9353) Fixed slapo-accesslog normalizer for reqStart (ITS#9358) Fixed slapo-accesslog to not generate new contextCSN on purge (ITS#9361) Fixed slapo-syncprov contextCSN generation with empty suffix (ITS#9015) Fixed slapo-syncprov sessionlog to use a TAVL tree (ITS#8486) OpenLDAP 2.4.53 Release (2020/09/07) Added slapd syncrepl additional SYNC logging (ITS#9043) Fixed slapd syncrepl segfault on NULL cookie on REFRESH (ITS#9282) Fixed slapd syncrepl to use fresh connection on REFRESH fallback (ITS#9338) Fixed slapo-ppolicy race condition for pwdFailureTime (ITS#9302,ITS#9334) Build Require OpenSSL 1.0.2 or later (ITS#9323) Fixed libldap compilation issue with broken C compilers (ITS#9332) OpenLDAP 2.4.52 Release (2020/08/28) Added libldap LDAP_OPT_X_TLS_REQUIRE_SAN option (ITS#9318) Added libldap OpenSSL support for multiple EECDH curves (ITS#9054) Added slapd OpenSSL support for multiple EECDH curves (ITS#9054) Fixed librewrite malloc/free corruption (ITS#9249) Fixed libldap hang when using UDP and server down (ITS#9328) Fixed slapd syncrepl rare deadlock due to network issues (ITS#9324) Fixed slapd syncrepl regression that could trigger an assert (ITS#9329) Fixed slapd-mdb index error with collapsed range (ITS#9135) OpenLDAP 2.4.51 Release (2020/08/11) Added slapo-ppolicy implement Netscape password policy controls (ITS#9279) Fixed libldap retry loop in ldap_int_tls_connect (ITS#8650) Fixed libldap to use getaddrinfo in ldap_pvt_get_fqdn (ITS#9287) Fixed slapd to enforce singular existence of some overlays (ITS#9309) Fixed slapd syncrepl to not delete non-replicated attrs (ITS#9227) Fixed slapd syncrepl to correctly delete entries on resync (ITS#9282) Fixed slapd syncrepl to use replace on single valued attrs (ITS#9294, ITS#9295) Fixed slapd-perl dynamic config with threaded slapd (ITS#7573) Fixed slapo-ppolicy to expose the ppolicy control (ITS#9285) Fixed slapo-ppolicy race condition for pwdFailureTime (ITS#9302) Fixed slapo-ppolicy so it can only exist once per DB (ITS#9309) Fixed slapo-chain to check referral (ITS#9262) Build Environment Fix test064 so it no longer uses bashisms (ITS#9263) Contrib Fix default prefix value for pw-argon2, pw-pbkdf2 modules (ITS#9248) slapo-allowed - Fix usage of uninitialized variable (ITS#9308) Documentation ldap_parse_result(3) - Document ldap_parse_intermediate (ITS#9271) OpenLDAP 2.4.50 Release (2020/04/28) Fixed client benign typos (ITS#8890) Fixed libldap type cast (ITS#9175) Fixed libldap retry loop in ldap_int_tls_connect (ITS#8650) Fixed libldap_r race on Windows mutex initialization (ITS#9181) Fixed liblunicode memory leak (ITS#9198) Fixed slapd benign typos (ITS#8890) Fixed slapd to limit depth of nested filters (ITS#9202) Fixed slapd-mdb memory leak in dnSuperiorMatch (ITS#9214) Fixed slapo-pcache database initialization (ITS#9182) Fixed slapo-ppolicy callback (ITS#9171) Build Fix olcDatabaseDummy initialization for windows (ITS#7074) Fix detection for ws2tcpip.h for windows (ITS#8383) Fix back-mdb types for windows (ITS#7878) Contrib Update ldapc++ config.guess and config.sub to support newer architectures (ITS#7855) Added pw-argon2 module (ITS#9233, ITS#8575, ITS#9203, ITS#9206) Documentation slapd-ldap(5) - Clarify idassert-authzfrom behavior (ITS#9003) slapd-meta(5) - Remove client-pr option (ITS#8683) slapindex(8) - Fix truncate option information for back-mdb (ITS#9230) OpenLDAP 2.4.49 Release (2020/01/30) Added slapd-monitor database entry count for slapd-mdb (ITS#9154) Fixed client tools to not add controls on cancel/abandon (ITS#9145) Fixed client tools SyncInfo message to be LDIF compliant (ITS#8116) Fixed libldap to correctly free sb (ITS#9081, ITS#8755) Fixed libldap descriptor leak if ldaps fails (ITS#9147) Fixed libldap remove unnecessary global mutex for GnuTLS (ITS#9069) Fixed slapd syntax evaluation of preferredDeliveryMethod (ITS#9067) Fixed slapd to relax domainScope control check (ITS#9100) Fixed slapd to have cleaner error handling during connection setup (ITS#9112) Fixed slapd data check when processing cancel exop (ITS#9124) Fixed slapd attribute description processing (ITS#9128) Fixed slapd-ldap to set oldctrls correctly (ITS#9076) Fixed slapd-mdb to honor unchecked limit with alias deref (ITS#7657) Fixed slapd-mdb missing final commit with slapindex (ITS#9095) Fixed slapd-mdb drop attr mappings added in an aborted txn (ITS#9091) Fixed slapd-mdb nosync FLAG configuration handling (ITS#9150) Fixed slapd-monitor global operation counter reporting (ITS#9119) Fixed slapo-ppolicy when used with slapauth (ITS#8629) Fixed slapo-ppolicy to add a missed normalised copy of pwdChangedTime (ITS#9126) Fixed slapo-syncprov fix sessionlog init (ITS#9146) Fixed slapo-unique loop termination (ITS#9077) Build Environment Fix mkdep to honor TMPDIR if set (ITS#9062) Remove ICU library detection (ITS#9144) Update config.guess and config.sub to support newer architectures (ITS#7855) Disable ITS8521 regression test as it is no longer valid (ITS#9015) Documentation admin24 - Fix inconsistent whitespace in replication section (ITS#9153) admin24 - Fix dmoz URL to point to Curlie (ITS#9289) slapd-config(5)/slapd.conf(5) - Fix missing bold tag for keyword (ITS#9063) slapd-ldap(5) - Document "tls none" option (ITS#9071) slapo-ppolicy(5) - Correctly document pwdGraceAuthnLimit (ITS#9065) OpenLDAP 2.4.48 Release (2019/07/24) Added libldap OpenSSL Elliptic Curve support (ITS#7595) Added libldap Expose OpenLDAP specific interfaces via openldap.h (ITS#8671) Added slapd-monitor support for slapd-mdb (ITS#7770) Fixed liblber leaks (ITS#8727) Fixed liblber with partial flush (ITS#8864) Fixed libldap ASYNC TLS so it works (ITS#8957,ITS#8980) Fixed libldap ASYNC connections with Solaris 10 (ITS#8968) Fixed libldap with SASL_NOCANON=on and ldapi connections (ITS#7585) Fixed libldap to be able to unset syncrepl TLS options (ITS#7042) Fixed libldap race condition in ldap_int_initialize (ITS#7996, ITS#8450) Fixed libldap return code in ldap_create_assertion_control_value (ITS#8674) Fixed libldap to correctly disable IPv6 when configured to do so (ITS#8754) Fixed libldap to correctly close TLS connection (ITS#8755) Fixed libldap with non-blocking TLS and referals (ITS#8167) Fixed libldap_r handling of deprecated OpenSSL function (ITS#8353) Fixed liblunicode case correspondence (ITS#8508) Fixed slapd with an idletimeout of less than four seconds (ITS#8952) Fixed slapd config parser variable for Windows64 (ITS#9012) Fixed slapd syncrepl fallback handling with delta-syncrepl (ITS#9015) Fixed slapd telephoneNumberNormalize, cert DN validation (ITS#8999) Fixed slapd syncrepl for relax with delta-syncrepl (ITS#8037) Fixed slapd to restrict rootDN proxyauthz to its own databases (ITS#9038) Fixed slapd to initialize SASL SSF per connection (ITS#9052) Fixed slapd-ldap starttls connections timeout behavior (ITS#8963) Fixed slapd-ldap segfault when entry result doesn't match filter (ITS#8997) Fixed slapd-meta conversion from slapd.conf to cn=config (ITS#8743) Fixed slapd-meta assertion when network interface goes down (ITS#8841) Fixed slapd-mdb fix bitshift integer overflow (ITS#8989) Fixed slapd-mdb index cleanup with cn=config (ITS#8472) Fixed slapd-mdb to improve performance with alias deref (ITS#7657) Fixed slapo-accesslog with SLAP_MOD_SOFT modifications (ITS#8990) Fixed slapo-accesslog possible assert with exops (ITS#8971) Fixed slapo-chain to correctly reject multiple chaining URIs (ITS#8637) Fixed slapo-chain conversion from slapd.conf to cn=config (ITS#8799) Fixed slapo-memberof conversion from slapd.conf to cn=config (ITS#8663) Fixed slapo-memberof for group name change to itself (ITS#9000) Fixed slapo-ppolicy behavior when pwdInHistory is changed (ITS#8349) Fixed slapo-rwm to not free original filter (ITS#8964) Fixed slapo-syncprov contextCSN generation (ITS#9015) Build Environment Fixed slapd to only link to BDB libraries with static build (ITS#8948) Fixed libldap implicit declaration with LDAP_CONNECTIONLESS (ITS#8794) Fixed libldap double inclusion of limits.h in cyrus.c (ITS#9041) Documentation General - Fixed minor typos (ITS#8764, ITS#8761) admin24 - Miscellaneous updates promoting mdb and fixing examples (ITS#9031) slapd.access(5) - Note MDB is the primary backend (ITS#8881) slapd.backends(5) - Note MDB is the recommended backend (ITS#8771) slapd-ldap(5) - Document starttls parameter (ITS#8693) Contrib Added slapo-lastbind capability to forward authTimestamp updates (ITS#7721) OpenLDAP 2.4.47 Release (2018/12/19) Added slapd-sock DN qualifier for subtrees to be processed (ITS#8051) Added slapd-sock ability to send extended operations to external listeners (ITS#8714) Fixed liblber to avoid incremental access to user-supplied bv in dupbv (ITS#8752) Fixed libldap dn to domain parsing with bad input (ITS#8842) Fixed slapd slapcat to correctly honor -g option (ITS#8667) Fixed slapd to correctly handle NO_SUCH_OBJECT with dynamic groups (ITS#8923) Fixed slapd to check status of rdnNormalize (ITS#8932) Fixed slapd cn=config when modifying slapo-syncprov config (ITS#8616) Fixed slapd sasl authz-policy "all" behavior (ITS#8909) Fixed slapd sasl minor typo (ITS#8918) Fixed slapd to correctly hide hidden DBs in the rootDSE (ITS#8912) Fixed slapd domainScope control to match Microsoft specification (ITS#8840) Fixed slapd-bdb/hdb/mdb to not convert certain IDLs to ranges (ITS#8868) Fixed slapo-accesslog deadlock during cleanup (ITS#8752) Fixed slapo-memberof cn=config modifications (ITS#8663) Fixed slapo-ppolicy with multi-provider replication (ITS#8927) Fixed slapo-syncprov with NULL modlist (ITS#8843) Build Environment Added slapd reproducible build support (ITS#8928) Fixed missing includes with OpenSSL 1.0.2 (ITS#8809) Contrib Fixed slapo-pbkdf2 hash generation (ITS#8878) Documentation admin24 fixed minor typo (ITS#8887) OpenLDAP 2.4.46 Release (2018/03/22) Fixed libldap connection delete callbacks when TLS fails to start (ITS#8717) Fixed libldap to not reuse tls_session if TLS hostname check fails (ITS#7373) Fixed libldap cross-compiling with OpenSSL 1.1 (ITS#8687) Fixed libldap OpenSSL 1.1.1 compatibility with BIO_method (ITS#8791) Fixed libldap MozNSS CA certificate hash matching (ITS#7374) Fixed libldap MozNSS with PEM certs when also using an NSS cert db (ITS#7389) Fixed libldap MozNSS initialization (ITS#8484) Fixed libldap GnuTLS with GNUTLS_E_AGAIN (ITS#8650) Fixed libldap memory leak with cancel operations (ITS#8782) Fixed slapd Eventlog registry key creation on 64-bit Windows (ITS#8705) Fixed slapd to maintain SSF across SASL binds (ITS#8796) Fixed slapd syncrepl deadlock when updating cookie (ITS#8752) Fixed slapd syncrepl callback to always be last in the stack (ITS#8752) Fixed slapd telephoneNumberNormalize when the value is spaces and hyphens (ITS#8778) Fixed slapd CSN queue processing (ITS#8801) Fixed slapd-ldap TLS connection timeout with high latency connections (ITS#8720) Fixed slapd-ldap to ignore unknown schema when omit-unknown-schema is set (ITS#7520) Fixed slapd-mdb with an optimization for long lived read transactions (ITS#8226) Fixed slapd-meta assert when olcDbRewrite is modified (ITS#8404) Fixed slapd-sock with LDAP_MOD_INCREMENT operations (ITS#8692) Fixed slapo-accesslog cleanup to only occur on failed operations (ITS#8752) Fixed slapo-dds entryTTL to actually decrease as per RFC 2589 (ITS#7100) Fixed slapo-syncprov memory leak with delete operations (ITS#8690) Fixed slapo-syncprov to not clear pending operation when checkpointing (ITS#8444) Fixed slapo-syncprov to correctly record contextCSN values in the accesslog (ITS#8100) Fixed slapo-syncprov not to log checkpoints to accesslog db (ITS#8607) Fixed slapo-syncprov to process changes from this SID on REFRESH (ITS#8800) Fixed slapo-syncprov session log parsing to not block other operations (ITS#8486) Build Environment Fixed Windows build with newer MINGW version (ITS#8697) Fixed compiler warnings and removed unused variables (ITS#8578) Contrib Fixed ldapc++ Control structure (ITS#8583) Documentation Delete stub manpage for back-ldbm (ITS#8713) Fixed ldap_bind(3) to mention the LDAP_SASL_SIMPLE mechanism (ITS#8121) Fixed ldap.conf(5) to note SASL_MECH/SASL_REALM are no longer user-only (ITS#8818) Fixed slapd-config(5) typo for olcTLSCipherSuite (ITS#8715) Fixed slapo-syncprov(5) indexing requirements (ITS#5048) OpenLDAP 2.4.45 Release (2017/06/01) Added slapd support for OpenSSL 1.1.0 series (ITS#8353, ITS#8533, ITS#8634) Fixed libldap to fail ldap_result if the handle is already bad (ITS#8585) Fixed libldap to expose error if user specified CA doesn't exist (ITS#8529) Fixed libldap handling of Diffie-Hellman parameters (ITS#7506) Fixed libldap GnuTLS use after free (ITS#8385) Fixed libldap SASL initialization (ITS#8648) Fixed slapd bconfig rDN escape handling (ITS#8574) Fixed slapd segfault with invalid hostname (ITS#8631) Fixed slapd sasl SEGV rebind in same session (ITS#8568) Fixed slapd syncrepl filter handling (ITS#8413) Fixed slapd syncrepl infinite looping mods with delta-sync MPR (ITS#8432) Fixed slapd callback struct so older modules without writewait should function. Custom modules may need to be updated for sc_writewait callback (ITS#8435) Fixed slapd-ldap/meta broken LDAP_TAILQ macro (ITS#8576) Fixed slapd-mdb so it passes ITS6794 regression test (ITS#6794) Fixed slapd-mdb double free with size zero paged result (ITS#8655) Fixed slapd-meta uninitialized diagnostic message (ITS#8442) Fixed slapo-accesslog to honor pauses during purge for cn=config update (ITS#8423) Fixed slapo-accesslog with multiple modifications to the same attribute (ITS#6545) Fixed slapo-relay to correctly initialize sc_writewait (ITS#8428) Fixed slapo-sssvlv double free (ITS#8592) Fixed slapo-unique with empty modifications (ITS#8266) Build Environment Added test065 for proxyauthz (ITS#8571) Fix test008 to be portable (ITS#8414) Fix test064 to wait for slapd to start (ITS#8644) Fix its4336 regression test (ITS#8534) Fix its4337 regression test (ITS#8535) Fix regression tests to execute on all backends (ITS#8539) Contrib Added slapo-autogroup(5) man page (ITS#8569) Added passwd missing conversion scripts for apr1 (ITS#6826) Fixed contrib modules where the writewait callback was not correctly initialized (ITS#8435) Fixed smbk5pwd to build with newer OpenSSL releases (ITS#8525) Documentation admin24 fixed tls_cipher_suite bindconf option (ITS#8099) admin24 fixed typo cn=config to be slapd.d (ITS#8449) admin24 fixed slapo-syncprov information to be current (ITS#8253) admin24 fixed typo in access control docs (ITS#7341, ITS#8391) admin24 fixed minor typo in tuning guide (ITS#8499) admin24 fixed information about the limits option (ITS#7700) admin24 fixed missing options for syncrepl configuration (ITS#7700) admin24 fixed accesslog documentation to note it should not be replicated (ITS#8344) admin24 fix typos (ITS#8562) admin24 fix replication sections to include back-mdb (ITS#8563) Fixed ldap.conf(5) missing information on SASL_NOCANON option (ITS#7177) Fixed ldapsearch(1) information on the V[V] flag behavior (ITS#7177, ITS#6339) Fixed slapd-config(5), slapd.conf(5) clarification on interval keyword for refreshAndPersist (ITS#8538) Fixed slapd-config(5), slapd.conf(5) clarify serverID requirements (ITS#8635) Fixed slapd-config(5), slapd.conf(5) clarification on loglevel settings (ITS#8123) Fixed slapo-ppolicy(5) to clearly note rootdn requirement (ITS#8565) Fixed slapo-memberof(5) to note it is not safe to use with replication (ITS#8613) Fixed slapo-syncprov(5) documentation to be current (ITS#8253) Fixed slapadd(8) manpage to note slapd-mdb (ITS#8215) Fixed various minor grammar issues in the man pages (ITS#8544) Fixed various typos (ITS#8587) OpenLDAP 2.4.44 Release (2016/02/05) Fixed slapd-bdb/hdb missing olcDbChecksum config attr (ITS#8337) Fixed slapd-mdb behavior with long lived read transactions (ITS#8226) Fixed slapd-mdb cleanup after failed transaction (ITS#8360) Fixed slapd-sql missing id_query/olcSqlIdQuery (ITS#8329) Fixed slapo-accesslog callback initialization (ITS#8351) Fixed slapo-ppolicy pwdMaxRecordedFailure must never be zero (ITS#8327) Fixed slapo-syncprov abandon processing (ITS#8354) Fixed slapo-syncprov ctxcsn snapshot on refresh (ITS#8281, ITS#8365) Documentation admin24 Stop linking to Berkeley DB downloads (ITS#8362) admin24 Update documentation for LMDB preference OpenLDAP 2.4.43 Release (2015/11/30) Fixed liblber remove obsolete assert (ITS#8240, ITS#8301) Fixed libldap file URLs on windows (ITS#8273) Fixed libldap microsecond timer for windows (ITS#8295) Fixed slap tools minor one time memory leak (ITS#8082) Fixed slapd to avoid redundant processing of abandon ops (ITS#8232) Fixed slapd syncrepl SEGV when present list is NULL (ITS#8231, ITS#8042) Fixed slapd segfault with invalid SASL URI (ITS#8218) Fixed slapd configuration parser with unbalanced quotes (ITS#8233) Fixed slapd syncrepl check with config db on windows (ITS#8277) Fixed slapd with mod Increment and inherited attribute type (ITS#8289) Fixed slapd-ldap SEGV after failed retry (ITS#8173) Fixed slapd-ldap to skip client controls in ldap_back_entry_get (ITS#8244) Fixed slapd-null to have an option to return a search entry (ITS#8249) Fixed slapd-relay to correctly handle quoted options (ITS#8284) Fixed slapo-accesslog delta-sync MPR with interrupted refresh phase (ITS#8281) Fixed slapo-dds segfault when using slapo-memberof (ITS#8133) Fixed slapo-ppolicy to allow purging of stale pwdFailureTime attributes (ITS#8185) Fixed slapo-ppolicy to release entry on failure (ITS#7537) Fixed slapo-ppolicy to fall back to default policy if there is a parsing error (ITS#8234) Fixed slapo-syncprov with interrupted refresh phase (ITS#8281) Fixed slapo-refint with subtree renames (ITS#8220) Fixed slapo-rwm missing olcDropUnrequested attribute (ITS#7889) Fixed slapo-rwm parsing to avoid double-escaping rewrite rules (ITS#7964) Build Environment Fixed ldif-filter option parsing (ITS#8292) Fixed slapd-tester EOL handling in test output for windows (ITS#8280) Fixed slapd-tester executable suffix for windows (ITS#8216) Fixed test061 timing issues (ITS#8297) Contrib Added libnettle support to pw-pbkdf2 (ITS#8198) Fixed smbk5pwd compiler warnings with libnettle (ITS#8235) Fixed passwd symbol collisions with other crypto libraries (ITS#8294) Documentation Updated guide to reflect changes to how TLS is handled with syncrepl (ITS#7897) OpenLDAP 2.4.42 Release (2015/08/14) Fixed liblber address length for CLDAP (ITS#8158) Fixed libldap dnssrv potential overflow with port number (ITS#7027,ITS#8195) Fixed slapd cn=config when updating olcAttributeTypes (ITS#8199) Fixed slapd-mdb to correctly update search candidates for scoped searches (ITS#8203) Fixed slapo-ppolicy with redundant mod ops on glued trees (ITS#8184) Fixed slapo-rwm crash when deleting rewrite rules (ITS#8213) Build Environment Fixed libdb detection with gcc 5.x (ITS#8056) OpenLDAP 2.4.41 Release (2015/06/21) Fixed ldapsearch to explicitly flush its buffer (ITS#8118) Fixed libldap async connections (ITS#8090) Fixed libldap double free of request during abandon (ITS#7967) Fixed libldap error string for LDAP_X_CONNECTING (ITS#8093) Fixed libldap segfault in ldap_sync_initialize (ITS#8001) Fixed libldap ldif-wrap off by one error (ITS#8003) Fixed libldap handling of TLS in async mode (ITS#8022) Fixed libldap null pointer dereference (ITS#8028) Fixed libldap mutex handling with LDAP_OPT_SESSION_REFCNT (ITS#8050) Fixed slapd slapadd config db import of minimal frontend entry (ITS#8150) Fixed slapd slapadd onetime leak with -w (ITS#8014) Fixed slapd sasl auxprop crash with invalid config (ITS#8092) Fixed slapd syncrepl delta-mpr issue with overlays and slapd.conf (ITS#7976) Fixed slapd syncrepl mutex for cookie state (ITS#7968) Fixed slapd syncrepl memory leaks (ITS#8035) Fixed slapd syncrepl to free presentlist at end of refresh mode (ITS#8038) Fixed slapd syncrepl to streamline presentlist (ITS#8042) Fixed slapd syncrepl concurrency when CHECK_CSN is enabled (ITS#8120) Fixed slapd rootdn checks for hidden backends (ITS#8108) Fixed slapd segfault when using matched values control (ITS#8046) Fixed slapd-ldap reconnection behavior on remote failure (ITS#8142) Fixed slapd-mdb minor case typo (ITS#8049) Fixed slapd-mdb one-level search (ITS#7975) Fixed slapd-mdb heap corruption (ITS#7965) Fixed slapd-mdb crash after deleting in-use schema (ITS#7995) Fixed slapd-mdb minor code cleanup (ITS#8011) Fixed slapd-mdb to return errors when using incorrect env flags (ITS#8016) Fixed slapd-mdb to correctly update search candidates (ITS#8036, ITS#7904) Fixed slapd-mdb when there were more than 65535 aliases in scope (ITS#8103) Fixed slapd-mdb alias deref when objectClass is not indexed (ITS#8146) Fixed slapd-meta TLS initialization with ldaps URIs (ITS#8022) Fixed slapd-meta to have better error logging (ITS#8131) Fixed slapd-perl conversion to cn=config (ITS#8105) Fixed slapd-sql autocommit config variable (ITS#8129,ITS#6613) Fixed slapo-collect segfault (ITS#7797) Fixed slapo-constraint with 0 count constraint (ITS#7780,ITS#7781) Fixed slapo-deref with empty attribute list (ITS#8027) Fixed slapo-memberof to correctly reject invalid members (ITS#8107) Fixed slapo-sock result parser for CONTINUE (ITS#8048) Fixed slapo-syncprov synprov_matchops usage of test_filter (ITS#8013) Fixed slapo-syncprov segfault on disconnect/abandon (ITS#5452,ITS#8012) Fixed slapo-syncprov memory leak (ITS#8039) Fixed slapo-syncprov segfault on disconnect/abandon (ITS#8043) Fixed slapo-syncprov deadlock when autogroup is in use (ITS#8063) Fixed slapo-syncprov potential loss of changes when under load (ITS#8081) Fixed slapo-unique enforcement of uniqueness with manageDSAit control (ITS#8057) Build Environment Fixed ftello reference for Win32 (ITS#8127) Enhanced contrib modules build paths (ITS#7782) Fixed contrib/autogroup internal operation identity (ITS#8006) Fixed contrib/autogroup to skip internal ops with accesslog (ITS#8065) Fixed contrib/passwd/sha2 compiler warning (ITS#8000) Fixed contrib/noopsrch compiler warning (ITS#7998) Fixed contrib/dupent compiler warnings (ITS#7997) Test suite: Added vrFilter test (ITS#8046) Contrib Added pbkdf2 sha256 and sha512 schemes (ITS#7977) Fixed autogroup modification callback responses (ITS#6970) Fixed nssov compare with usergroup (ITS#8079) Fixed nssov password change behavior (ITS#8080) Fixed nssov updated to 0.9.4 (ITS#8097) Documentation Added ldap_get_option(3) LDAP_FEATURE_INFO_VERSION information (ITS#8032) Added ldap_get_option(3) LDAP_OPT_API_INFO_VERSION information (ITS#8032) Fixed slapd-config(5), slapd.conf(5) tls_cipher_suite option (ITS#8099) Fixed slapd-meta(5), slapd-ldap(5) tls_cipher_suite option (ITS#8099) Fixed slapd-meta(5) fix minor typo (ITS#7769) OpenLDAP 2.4.40 Release (2014/09/20) Fixed libldap DNS SRV priority handling (ITS#7027) Fixed libldap don't leak libldap err codes (ITS#7676) Fixed libldap CR/LF handling (ITS#4635) Fixed libldap ldif-wrap length (ITS#7871) Fixed libldap GnuTLS ciphersuite parsing (ITS#7500) Fixed libldap GnuTLS with newer versions (ITS#7430,ITS#6359) Fixed libldif to correctly handle 4096 character lines (ITS#7859) Fixed librewrite reference counting (ITS#7723) Fixed slapacl with back-mdb reader transactions (ITS#7920) Fixed slapd syncrepl to send cookie on fallback (ITS#7849) Fixed slapd syncrepl SEGV when abandoning a connection (ITS#7928) Fixed slapd slapcat with external schema (ITS#7895) Fixed slapd schema RDN normalization (ITS#7935) Fixed slapd with repeated language tags (ITS#7941) Fixed slapd modrdn crash on naming attr with no matching rule (ITS#7850) Fixed slapd memory leak in control handling (ITS#7942) Fixed slapd-ldap removed dead code (ITS#7922) Fixed slapd-mdb to work concurrently with slapadd (ITS#7798) Fixed slapd-mdb with paged results (ITS#7705, ITS#7800) Fixed slapd-mdb slapcat with nonexistent indices (ITS#7870) Fixed slapd-mdb long lived reader transactions (ITS#7904) Fixed slapd-mdb memory leak on matchedDN (ITS#7872) Fixed slapd-mdb sorting of attribute values (ITS#7902) Fixed slapd-mdb to flag attribute values as sorted (ITS#7903) Fixed slapd-mdb index config handling (ITS#7912) Fixed slapd-mdb entry release handling (ITS#7915) Fixed slapd-mdb with aliases and referrals (ITS#7927) Fixed slapd-mdb alias dereferencing (ITS#7702) Fixed slapd-sock socket flushing (ITS#7937) Fixed slapo-accesslog attribute normalization (ITS#7934) Fixed slapo-accesslog internal search logging (ITS#7929) Fixed slapo-auditlog connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-chain interaction with slapo-rwm (ITS#7930) Fixed slapo-constraint connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-dds connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-dyngroup connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-memberof attr count (ITS#7893) Fixed slapo-memberof frontendDB handling (ITS#7249) Fixed slapo-memberof internal search logging (ITS#7929) Fixed slapo-pcache config processing (ITS#7919) Fixed slapo-pcache connection destroy logic (ITS#7906,ITS#7923) Added slapo-ppolicy ORDERING rules (ITS#7838) Fixed slapo-ppolicy timestamp resolution to use microseconds (ITS#7161) Fixed slapo-ppolicy connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-refint to check for pauses in cn=config (ITS#7873) Fixed slapo-refint internal search logging (ITS#7929) Fixed slapo-refint connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-seqmod connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-slapover connection destroy logic (ITS#7906,ITS#7923) Fixed slapo-sock db_init (ITS#7868) Fixed slapo-sssvlv fix olcSssVlvMaxPerConn (ITS#7908) Fixed slapo-translucent double free (ITS#7587) Fixed slapo-translucent to work with manageDSAit (ITS#7864) Fixed slapo-translucent to use local backend with local entries (ITS#7915) Fixed slapo-unique connection destroy logic (ITS#7906,ITS#7923) Fixed slapcacl with invalid suffix (ITS#7827) Build Environment Remove support for gcrypt (ITS#7877) BDB 6.0.20 and later is not supported (ITS#7890) Fixed ODBC link check (ITS#7891) Fixed slapd.ldif frontend config (ITS#7933) Contrib Added pbkdf2 module (ITS#7742) Fixed autogroup double free (ITS#7831) Fixed autogroup modification callback responses (ITS#6970) Fixed ldapc++ memory leak in Async connection (ITS#7806) Fixed nssov install path (ITS#7858) Fixed passwd rpath (ITS#7885) Fixed apr1 do_phk_hash argument order (ITS#7869) Fixed slapd-sha2 buffer overrun (ITS#7851) Documentation Fixed slapd.ldif man page reference (ITS#7803) Fixed slapd.conf(5) man page to reference exattrs (ITS#7847) Fixed guide to work with mkrelease (ITS#7887) Fixed ldap_get_dn(3) ldap_ava definition (ITS#7860) OpenLDAP 2.4.39 Release (2014/01/26) Fixed libldap MozNSS crash (ITS#7783) Fixed libldap memory leak with SASL (ITS#7757) Fixed libldap assert in parse_passwdpolicy_control (ITS#7759) Fixed libldap shortcut NULL RDNs (ITS#7762) Fixed libldap deref to use correct control Fixed liblmdb keysizes with mdb_update_key (ITS#7756) Fixed slapd cn=config olcDbConfig modification (ITS#7750) Fixed slapd-bdb/hdb to bail out of search if config is paused (ITS#7761) Fixed slapd-bdb/hdb indexing issue with derived attributes (ITS#7778) Fixed slapd-mdb to bail out of search if config is paused (ITS#7761) Fixed slapd-mdb indexing issue with derived attributes (ITS#7778) Fixed slapd-perl to bail out of search if config is paused (ITS#7761) Fixed slapd-sql to bail out of search if config is paused (ITS#7761) Fixed slapo-constraint handling of softadd/softdel (ITS#7773) Fixed slapo-syncprov assert with findbase (ITS#7749) Build Environment Test suite: Use $(MAKE) for tests (ITS#7753) Documentation admin24 fix TLSDHParamFile to be correct (ITS#7684) OpenLDAP 2.4.38 Release (2013/11/16) Fixed liblmdb nordahead flag (ITS#7734) Fixed liblmdb to check cursor index before cursor_del (ITS#7733) Fixed liblmdb wasted space on split (ITS#7589) Fixed slapd for certs with a NULL issuerDN (ITS#7746) Fixed slapd cn=config with empty nested includes (ITS#7739) Fixed slapd syncrepl memory leak with delta-sync MPR (ITS#7735) Fixed slapd-bdb/hdb to stop processing on dn not found (ITS#7741) Fixed slapd-bdb/hdb with indexed ANDed filters (ITS#7743) Fixed slapd-mdb to stop processing on dn not found (ITS#7741) Fixed slapd-mdb dangling reader (ITS#7662) Fixed slapd-mdb matching rule for OlcDbEnvFlags (ITS#7737) Fixed slapd-mdb with indexed ANDed filters (ITS#7743) Fixed slapd-meta from blocking other threads (ITS#7740) Fixed slapo-syncprov assert with findbase (ITS#7749) OpenLDAP 2.4.37 Release (2013/10/27) Added liblmdb nordahead environment flag (ITS#7725) Fixed client tools CLDAP with IPv6 (ITS#7695) Fixed libldap CLDAP with IPv6 (ITS#7695) Fixed libldap lock ordering with abandon op (ITS#7712) Fixed liblmdb segfault with mdb_cursor_del (ITS#7718) Fixed liblmdb when converting to writemap (ITS#7715) Fixed liblmdb assert on MDB_NEXT with delete (ITS#7722) Fixed liblmdb wasted space on split (ITS#7589) Fixed slapd cn=config with olcTLSProtocolMin (ITS#7685) Fixed slapd-bdb/hdb optimize index updates (ITS#7329) Fixed slapd-ldap chaining with cn=config (ITS#7381, ITS#7434) Fixed slapd-ldap chaining with controls (ITS#7687) Fixed slapd-mdb optimize index updates (ITS#7329) Fixed slapd-meta chaining with cn=config (ITS#7381, ITS#7434) Fixed slapo-constraint to no-op on nonexistent entries (ITS#7692) Fixed slapo-dds assert on startup (ITS#7699) Fixed slapo-memberof to not replicate internal ops (ITS#7710) Fixed slapo-refint to not replicate internal ops (ITS#7710) Build Environment Fixed slapd-mdb ptr arithmetic on void *s (ITS#7720) Documentation ldapsearch(1) minor typo fix (ITS#7680) slapd-passwd(5) minor typo fix (ITS#7680) OpenLDAP 2.4.36 Release (2013/08/17) Added back-meta target filter patterns (ITS#7609) Added liblmdb mdb_txn_env to API (ITS#7660) Fixed libldap CLDAP with uninit'd memory (ITS#7582) Fixed libldap with UDP (ITS#7583) Fixed libldap OpenSSL TLS versions (ITS#7645) Fixed liblmdb MDB_PREV behavior (ITS#7556) Fixed liblmdb transaction issues (ITS#7515) Fixed liblmdb mdb_drop overflow page return (ITS#7561) Fixed liblmdb nested split (ITS#7592) Fixed liblmdb overflow page behavior (ITS#7620) Fixed liblmdb race condition with read and write txns (ITS#7635) Fixed liblmdb mdb_del behavior with MDB_DUPSORT and mdb_del (ITS#7658) Fixed slapd cn=config with unknown schema elements (ITS#7608) Fixed slapd cn=config with loglevel 0 (ITS#7611) Fixed slapd slapi filterlist free behavior (ITS#7636) Fixed slapd slapi control free behavior (ITS#7641) Fixed slapd schema countryString as directoryString (ITS#7659) Fixed slapd schema telephoneNumber as directoryString (ITS#7659) Fixed slapd-bdb/hdb to wait for read locks in tool mode (ITS#6365) Fixed slapd-mdb behavior with alias dereferencing (ITS#7577) Fixed slapd-mdb modrdn and base-scoped searches (ITS#7604) Fixed slapd-mdb refcount behavior (ITS#7628) Fixed slapd-meta binding flag is set (ITS#7524) Fixed slapd-meta with minimal config (ITS#7581) Fixed slapd-meta missing results messages (ITS#7591) Added slapd-meta TCP keepalive support (ITS#7513) Fixed slapo-sssvlv double free (ITS#7588) Fixed slaptest to list -Q option (ITS#7568) Build Environment Fixed slapd-meta declaration warnings (ITS#7654) Contrib Fixed nssov group enumeration bug (ITS#7569) Fixed autogroup when URI has no attrs (ITS#7580) Documentation admin24 Update database backend notes (ITS#7590) ldap.conf(5) fixed typos (ITS#7568) ldapmodify(1) remove replog reference (ITS#7562) ldif(5) remove replog reference (ITS#7562) slapd-config(5) remove replog reference (ITS#7562) slapd.conf(5) remove replog reference (ITS#7562) slapd-config(5) document TLSProtocolMin (ITS#5655,ITS#7645) slapd.conf(5) document TLSProtocolMin (ITS#5655,ITS#7645) OpenLDAP 2.4.35 Release (2013/03/31) Fixed liblmdb mdb_cursor_put with MDB_MULTIPLE (ITS#7551) Fixed liblmdb page rebalance (ITS#7536) Fixed liblmdb missing parens (ITS#7377) Fixed liblmdb mdb_cursor_del crash (ITS#7553) Fixed slapd syncrepl updateCookie status (ITS#7531) Fixed slapd connection logging (ITS#7543) Fixed slapd segfault on modify (ITS#7542, ITS#7432) Fixed slapd-mdb to reject undefined attrs (ITS#7540) Fixed slapo-pcache with +/- attrsets (ITS#7552) Build Environment don't install DB_CONFIG if no BDB backends (ITS#7533) Documentation slapschema(8) fix tool name (ITS#7534) admin24 fixed pcache example (ITS#7546) admin24 fixed config examples (ITS#7522) OpenLDAP 2.4.34 Release (2013/03/01) Fixed libldap connections with EINTR (ITS#7476) Fixed libldap lineno overflow in ldif_read_record (ITS#7497) Fixed liblmdb mdb_env_open flag handling (ITS#7453) Fixed liblmdb mdb_midl_sort array optimization (ITS#7432) Fixed liblmdb freelist with large entries (ITS#7455) Fixed liblmdb to check for filled dirty page list (ITS#7491) Fixed liblmdb to validate data limits (ITS#7485) Fixed liblmdb mdb_update_key for large keys (ITS#7505) Fixed ldapmodify to not core dump with invalid LDIF (ITS#7477) Fixed slapd syncrepl for old entries in MPR setup (ITS#7427) Fixed slapd signedness for index_substr_any_* (ITS#7449) Fixed slapd enforce SLAPD_MAX_DAEMON_THREADS (ITS#7450) Fixed slapd mutex in send_ldap_ber (ITS#6164) Added slapd-ldap onerr option (ITS#7492) Added slapd-ldap keepalive support (ITS#7501) Fixed slapd-ldif with empty dir (ITS#7451) Fixed slapd-mdb to reopen attr DBs after env reopen (ITS#7416) Fixed slapd-mdb handling of missing entries (ITS#7483,7496) Fixed slapd-mdb environment flag setting (ITS#7452) Fixed slapd-mdb with sub db slapcat (ITS#7469) Fixed slapd-mdb to correctly work with toolthreads > 2 (ITS#7488,ITS#7527) Fixed slapd-mdb subtree search speed (ITS#7473) Fixed slapd-meta conversion to cn=config (ITS#7525) Fixed slapd-meta segfault when modifying olcDbUri (ITS#7526) Fixed slapd-sql back-config support (ITS#7499) Fixed slapo-constraint handle uri and restrict correctly (ITS#7418) Fixed slapo-constraint with multi-provider replication (ITS#7426) Fixed slapo-constraint segfault (ITS#7431) Fixed slapo-deref control initialization (ITS#7436) Fixed slapo-deref control exposure (ITS#7445) Fixed slapo-memberof with internal ops (ITS#7487) Fixed slapo-pcache matching rules for config db (ITS#7459) Fixed slapo-rwm modrdn cleanup (ITS#7414) Fixed slapo-sssvlv maxperconn parameter (ITS#7484) Build Environment Fixed slapo-constraint test suite (ITS#7423) Contrib Added nssov nssov_config support (ITS#7518) Added nssov password_prohibit_message (ITS#7518) Fixed ldapc++ with gcc-4.7 (ITS#7281,ITS#7304) Fixed nssov olcNssPamSession handling (ITS#7481) Fixed nssov connection DN (ITS#7518) Add missing Makefile for various modules (ITS#7308) Unify Makefile structure for modules (ITS#7309) Fixed slapo-allowed attribute replication (ITS#7493) Fixed slapo-passwd SHA2 to correctly zero buffer (ITS#7490) Documentation ldapurl(1) fix example usage (ITS#7454) ldap_get_option(3) fixed trailing whitespace (ITS#7411) slapd-config(5) olcExtraAttrs is per db (ITS#7421) slapd-overlays(5) update manpage index (ITS#7489) slapo-dynlist(5) Search behavior notes (ITS#7486) slapo-valsort(5) Document valsort control syntax (ITS#7523) OpenLDAP 2.4.33 Release (2012/10/10) Added slapd-meta cn=config support Fixed libldap MozNSS slot picking (ITS#7359) Fixed libldap MozNSS with tokenname:certnickname format (ITS#7360) Fixed liblmdb POSIX semaphore cleanup on environment close (ITS#7364) Fixed liblmdb mdb_page_split (ITS#7385, ITS#7229) Fixed slapd alock handling on Windows (ITS#7361) Fixed slapd acl handling with zero-length values (ITS#7350) Fixed slapd syncprov to not reference ops inside a lock (ITS#7172) Fixed slapd delta-syncrepl MPR with large attribute values (ITS#7354) Fixed slapd slapd_rw_destroy function (ITS#7390) Fixed slapd-ldap idassert bind handling (ITS#7403) Fixed slapd-mdb slapadd -q -w double free (ITS#7356) Fixed slapd-mdb to close read txn in reindex commit (ITS#7386) Fixed slapo-constraint with multiple modifications (ITS#7168) Build Environment Fixed build with Visual Studio (ITS#7358) Fixed liblmdb posix semaphore use on BSD system (ITS#7363) Add slapo-constraint test suite (ITS#7344, ITS#7366) Contrib Updated radius passwd module for NAS-Identifier (ITS#7357) Documentation slapo-refint(5) Note that refint is not replicated (ITS#7405) OpenLDAP 2.4.32 Release (2012/07/31) Added slappasswd loadable module support (ITS#7284) Fixed tools to not clobber SASL_NOCANON (ITS#7271) Fixed libldap function declarations (ITS#7293) Fixed libldap double free (ITS#7270) Fixed libldap debug level setting (ITS#7290) Fixed libldap MozNSS PEM/certdb handling (ITS#7276) Fixed libldap MozNSS cipher suite selection (ITS#7285) Fixed libldap MozNSS error handling (ITS#7287) Fixed libldap MozNSS cipher suite being ignored (ITS#7289) Fixed libldap MozNSS infinite loop (ITS#7291) Fixed libldap MozNSS context token for certdb (ITS#7312) Fixed libldap MozNSS store certificate object (ITS#7313) Fixed libldap MozNSS fix init and cleanup (ITS#7314) Fixed libldap MozNSS slot and pin usage (ITS#7315) Fixed libldap MozNSS to avoid infinite loop (ITS#7316) Fixed libldap MozNSS untrusted issuer error (ITS#7331) Fixed libldap gettime() regression (ITS#6262) Fixed libldap sasl handling (ITS#7118, ITS#7133) Fixed libldap to correctly free socket with TLS (ITS#7241) Fixed liblmdb leaf node handling (ITS#7266) Fixed liblmdb mutexes on Apple/Windows (ITS#7251) Fixed slapd config index renumbering (ITS#6987) Fixed slapd duplicate error response (ITS#7076) Fixed slapd parsing of PermissiveModify control (ITS#7298) Fixed slapd-bdb/hdb cache hang under high load (ITS#7222) Fixed slapd-bdb/hdb alias checking (ITS#7303) Fixed slapd-bdb/hdb olcDbConfig changes work immediately (ITS#7338) Fixed slapd-ldap to encode user DN during password change (ITS#7319) Fixed slapd-ldap assertion when proxying to MS AD (ITS#6851) Fixed slapd-ldap monitoring (ITS#7182, ITS#7225) Fixed slapd-mdb with tool mode (ITS#7255) Fixed slapd-mdb with approx indexing (ITS#7279) Fixed slapd-mdb dn2id delete (ITS#7302) Fixed slapd-mdb memory leak in online indexer (ITS#7323) Fixed slapd-mdb db corruption when hitting maxsize (ITS#7337) Fixed slapd-mdb aborts with online indexing (ITS#7339) Fixed slapd-perl panic (ITS#7325) Fixed slapo-accesslog memory leaks with sync replication (ITS#7292) Fixed slapo-syncprov memory leaks with sync replication (ITS#7292) Fixed contrib/smbk5pwd to not compile with MozNSS (ITS#7327) Fixed contrib/sha2 portability (ITS#7267) Fixed contrib/sha2 thread safety (ITS#7269) Added contrib/sha2 {SSHA256}, {SSHA384}, {SSHA512} support (ITS#7278) Build Environment Fixed test057 timing issues (ITS#7317) Fixed compilation with MS Visual Studio (ITS#7332) Contrib Added slapi_[get|free]_client_ip() (ITS#7305) Documentation slapo-sssvlv Added note about criticality (ITS#7253) admin24 Fix peername.regex typo (ITS#7282) Fixed slapd-config file include example (ITS#7318) slapd-ldap(5) Reference RFC4526 (ITS#7294) slapd-meta(5) Reference RFC4526 (ITS#7294) OpenLDAP 2.4.31 Release (2012/04/21) Added slapo-accesslog support for reqEntryUUID (ITS#6656) Fixed libldap IPv6 URL detection (ITS#7194) Fixed libldap rebinding on failed connection (ITS#7207) Fixed liblmdb alignment of MDB_db members (ITS#7191) Fixed liblmdb branch page merging on deletes (ITS#7190) Fixed liblmdb page split with MDB_APPEND (ITS#7213) Fixed liblmdb free page usage with entry deletion (ITS#7210) Fixed liblmdb to use IOV_MAX if it is defined and small (ITS#7196) Fixed liblmdb key alignment (ITS#7219) Fixed liblmdb mdb_page_split (ITS#7229) Fixed liblmdb with zero length IDLs (ITS#7230) Fixed slapd listener initialization (ITS#7233) Fixed slapd cn=config with olcTLSVerifyClient (ITS#7197) Fixed slapd delta-syncrepl fallback on non-leaf error (ITS#7195) Fixed slapd to reject MPR setups with bad serverID setting (ITS#7200) Fixed slapd approxIndexer key generation (ITS#7203) Fixed slapd modification of olcSuffix (ITS#7205) Fixed slapd schema validation with missing definitions (ITS#7224) Fixed slapd syncrepl -c with supplied CSN values (ITS#7245) Fixed slapd-bdb/hdb idlcache with only one element (ITS#7231) Fixed slapd-perl modify with binary values (ITS#7149) Fixed slapd-shell cn=config support (ITS#7201) Fixed slapd-shell modify with binary values (ITS#7149) Fixed slapo-accesslog deadlock with non-logged write ops (ITS#7088) Fixed slapo-syncprov sessionlog check (ITS#7218) Fixed slapo-syncprov entry leak (ITS#7234) Fixed slapo-syncprov startup initialization (ITS#7235) Build Environment Fixed test022 to check ldapsearch results (ITS#7228) Fixed test044 when back-monitor is disabled (ITS#7204) Documentation Fixed slapschema(8) formatting (ITS#7188) Fixed limdb functionality documentation (ITS#7238) Fixed ldap_get_option(3) note inheritance behavior (ITS#7240) OpenLDAP 2.4.30 Release (2012/02/29) Fixed libldap socket polling for writes (ITS#7167) Fixed liblutil string modifications (ITS#7174) Fixed slapd crash when attrsOnly is true (ITS#7143) Fixed slapd syncrepl delete handling (ITS#7052,ITS#7162) Fixed slapd-mdb slapadd with -q (ITS#7170) Fixed slapd-mdb slapadd with -w (ITS#7180) Fixed slapd-mdb slapindex with -q and -t (ITS#7176) Fixed slapo-pcache time-to-refesh handling (ITS#7178) Fixed slapo-syncprov loop detection (ITS#6024) Build Environment Fixed POSIX make support (ITS#7160) Fixed slapd-mdb build on POSIX (ITS#7160) Documentation Added option "-o" to ldap*(1) pages (ITS#7152) Fixed ldap*(1) page cleanup (ITS#7177) Fixed ldap_modify(3) prototypes (ITS#7173) OpenLDAP 2.4.29 Release (2012/02/12) Fixed libldap MozNSS deferred initialization handling (ITS#7136) Fixed libldap MozNSS with TLSCertificateKeyFile not set (ITS#7135) Fixed slapd cn=config modification of first schema element (ITS#7098) Fixed slapd operation reuse (ITS#7107) Fixed slapd blocked writers to not interfere with pool pause (ITS#7115) Fixed slapd connection loop connindex usage (ITS#7131) Fixed slapd double mutex unlock via connection_done (ITS#7125) Fixed slapd check order in connection_write (ITS#7113) Fixed slapd slapadd to exit on failure (ITS#7142) Fixed slapd syncrepl reference to freed memory (ITS#7127,ITS#7132) Fixed slapd syncrepl to ignore some errors on delete (ITS#7052) Fixed slapd syncrepl to handle missing oldRDN (ITS#7144) Fixed slapd-mdb to handle overlays in tool mode (ITS#7099) Fixed slapd-mdb segfaults with page splits (ITS#7121) Fixed slapd-mdb cleanup on transaction abort (ITS#7140) Fixed slapd-mdb with attribute descriptions (ITS#7146) Fixed slapd-meta to correctly handle multiple targets (ITS#7050) Fixed slapd-monitor compare op to update cached entry (ITS#7123) Fixed slapd-perl initialization (ITS#7075) Fixed slapd-sql to properly initialize be_cf_ocs (ITS#7158) Fixed slapo-dds to properly exit when in tool mode (ITS#7099) Fixed slapo-rwm not leave empty lots with normalized attrs (ITS#7143) Fixed slapo-syncprov with already abandoned operation (ITS#7150) Fixed contrib/smbk5pwd uninitialized keys in shadowLastChange (ITS#7138) Build Environment Fixed ldapsearch build on windows (ITS#7156) Fixed test001 to skip back-ldif (ITS#7101) Documentation admin24 Fix typo (ITS#7117) OpenLDAP 2.4.28 Release (2011/11/26) Fixed back-mdb out of order slapadd (ITS#7090) OpenLDAP 2.4.27 Release (2011/11/24) Added libldap support for draft-wahl-ldap-session (ITS#6984) Added slapd support for draft-wahl-ldap-session (ITS#6984) Added slapadd pipelining capability (ITS#7078) Added slapd Add-if-not-present (ITS#6561) Added slapd delta-syncrepl MPR (ITS#6734,ITS#7029,ITS#7031) Added slapd-mdb experimental backend (ITS#7079) Added slapd-passwd dynamic config support Added slapd-perl dynamic config support Added slapd-shell dynamic config support Added slapd-sock support as an overlay (ITS#6666) Added slapd-sql dynamic config support Added contrib/passwd APR1 support (ITS#6826) Fixed slapi linking on AIX (ITS#3272) Fixed ldapmodify crash with LDIF controls (ITS#7039) Fixed ldapsearch to honor timeout and timelimit (ITS#7009) Fixed libldap endless looping (ITS#7035) Fixed libldap TLS to not check hostname when using 'allow' (ITS#7014) Fixed libldap GnuTLS cert dn parse (ITS#7051) Fixed libldap MozNSS correctly destroy SSL_PeerCertificate (ITS#6980) Fixed libldap MozNSS with issuer expiration and verify never (ITS#6998) Fixed libldap MozNSS memory leak (ITS#7001) Fixed libldap MozNSS allow/try behavior (ITS#7002) Fixed libldap MozNSS to be thread safe (ITS#7022) Fixed libldap MozNSS SSL_ForceHandshake to use a mutex (ITS#7034) Fixed libldap MozNSS with wildcard certs (ITS#7006) Fixed liblutil MD5 initialization (ITS#6982) Fixed slapadd common code into slapcommon (ITS#6737) Fixed slapd backend connection initialization (ITS#6993) Fixed slapd frontend DB parsing in cn=config (ITS#7016) Fixed slapd hang with {numbered} overlay insertion (ITS#7030) Fixed slapd inet_ntop usage (ITS#6925) Fixed slapd cn=config deletion of bitmasks (ITS#7083) Fixed slapd cn=config modify replace/delete crash (ITS#7065) Fixed slapd schema UTF8StringNormalize with 0 length values (ITS#7059) Fixed slapd with dynamic acls for cn=config (ITS#7066) Fixed slapd response callbacks (ITS#6059,ITS#7062) Fixed slapd no_connection warnings with ldapi (ITS#6548,ITS#7092) Fixed slapd return code processing (ITS#7060) Fixed slapd sl_malloc various issues (ITS#6437) Fixed slapd startup behavior (ITS#6848) Fixed slapd syncrepl crash with non-replicated ops (ITS#6892) Fixed slapd syncrepl with modrdn (ITS#7000,ITS#6472) Fixed slapd syncrepl timeout when using refreshAndPersist (ITS#6999) Fixed slapd syncrepl deletes need a non-empty CSN (ITS#7052) Fixed slapd syncrepl glue for empty suffix (ITS#7037) Fixed slapd results cleanup (ITS#6763,ITS#7053) Fixed slapd validation of args for TLSCertificateFile (ITS#7012) Fixed slapd-bdb/hdb to build entry DN based on parent DN (ITS#5326) Fixed slapd-hdb with zero-length entries (ITS#7073) Fixed slapd-hdb duplicate entries in subtree IDL cache (ITS#6983) Fixed slapo-constraint conversion to back-config (ITS#6986) Fixed slapo-dds tag in refresh response (ITS#6886) Fixed slapo-dds TTL tolerance (ITS#7017) Fixed slapo-lastbind so authTimestamp is manageable (ITS#6873) Fixed slapo-pcache response cleanup (ITS#6981) Fixed slapo-ppolicy pwdAllowUserChange behavior (ITS#7021) Fixed slapo-sssvlv issue with greaterThanorEqual (ITS#6985) Fixed slapo-sssvlv to only return requested attrs (ITS#7061) Fixed slapo-syncprov DSA attribute filtering for Persist mode (ITS#7019) Fixed slapo-syncprov when consumer has newer state of our SID (ITS#7040) Fixed slapo-syncprov crash (ITS#7025) Fixed slapo-unique URI checking of "host" portion (ITS#7018) Fixed contrib/autogroup double-free (ITS#6972) Fixed contrib/smbk5pwd cn=config deletion of bitmasks (ITS#7083) Fixed contrib/smbk5pwd on 64-bit systems (ITS#7082) Build Environment Added missing LDIF form of schema files (ITS#7063) Fixed build for Solaris native compilers (ITS#6992) Fixed creation and installation of slapd.ldif (ITS#7015) Fixed libnet linking (ITS#7071) Documentation admin24 Fix table numbering (ITS#7003) slapd.conf(5) Fixed TLSCACertificateFile information (ITS#7023) ldapmodify(1) Fixed minor typo in -S option description (ITS#7086) ldap_sync(3) Document ldap_sync_destroy (ITS#7028) slapo-unique(5) Fix keyword quoting (ITS#7028) OpenLDAP 2.4.26 Release (2011/06/30) Added libldap LDAP_OPT_X_TLS_PACKAGE (ITS#6969) Fixed libldap MozNSS with CACertDir (ITS#6975) Fixed libldap MozNSS with PR_SetEnv (ITS#6862) Fixed libldap descriptor leak (ITS#6929) Fixed libldap socket leak (ITS#6930) Fixed libldap get option crash (ITS#6931) Fixed libldap lockup (ITS#6898) Fixed libldap ASYNC TLS setup (ITS#6828) Fixed libldap with missing \n terminations (ITS#6947) Fixed tools double free (ITS#6946) Fixed tools verbose output (ITS#6977) Fixed ldapmodify SEGV on invalid LDIF (ITS#6978) Added slapd extra_attrs database option (ITS#6513) Fixed slapd asserts (ITS#6932) Fixed slapd configfile param on windows (ITS#6933) Fixed slapd config with global chaining (ITS#6843) Fixed slapd uninitialized variables (ITS#6935) Fixed slapd config objectclass is readonly (ITS#6963) Fixed slapd entry response with control (ITS#6899) Fixed slapd with unknown attrs (ITS#6819) Fixed slapd normalization of schema RDN (ITS#6967) Fixed slapd operations cache to 10 op limit (ITS#6944) Fixed slapd syncrepl crash with non-replicated ops (ITS#6892) Fixed slapd-bdb/hdb with sparse index ranges (ITS#6961) Fixed slapd-monitor stray code cleanup (ITS#6974) Fixed back-ldap ppolicy updates (ITS#6711) Fixed back-ldap with id-assert (ITS#6817) Fixed slapd-meta reentry issues (ITS#6909) Fixed slapd-sql length of data type (ITS#6657,ITS#6691) Added slapo-accesslog filter matching (ITS#6815) Fixed slapo-accesslog with invalid attrs (ITS#6819) Added slapo-auditlog connID and peername logging (ITS#6936) Fixed slapo-memberof with accesslog (ITS#6329,ITS#6766,ITS#6915) Fixed slapo-pcache with unknown attrs (ITS#6823) Fixed slapo-pcache with '1.1', '+', and '*' attrs (ITS#6950) Fixed slapo-pcache buffersize issues (ITS#6951) Fixed slapo-pcache refresh (ITS#6953) Fixed slapo-pcache with pCacheBind (ITS#6954) Fixed slapo-pcache database corruption (ITS#6831) Fixed slapo-rwm with attributes with no equality rule (ITS#6943) Fixed slapo-sssvlv limits check when global (ITS#6973) Fixed slapo-syncprov with replicated subtrees (ITS#6872) Fixed slapo-unique with managedsait (ITS#6641) Fixed slapo-unique filter with zero-length values (ITS#6901) Added contrib/acl GSS naming extensions ACL module Fixed contrib/smbk5pwd with shadowLastChange (ITS#6955) Build Environment Fixed builds that do not have GETTIMEOFDAY (ITS#6885) Fixed libldap libfetch dependancy (ITS#6889) Documentation ldap_get_dn(3) add man page (ITS#6959) slapd-backends(5) update recommended database backend (ITS#6904) slapd-bdb(5) update recommended database backend (ITS#6904) slapd-hdb(5) update recommended database backend (ITS#6904) slapo-nssov(5) Fixed typo (ITS#6934) admin24 update that cn=config is preferred (ITS#6905) admin24 update information about indexes (ITS#6906) admin24 fix --enable-wrappers option (ITS#6971) OpenLDAP 2.4.25 Release (2011/03/26) Fixed ldapsearch pagedresults loop (ITS#6755) Fixed tools for incompatible args (ITS#6849) Fixed libldap MozNSS crash (ITS#6863) Fixed slapd add objectclasses in order (ITS#6837) Added slapd ordering for uidNumber and gidNumber (ITS#6852) Fixed slapd segfault when adding values out of order (ITS#6858) Fixed slapd sortval handling (ITS#6845) Fixed slapd-bdb with slapadd/index quick option (ITS#6853) Fixed slapd-ldap chain cn=config support (ITS#6837) Fixed slapd-ldap chain with slapd.conf (ITS#6857) Fixed slapd-meta deadlock (ITS#6846) Fixed slapo-sssvlv with multiple requests (ITS#6850) Fixed contrib/lastbind install rules (ITS#6238) Fixed contrib/cloak install rules (ITS#6877) Build Environment Fixed windows NT threads build (ITS#6859) Fixed libldap/lberl/util if/else usage (ITS#6832) Fixed Windows odbc32 detection (ITS#6125) Fixed Windows msys build (ITS#6870) Fixed test020 exit codes (ITS#6404) Documentation admin24 guide ldapi usage (ITS#6839) admin24 guide conversion notes (ITS#6834) admin24 guide fix drawback math for syncrepl (ITS#6866) admin24 guide note manpages are definitive (ITS#6855) OpenLDAP 2.4.24 Release (2011/02/10) Added LDIF line wrapping setting (ITS#6645) Added MozNSS support (ITS#6714,ITS#6742,ITS#6790,ITS#6791) Added MozNSS support (ITS#6802,ITS#6811,ITS#6816,ITS#5696) Added libldap cert x500UniqueIdentifier handling (ITS#6741) Added libldap_r,libldap formal concurrency API (ITS#6625,ITS#5421) Added slapadd attribute value checking (ITS#6592) Added slapcat continue mode for problematic DBs (ITS#6482) Added slapd syncrepl suffixmassage support (ITS#6781) Added slapd multiple listener threads (ITS#6780) Added slapd extensible match for ordering rules (ITS#6532) Added slapd-meta paged results control forwarding (ITS#6664) Added slapd-meta subtree-include support (ITS#6801) Added slapd-null back-config support (ITS#6624) Added slapd-sql autocommit support (ITS#6612) Added slapd-sql support for long long keys (ITS#6617) Added slapo-sssvlv multiple sorts per connection (ITS#6686) Added contrib/autogroup LDAP URI with attribute filter (ITS#6536) Added contrib/dupent module (ITS#6630) Added contrib/lastbind (ITS#6238) Added contrib/kinit for kerberos tickets Added contrib/noopsrch for entry counting (ITS#6598) Fixed client tools control logging (ITS#6775) Fixed client tools one time leak (ITS#6778) Fixed liblber to not close invalid sockets (ITS#6585) Fixed liblber unmatched brace handling (ITS#6764) Fixed liblber error setting (ITS#6732) Fixed liblber memory debugging (ITS#6733) Fixed libldap connectionless warnings (ITS#6747) Fixed libldap dnssrv port format specifier (ITS#6644) Fixed libldap EOF handling (ITS#6723) Fixed libldap GnuTLS hang on socket close (ITS#6673) Fixed libldap sasl partial write handling (ITS#6639) Fixed libldap search leak (ITS#6453) Fixed libldap referral chasing (ITS#6602) Fixed libldap leak when chasing referrals (ITS#6744) Fixed libldap url parsing with NULL host (ITS#6653) Fixed libldap ldap_open_internal_connection (ITS#6788) Fixed libldap sync checking for BER errors (ITS#6738) Fixed libldap variable usage (ITS#6813) Fixed liblutil getpass prompts (ITS#6702) Fixed ldapsearch segfault with deref (ITS#6638) Fixed ldapsearch multiple controls parsing (ITS#6651) Fixed slapd SlapReply usage (ITS#6758) Fixed slapd acl parsing overflow (ITS#6611) Fixed slapd acl when resuming parsing (ITS#6804) Fixed slapd Compare operation (ITS#6753) Fixed slapd default config acls with overlays (ITS#6822) Fixed slapd assert control (ITS#5862) Fixed slapd assertions and debugging (ITS#6759) Fixed slapd config leak with olcDbDirectory (ITS#6634) Fixed slapd connectionless warnings (ITS#6747) Fixed slapd listeners destruction (ITS#6736) Fixed slapd to free controls if needed (ITS#6629) Fixed slapd to stop if given unknown options (ITS#6754) Fixed slapd filter leak (ITS#6635) Fixed slapd matching rules for strict ordering (ITS#6722) Fixed slapd when first acl is value dependent (ITS#6693) Fixed slapd modify to return actual error (ITS#6581) Fixed slapd modrdn with empty DN (ITS#6768) Fixed slapd c_authz_backend setting (ITS#6824) Fixed slapd sortvals of attributes with 1 value (ITS#6715) Fixed slapd syncrepl reuse of presence list (ITS#6707) Fixed slapd syncrepl uninitialized return code (ITS#6719) Fixed slapd syncrepl variable initialization (ITS#6739) Fixed slapd syncrepl refresh to use complete cookie (ITS#6807) Fixed slapd-bdb hasSubordinates generation (ITS#6712) Fixed slapd-bdb entry cache delete failure (ITS#6577) Fixed slapd-bdb entry cache leak on multi-core systems (ITS#6660) Fixed slapd-bdb error propagation to overlays (ITS#6633) Fixed slapd-bdb slapadd -q with glued dbs (ITS#6794) Fixed slapd-ldap debug output of timeout (ITS#6721) Fixed slapd-ldap DNSSRV referral chaining (ITS#6565) Fixed slapd-ldap chaining with bind failures (ITS#6607) Fixed slapd-ldap chaining with onelevel scope (ITS#6699) Fixed slapd-ldap chaining with ppolicy (ITS#6540) Fixed slapd-ldap with SASL/EXTERNAL (ITS#6642) Fixed slapd-ldap crash on matchedDN (ITS#6793) Fixed slapd-ldap with unknown objectClasses (ITS#6814) Fixed slapd-ldif error strings (ITS#6731) Fixed slapd-ndb to honor rootpw setting (ITS#6661) Fixed slapd-ndb hasSubordinates generation (ITS#6712) Fixed slapd-ndb variable initialization (ITS#6806) Fixed slapd-ndb with out of order attributes (ITS#6821) Fixed slapd-meta anon retry with failed auth method (ITS#6643) Fixed slapd-meta rebind proc (ITS#6665) Fixed slapd-meta to correctly rebind as user (ITS#6574) Fixed slapd-meta with SASL/EXTERNAL (ITS#6642) Fixed slapd-meta matchedDN return code (ITS#6774) Fixed slapd-meta candidate selection (ITS#6799) Fixed slapd-meta attribute normalization (ITS#6818) Fixed slapd-monitor hasSubordinates generation (ITS#6712) Fixed slapd-monitor abandon processing (ITS#6783) Fixed slapd-monitor entry locks (ITS#6787) Fixed slapd-sock missing newline in Compare operation (ITS#6809) Fixed slapd-sql with null objectClass (ITS#6616) Fixed slapd-sql hasSubordinates generation (ITS#6712) Fixed slapo-accesslog with controls (ITS#6652) Fixed slapo-dynlist Compare operation (ITS#6752) Fixed slapo-dynlist entry handling (ITS#6752) Fixed slapo-memberof CSN generation (ITS#6766) Fixed slapo-memberof log messages (ITS#6748) Fixed slapo-memberof with an empty groupOfNames (ITS#6670) Fixed slapo-memberof with modrdn operations (ITS#6700) Fixed slapo-pcache callback freeing (ITS#6640) Fixed slapo-pcache to ignore undefined attrs (ITS#6600) Fixed slapo-pcache pointer freeing (ITS#6797) Fixed slapo-pcache with negative caching (ITS#6796) Fixed slapo-pcache monitoring cleanup (ITS#6808) Fixed slapo-ppolicy don't update opattrs on consumers (ITS#6608) Fixed slapo-ppolicy to allow userPassword deletion (ITS#6620) Fixed slapo-refint when last group member is deleted (ITS#6663) Fixed slapo-refint with subtree rename (ITS#6730) Fixed slapo-rwm double free (ITS#6720) Fixed slapo-rwm crash (ITS#6632,ITS#6727) Fixed slapo-rwm entry handling (ITS#6760) Fixed slapo-rwm response hang (ITS#6792) Fixed slapo-sssvlv initialization (ITS#6649) Fixed slapo-sssvlv to not advertise when unused (ITS#6647) Fixed slapo-sssvlv result code (ITS#6685) Fixed slapo-syncprov to send error if consumer is newer (ITS#6606) Fixed slapo-syncprov filter race condition (ITS#6708) Fixed slapo-syncprov active mod race (ITS#6709) Fixed slapo-syncprov to refresh if context is dirty (ITS#6710) Fixed slapo-syncprov CSN updates to all consumers (ITS#6718) Fixed slapo-syncprov sessionlog ordering (ITS#6716) Fixed slapo-syncprov sessionlog with adds (ITS#6503) Fixed slapo-syncprov mutex (ITS#6438) Fixed slapo-syncprov mincsn check with MPR (ITS#6717) Fixed slapo-syncprov control leak (ITS#6795) Fixed slapo-syncprov error codes (ITS#6812) Fixed slapo-translucent entry leak (ITS#6746) Fixed contrib/autogroup install location (ITS#6684) Fixed contrib/autogroup crash with ppolicy (ITS#6684) Fixed contrib/autogroup with non-DN URIs (ITS#6684) Fixed contrib/autogroup with memberOf overlay (ITS#6684) Fixed contrib/cloak when returning multiple entries (ITS#6762) Fixed contrib/nssov to only close socket on shutdown (ITS#6676) Fixed contrib/nssov multi platform support (ITS#6604) Build Environment Added support for [unsigned] long long (ITS#6622) Added slapd support for BDB 5.0+ (ITS#6698) Fixed config.guess/sub to pick up newer OSes (ITS#6547) Fixed libldap mutex code - cleanup (ITS#6672) Fixed libldap unnecessary ifdef's (ITS#6603) Fixed slapd-tester EOF handling (ITS#6723) Fixed slapd-tester filter initialization (ITS#6735) Fixed test scripts with alternate testdir (ITS#6782) Removed antiquated SunOS LWP support (ITS#6669) Documentation admin24 guide fix examples (ITS#6681) admin24 guide typo fixes (ITS#6609) admin24 guide refint rootdn requirement (ITS#6364) admin24 add pcache overlay section (ITS#6521) ldap_open(3) document ldap_set_urllist_proc (ITS#6601) ldap.conf(5) GnuTLS cipher spec info (ITS#6525) slapd.conf(5) GnlTLS cipher spec info (ITS#6525) slapd.conf(5) multi-listener support (ITS#6780) slapd-config(5) GnuTLS cipher spec info (ITS#6525) slapd-config(5) multi-listener support (ITS#6780) slapd-meta(5) note deprecated items (ITS#6800) slapd-meta(5) document subtree-include (ITS#6801) slapo-pcache(5) note rootdn requirement (ITS#6522) slapo-refint(5) rootdn requirement (ITS#6364) OpenLDAP 2.4.23 Release (2010/06/30) Fixed libldap to return server's error code (ITS#6569) Fixed libldap memleaks (ITS#6568) Fixed liblutil off-by-one with delta (ITS#6541) Fixed slapd acls with glued databases (ITS#6468) Fixed slapd syncrepl rid logging (ITS#6533) Fixed slapd modrdn handling of invalid values (ITS#6570) Fixed slapd-bdb hasSubordinates computation (ITS#6549) Fixed slapd-bdb to use memcpy instead for strcpy (ITS#6474) Fixed slapd-bdb entry cache delete failure (ITS#6577) Fixed slapd-ldap to return control responses (ITS#6530) Fixed slapo-ppolicy to use Debug (ITS#6566) Fixed slapo-refint to zero out freed DN vals (ITS#6572) Fixed slapo-rwm to use Debug (ITS#6566) Fixed slapo-sssvlv to use Debug (ITS#6566) Fixed slapo-syncprov lost deletes in refresh phase (ITS#6555) Fixed slapo-valsort to use Debug (ITS#6566) Fixed contrib/nssov network.c missing patch (ITS#6562) Build Environment Fixed test043 attribute sorting (ITS#6553) Documentation slapd-config(5) note default rootdn (ITS#6546) OpenLDAP 2.4.22 Release (2010/04/24) Added slapd SLAP_SCHEMA_EXPOSE flag for hidden schema elements (ITS#6435) Added slapd tools selective iterations (ITS#6442) Added slapd syncrepl TCP keepalive (ITS#6389) Added slapo-ldap idassert-passthru (ITS#6456) Added slapo-pbind Fixed libldap gmtime re-entrancy (ITS#6262) Fixed libldap gssapi off by one error (ITS#6223) Fixed libldap GnuTLS serial length (ITS#6460) Fixed libldap MozNSS context and PEM support (ITS#6432) Fixed libldap referral on bind behavior(ITS#6510) Fixed slapd acl non-entry internal searches (ITS#6481) Fixed slapd acl attrval style initialization (ITS#6520) Fixed slapd certificateListValidate (ITS#6466) Fixed slapd empty URI parsing (ITS#6465) Fixed slapd glued misplaced entries (ITS#6506) Fixed slapd glued paged cookies (ITS#6507) Fixed slapd glued paged results (ITS#6504) Fixed slapd gmtime re-entrancy (ITS#6262) Fixed slapd to ignore controls with unrecognized flags (ITS#6480) Fixed slapd entry ownership (ITS#5340) Fixed slapd sasl auxprop_lookup (ITS#6441) Fixed slapd sasl auxprop ssf (ITS#5195) Fixed slapd syncrepl for attributes with no matching rule (ITS#6458) Fixed slapd syncrepl for unknown attrs and delta-sync (ITS#6473) Fixed slapd syncrepl loop with moddn (ITS#6472) Fixed slapo-accesslog to not replicate internal purges (ITS#6519) Fixed slapd-bdb contextCSN updates from updatedn (ITS#6469) Fixed slapd-bdb lockobj zeroing (ITS#6501) Fixed slapd-ldap/meta control criticality (ITS#6523) Fixed slapd-ldap/meta with ordered values (ITS#6516) Fixed slapo-collect entry ownership (ITS#5340,ITS#6423) Fixed slapo-dds with NULL backend (ITS#6490) Fixed slapo-dynlist entry ownership (ITS#5340,ITS#6423) Fixed slapo-memberof attr count (ITS#6508) Fixed slapo-pcache to release its own entries (ITS#6484) Fixed slapo-pcache with NULL backend (ITS#6490) Fixed slapo-rwm entry release handling (ITS#6484) Fixed slapo-rwm memory handling with rewrites (ITS#6526) Fixed slapo-rwm olcRwmMap handling (ITS#6436) Fixed slapo-rwm entry ownership (ITS#5340,ITS#6423) Fixed slapo-syncprov memory leak (ITS#6459) Fixed slapo-translucent counter increment (ITS#6497) Fixed slapo-valsort entry ownership (ITS#5340,ITS#6423) Fixed contrib/sha2 adds mechs for more hashes (ITS#6433) Fixed contrib/nssov to use nss-pam-ldapd (ITS#6488) Build Environment Added back-ldif, back-null test support (ITS#5810) Documentation admin24 avoid explicit moduleload statements (ITS#6486) admin24 broken link fixes (ITS#6493,ITS#6515) slapd.access(5) val.regex explanation (ITS#5804) OpenLDAP 2.4.21 Release (2009/12/20) Fixed liblutil for negative microsecond offsets (ITS#6405) Fixed slapd global settings to work without restart (ITS#6428) Fixed slapd looping with SSL/TLS connections (ITS#6412) Fixed slapd syncrepl freeing tasks from queue (ITS#6413) Fixed slapd syncrepl parsing of tls defaults (ITS#6419) Fixed slapd syncrepl uninitialized variables (ITS#6425) Fixed slapd-config Adds with Abstract classes (ITS#6408) Fixed slapo-dynlist behavior with simple filters (ITS#6421) Fixed slapd-ldif access outside database directory (ITS#6414) Fixed slapd-null extraneous assert (ITS#6403) Fixed slapo-translucent with back-null (ITS#6403) Fixed slapo-unique criteria checking (ITS#6270) Build Environment Deleted broken LBER_INVALID macro (ITS#6402) Fixed test058 kill usage (ITS#6420) Fixed meta regression test (ITS#6418) Documentation slapd-meta(5) Note deprecated functions (ITS#6424) admin24 fix set example for group of groups (ITS#6382) admin24 fix dynamic group documentation (ITS#6290) OpenLDAP 2.4.20 Release (2009/11/27) Fixed client tools with LDAP options (ITS#6283) Fixed liblber embedded NUL values in BerValues (ITS#6353) Fixed liblber inverted LBER_USE_DER test (ITS#6348) Fixed liblber to return failure on certain failures (ITS#6344) Fixed libldap connection initialization (ITS#6386) Fixed libldap sasl buffer sizing (ITS#6327,ITS#6334) Fixed libldap uninitialized return value (ITS#6355) Fixed libldap unlimited timeout (ITS#6388) Added slapd handling of hex server IDs (ITS#6297) Added slapd syncrepl contextCSN storing in subentry (ITS#6373) Fixed slapd asserts in minimal environment (ITS#6361) Fixed slapd authid-rewrite parsing (ITS#6392) Fixed slapd checks of str2filter (ITS#6391) Fixed slapd configArgs initialization (ITS#6363) Fixed slapd debug handling of LDAP_DEBUG_ANY (ITS#6324) Fixed slapd db_open with connection_fake_init (ITS#6381) Fixed slapd with embedded \0 in bervals (ITS#6378,ITS#6379) Fixed slapd inclusion of ac/unistd.h (ITS#6342) Fixed slapd invalid dn log message (ITS#6309) Fixed slapd lockup on shutdown (ITS#6372) Fixed slapd onetime leak (ITS#6398) Fixed slapd RID range to be decimal only (ITS#6394) Fixed slapd sl_free to better reclaim memory (ITS#6380) Fixed slapd syncrepl deletes in MirrorMode (ITS#6368) Fixed slapd syncrepl to use correct SID (ITS#6367) Fixed slapd termination for one level DNs (ITS#6338) Fixed slapd tls_accept to retry in certain cases (ITS#6304) Fixed slapd-bdb/hdb cache corruption (ITS#6341) Fixed slapd-bdb/hdb entry cache (ITS#6360) Fixed slapd-ldap leak (ITS#6326) Fixed slapd-relay bind segfault (ITS#6337) Fixed slapo-accesslog ensure CSNs are normalized (ITS#6400) Fixed slapo-memberof operational attr updates (ITS#6329) Fixed slapo-pcache entry dupe (ITS#6310) Fixed slapo-syncprov checkpoint conversion (ITS#6370) Fixed slapo-syncprov deadlock (ITS#6335) Fixed slapo-syncprov memory leak (ITS#6376) Fixed slapo-syncprov out of order changes (ITS#6346) Fixed slapo-syncprov psearch with stale cookie (ITS#6397) Build Environment Added additional operations for ITS#6332 Fixed memrchr define (ITS#6351) Fixed slapd MAXPATHLEN handling (ITS#6342) Added test050 rapid add/mod/del sequence (ITS#6368) Fixed test057 handling of memberof/refint (ITS#6343) Fixed slapd test error ignoring (ITS#6345) Fixed liblutil constant (ITS#5909) Documentation admin24 fix RFC4511 and other references (ITS#6399) ldap_get_dn(3) typos (ITS#5366) ldap.conf(5) clarify comment usage (ITS#6384) slapd.conf(5) note hex server IDs (ITS#6297) slapd-config(5) note hex server IDs (ITS#6297) OpenLDAP 2.4.19 Release (2009/10/06) Fixed client tools with null timeouts (ITS#6282) Fixed slapadd to warn about missing attrs for consumers (ITS#6281) Fixed slapd acl cache (ITS#6287) Fixed slapd tools to allow -n for conversion (ITS#6258) Fixed slapd-ldap with null timeouts (ITS#6282) Fixed slapd-ldap with strong binds with relay/translucent (ITS#6296) Fixed slapd-ldif buffer overflow (ITS#6303) Fixed slapo-auditlog comments when modifying (ITS#6286) Fixed slapo-dynlist lock leak (ITS#6308) Fixed slapo-pcache cache corruption (ITS#6242) Fixed slapo-sssvlv sort control dereferencing (ITS#6288) Fixed contrib/autogroup segfaults (ITS#6279) Fixed contrib/nssov getgroupbymembers (ITS#6291) Fixed contrib/smbk5pwd rpath linking (ITS#6323) Build Environment Fixed --enable-deref support (ITS#6311) Fixed contrib/autogroup default libtool path (ITS#6284) Deleted nadf.schema (ITS#6140) OpenLDAP 2.4.18 Release (2009/09/06) Fixed client tools common options (ITS#6049) Fixed liblber speed and other problems (ITS#6215) Added libldap MozNSS PEM support (ITS#6278) Added libldap option for SASL_USERNAME (ITS#6257) Fixed libldap error parsing (ITS#6197) Fixed libldap native getpass usage (ITS#4643) Fixed libldap tls_check_hostname for OpenSSL and MozNSS (ITS#6239) Added slapd tcp buffers support (ITS#6234) Fixed slapd allow mirrormode to be set to FALSE (ITS#5946) Fixed slapd certificate list parsing (ITS#6241) Fixed slapd writers blocking (ITS#6276) Fixed slapd dncachesize behavior to unlimited by default (ITS#6222) Fixed slapd incorrectly applying writetimeout when not set (ITS#6220) Fixed slapd with duplicate empty lines for olcDbConfig (ITS#6240) Fixed slapd server URL matching (ITS#5942) Fixed slapd subordinate needs a suffix (ITS#6216) Fixed slapd syncrepl decrement on possible NULL value (ITS#6256) Fixed slapd tools to properly close database (ITS#6214) Fixed slapd uninitialized SlapReply components (ITS#6101) Fixed slapd-meta starttls with targets (ITS#6190) Fixed slapd-monitor stats with glued subordinates (ITS#6243) Fixed slapd-ndb startup (ITS#6203) Fixed slapd-relay various issues (ITS#6133) Fixed slapd-relay response/cleanup callback mismatch (ITS#6154) Fixed slapd-sql with baseObject query (ITS#6172) Fixed slapd-sql with empty attribute (ITS#6163) Fixed slapo-dynlist uninitialized var (ITS#6266) Fixed slapo-pcache multiple enhancements (ITS#6152,ITS#5178) Fixed slapo-ppolicy updating operational attributes (ITS#6265) Fixed slapo-translucent attribute return (ITS#6254) Fixed slapo-translucent filter matching (ITS#6255) Fixed slapo-translucent to honor sizelimit (ITS#6253) Fixed slapo-unique filter matching (ITS#6077) Fixed tools off by one error (ITS#6233) Fixed tools resource leaks (ITS#6145) Added contrib/allowed (ITS#4730) Fixed contrib/autogroup with RE24 (ITS#6227) Fixed contrib/nss symbols (ITS#6273) Build Environment Tests note which backend is being tested (ITS#5810) Fixed test056-monitor with custom ports (ITS#6213) Documentation admin24 fix broken link (ITS#6264) ldap_open(3) document URI (ITS#6261) ldap_set/get_option(3) SASL/TLS options added (ITS#6260) man page format updates (ITS#6023) OpenLDAP 2.4.17 Release (2009/07/13) Fixed liblber to use ber_strnlen (ITS#6080) Fixed libldap GnuTLS private key init (ITS#6053) Fixed libldap openssl digest initialization (ITS#6192) Fixed libldap tls NULL error messages (ITS#6079) Fixed libldap_r missing stub (ITS#6188) Fixed liblutil opendir/closedir on windows (ITS#6041) Fixed liblutil for _GNU_SOURCE (ITS#5464,ITS#5666) Added slapd sasl auxprop support (ITS#6147) Added slapd schema checking tool (ITS#6150) Added slapd writetimeout keyword (ITS#5836) Fixed slapd abandon/cancel handling for some ops (ITS#6157) Fixed slapd access setstyle to expand (ITS#6179) Fixed slapd assert with closing connections (ITS#6111) Fixed slapd bind race condition (ITS#6189) Fixed slapd cancel behavior (ITS#6137) Fixed slapd cert validation (ITS#6098) Fixed slapd connection_destroy assert (ITS#6089) Fixed slapd csn normalization (ITS#6195) Fixed slapd errno handling (ITS#6037) Fixed slapd global alloc handling (ITS#6054) Fixed slapd hung writers (ITS#5836) Fixed slapd ldapi issues (ITS#6056) Fixed slapd moduleload with static backends and modules (ITS#6016) Fixed slapd normalization of updated schema attributes (ITS#5540) Fixed slapd olcLimits handling (ITS#6159) Fixed slapd olcLogLevel with hex levels (ITS#6162) Fixed slapd pagedresults stacked control with overlays (ITS#6056) Fixed slapd password-hash incorrect limit on arg length (ITS#6139) Fixed slapd readonly restrictions (ITS#6109) Fixed slapd sending cancelled operations results (ITS#6103) Fixed slapd slapi_entry_has_children (ITS#6132) Fixed slapd sockets usage on windows (ITS#6039) Fixed slapd some abandon and cancel race conditions (ITS#6104) Fixed slapd tls context after changes (ITS#6135) Fixed slapd-bdb/hdb adjust dncachesize if too low (ITS#6176) Fixed slapd-bdb/hdb crashes during delete (ITS#6177) Fixed slapd-bdb/hdb multiple olcIndex for same attr (ITS#6196) Fixed slapd-hdb freeing of already freed entries (ITS#6074) Fixed slapd-hdb entryinfo cleanup (ITS#6088) Fixed slapd-hdb dncache lockups (ITS#6095) Fixed slapd-ldap deadlock with non-responsive TLS URIs (ITS#6167) Fixed slapd-relay to return failure on failure (ITS#5328) Fixed slapd-sql with BACKSQL_ARBITRARY_KEY defined (ITS#6100) Fixed slapo-collect collectinfo ordering (ITS#6076) Fixed slapo-collect missing equality match rule (ITS#6075) Fixed slapo-dds entry expiration (ITS#6169) Fixed slapo-perl symbols (ITS#5658) Fixed slapo-ppolicy to honor pwdLockout (ITS#6168) Fixed slapo-ppolicy to return check modules error message (ITS#6082) Fixed slapo-refint refint_repair handling (ITS#6056) Added slapo-rwm rwm-drop-unrequested-attrs config option (ITS#6057) Fixed slapo-rwm dn passing (ITS#6070) Fixed slapo-rwm entry free (ITS#6058) Fixed slapo-rwm entry release (ITS#6081) Fixed slapo-translucent entry gathering (ITS#6156) Fixed tools returning ldif errors (ITS#5892) Fixed contrib/smbk5pwd use of private functions (ITS#5535) Build Environment Added test056-monitor (ITS#5540) Added test057-memberof-refint (ITS#5395) Fixed winsock detection for windows (ITS#6102, ITS#6078) Removed GSSAPI configure option (ITS#6091,ITS#6092,ITS#6093,ITS#5369) Documentation admin24 relocate configuration examples (ITS#6183) admin24 fixed example regex (ITS#6052) admin24 removed temporary back-monitor note (ITS#6130) admin24 slapd.conf to cn=config conversion process (ITS#6060) man page consistency fixes (ITS#6023) ldapcompare(1) note -e option (ITS#6107) ldapdelete(1) note -e option (ITS#6107) ldapmodify(1) note -e option (ITS#6107) ldapmodrdn(1) note -e option (ITS#6107) ldapsearch(1) output format description (ITS#6146) ldapurl(1) note -e option (ITS#6107) ldapwhoami(1) note -e option (ITS#6107) ldap_result(3) Add RETURN VALUE heading (ITS#6180) ldap.conf(5) improve sizelimit/timelimit limits (ITS#6127) slapd.access(5) Fix to use expand (ITS#6179) slapd.conf(5) document default modulepath (ITS#5829) slapd.conf(5) pidfile/argsfile description fix (ITS#5975) slapd-config(5) document default modulepath (ITS#5829) slapd-config(5) pidfile/argsfile description fix (ITS#5975) slapo-constraint(5) clarify URI example (ITS#6118) slapo-unique(5) explicitly note rootdn requirement (ITS#6108) slapadd(8) note it does indexing (ITS#6160) OpenLDAP 2.4.16 Release (2009/04/05) Fixed libldap GnuTLS with x509v1 CA certs (ITS#5992) Fixed libldap GnuTLS with CA chains (ITS#5991) Fixed libldap GnuTLS TLSVerifyClient try (ITS#5981) Fixed libldap segfault in checking cert/DN (ITS#5976) Fixed libldap peer cert double free (ITS#5849) Fixed libldap referral chasing (ITS#5980) Fixed slapd backglue with empty DBs (ITS#5986) Fixed slapd ctxcsn race condition (ITS#6001) Fixed slapd debug message (ITS#6027) Fixed slapd redundant module loading (ITS#6030) Fixed slapd schema_init freed value (ITS#6036) Fixed slapd syncrepl newCookie sync messages (ITS#5972) Fixed slapd syncrepl hang during shutdown (ITS#6011) Fixed slapd syncrepl too many MPR messages (ITS#6020) Fixed slapd syncrepl skipped entries with MPR (ITS#5988) Fixed slapd-bdb/hdb cachesize handling (ITS#5860) Fixed slapd-bdb/hdb with slapcat with empty dn (ITS#6006) Fixed slapd-bdb/hdb with NULL transactions (ITS#6012) Fixed slapd-ldap incorrect referral handling (ITS#6003,ITS#5916) Fixed slapd-ldap/meta with broken AD results (ITS#5977) Fixed slapd-ldap/meta with invalid attrs again (ITS#5959) Fixed slapo-accesslog interaction with ppolicy (ITS#5979) Fixed slapo-dynlist conversion to cn=config (ITS#6002) Fixed slapo-syncprov newCookie sync messages (ITS#5972) Fixed slapd-syncprov too many MPR messages (ITS#6020) Fixed slapo-syncprov consumer lockout (ITS#5985) Fixed slapo-syncprov modtarget tracking (ITS#5999) Fixed slapo-syncprov multiple CSN propagation (ITS#5973) Fixed slapo-syncprov race condition (ITS#6045) Fixed slapo-syncprov sending cookies without CSN (ITS#6024) Fixed slapo-syncprov skipped entries with MPR (ITS#5988) Fixed tools passphrase free (ITS#6014) Build Environment Cleaned up alloc/free functions for Windows (ITS#6005) Fixed running of autosave files in testsuite (ITS#6026) Documentation admin24 clarified MPR URI requirements (ITS#5942,ITS#5987) Added ldapexop(1) manual page (ITS#5982) slapd-ldap/meta(5) added missing TLS options (ITS#5989) OpenLDAP 2.4.15 Release (2009/02/24) Fixed libldap alias dereferencing in C API again (ITS#5916) Fixed libldap GnuTLS compilation (ITS#5955) Fixed slapd bconfig conversion again (ITS#5346) Fixed slapd behavior with superior objectClasses again (ITS#5517) Fixed slapd RFC4512 behavior with same attr in RDN (ITS#5968) Fixed slapd corrupt contextCSN (ITS#5947) Fixed slapd syncrepl order to match on add/delete (ITS#5954) Fixed slapd adding rdn with other values (ITS#5965) Fixed slapd-bdb/hdb behavior with unallocatable shm (ITS#5956) Fixed slapd-ldap/meta with entries with invalid attrs (ITS#5959) Fixed slapd-relay control initialization (ITS#5724) Fixed slapo-pcache caching invalid entries (ITS#5927) Fixed slapo-syncprov csn updates (ITS#5969) Fixed slapo-rwm objectClass preservation (ITS#5760) Fixed slapo-rwm rwm_bva_rewrite handling (ITS#5960) Build Environment Fixed tester library linking for windows (ITS#5740) OpenLDAP 2.4.14 Release (2009/02/14) Added libldap option to disable SASL host canonicalization (ITS#5812) Added libldap TLS_PROTOCOL_MIN (ITS#5655) Added libldap GnuTLS support for TLS_CIPHER_SUITE (ITS#5887) Added libldap GnuTLS setting random file (ITS#5462) Added libldap alias dereferencing in C API (ITS#5916) Fixed libldap chasing multiple referrals (ITS#5853) Fixed libldap deref handling (ITS#5768) Fixed libldap NULL pointer deref (ITS#5934) Fixed libldap peer cert memory leak (ITS#5849) Fixed libldap interaction with GnuTLS CN IP-based matches (ITS#5789) Fixed libldap intermediate response behavior (ITS#5896) Fixed libldap IPv6 address handling (ITS#5937) Fixed libldap_r deref building (ITS#5768) Fixed libldap_r slapd lockup when paused during shutdown (ITS#5841) Added slapd syncrepl default retry setting (ITS#5825) Added slapd val.regex expansion (ITS#5804) Added slapd TLS_PROTOCOL_MIN (ITS#5655) Added slapd slapi_pw_find (ITS#2615,ITS#4359) Added slapd compatibility with MSAD ranged values (ITS#5927) Fixed slapd bconfig to return error codes (ITS#5867) Fixed slapd bconfig encoding incorrectly (ITS#5897) Fixed slapd bconfig dangling pointers (ITS#5924) Fixed slapd behavior with superior objectClasses (ITS#5517) Fixed slapd connection assert (ITS#5835) Fixed slapd epoll handling (ITS#5886) Fixed slapd frontend/backend options handling (ITS#5857) Fixed slapd glue with MPR (ITS#5925) Fixed slapd logging on Windows (ITS#5392) Fixed slapd listener comparison (ITS#5613) Fixed slapd manageDSAit with glue entries (ITS#5921) Fixed slapd relax behavior with structuralObjectClass (ITS#5792) Fixed slapd syncrepl rename handling (ITS#5809) Fixed slapd syncrepl MPR when adding new server (ITS#5850) Fixed slapd syncrepl MPR with deleted entries (ITS#5843) Fixed slapd syncrepl replication with glued DB (ITS#5866) Fixed slapd syncrepl replication with moddn (ITS#5901) Fixed slapd syncrepl replication with referrals (ITS#5881) Fixed slapd syncrepl replication with config tree (ITS#5935) Fixed slapd wake_sds close on Windows (ITS#5855) Fixed slapd-bdb/hdb dncachesize handling (ITS#5860) Fixed slapd-bdb/hdb RFC4528 control support (ITS#5861) Fixed slapd-bdb/hdb trickle task usage (ITS#5864) Fixed slapd-hdb idlcache with empty suffix (ITS#5859) Fixed slapd-ldap idassert-bind validity checking (ITS#5863) Fixed slapd-ldap/meta RFC4525 increment support (ITS#5912) Fixed slapd-ldap/meta search dereferencing (ITS#5916) Fixed slapd-ldap/meta with intermediate response (ITS#5931) Fixed slapd-ldif numerous bugs (ITS#5408) Fixed slapd-ldif rename on same DN (ITS#5319) Fixed slapd-ldif deadlock (ITS#5329) Fixed slapd-meta double response sending (ITS#5854) Fixed slapd-meta alias deref for retry (ITS#5889) Fixed slapd-relay recursion detection (ITS#5943) Fixed slapd-sock descriptor leak (ITS#5939) Fixed slapo-accesslog on glued dbs (ITS#5907) Fixed slapo-dynlist handling of flags (ITS#5898) Fixed slapo-memberof multiple instantiation (ITS#5903) Fixed slapo-pcache filter sorting (ITS#5756) Fixed slapo-ppolicy to not be global (ITS#5858) Fixed slapo-rwm double free (ITS#5923) Fixed slapo-rwm with back-config (ITS#5906) Fixed slapo-rwm olcRwmRewrite modification (ITS#5940) Added slapo-rwm newRDN rewriting (ITS#5834) Added slapadd progress meter (ITS#5922) Updated contrib/addpartial module (ITS#5764) Added contrib/cloak module (ITS#5872) Added contrib/smbk5pwd gcrypt support (ITS#5410) Added contrib/passwd sha2 support (ITS#5660) Build Environment Fixed test006 appending to log file (ITS#5910) Fixed test036,test039 behavior on error (ITS#5893) Fixed test048 sed pathname substitution (ITS#5910) Fixed test049,test050 to work on windows (ITS#5842) Updated test017,test018,test019 to cover more cases (ITS#5883) Removed patch for BerkeleyDB 4.7.25 (Official patch available) Fixed MSVC 9.0 build issues (ITS#5888) Fixed gss detection on Solaris (ITS#5846) Fixed uuid_create/uuid_unparse_lower detection (ITS#5905) Fixed liblutil tavl_delete to macroize constants (ITS#5909) Documentation admin24 added limits chapter (ITS#5818) admin24 access-control clarify global ACLS (ITS#5851,ITS#5852) admin24 search on nested naming contexts (ITS#5788) admin24 consistent loglevel documentation (ITS#5904) slapd-bdb/hdb expansion on dncachesize behavior (ITS#5721) slapo-constraint(5) example fix (ITS#5895) slap*(8) man pages should mention slapd-config (ITS#5828) slapacl(8c) fix wording (ITS#5918) slapd(8) document sid (ITS#5873) slapd.access(5) clarify global ACLS (ITS#5851,ITS#5852) slapadd/cat/index(8) note -n 0 for slapd-config (ITS#5891) Added SEE ALSO slapd-config(5) to relevant man pages (ITS#5914) OpenLDAP 2.4.13 Release (2008/11/24) Added libldap dereference control support (ITS#5768) Fixed libldap parameter checking (ITS#5817) Fixed liblutil hex conversion (ITS#5699) Fixed liblutil returning undefined data (ITS#5748) Fixed libldap error code return (ITS#5762) Fixed libldap interaction with GnuTLS CN IP-based matches (ITS#5789) Fixed libldap MAXHOSTNAMELEN typo (ITS#5815) Fixed libldap Ipv6 detection (ITS#5739) Fixed libldap setuid usage with .ldaprc (ITS#4750) Fixed slapacl crash (ITS#5820) Fixed slapd acl checks on ADD (ITS#4556,ITS#5723) Fixed slapd acl application to newly created backends (ITS#5572) Fixed slapd #if/#elif issues in thread includes (ITS#5824) Added slapd keyword add_content_acl for add checks (ITS#4556,ITS#5723) Fixed slapd concurrent access to connections (ITS#5814) Fixed slapd config backend olcLogFile support (ITS#5765) Fixed slapd contextCSN pending list (ITS#5709) Fixed slapd control criticality (ITS#5785) Added slapd dn.this search limits (ITS#5734) Fixed slapd error status on shutdown (ITS#5745) Fixed slapd filter substring handling (ITS#5803) Fixed slapd nameUIDPretty bitstring parsing (ITS#5750) Fixed slapd null termination of password (ITS#5794) Fixed slapd overlay/database open with real structure (ITS#5724) Fixed slapd parsing of read entry control (ITS#5741) Added slapd PMI schema (ITS#5695) Added slapd private databases in global overlays (ITS#5735,ITS#5736) Fixed slapd rdn generation when it isn't specified (ITS#5819) Fixed slapd slapd.conf validation to LDIF (ITS#5755) Fixed slapd startup scan for CSN (ITS#5640) Fixed slapd statslog printing of released entry (ITS#5775) Added slapd support for certificateListExactMatch (ITS#5700) Fixed slapd syncrepl event loss (ITS#5710) Fixed slapd syncrepl MOD of attrs with no EQ rule (ITS#5781) Fixed slapd syncrepl rename handling (ITS#5809) Fixed slapd syncrepl schema checking (ITS#5798) Fixed slapd syncrepl filter leak (ITS#5826) Fixed slapd undef promote (ITS#5783,ITS#5795) Added slapd What failed? control (ITS#5784) Fixed slapd-bdb/hdb invalid db crash (ITS#5698) Added slapd-bdb/hdb dbpagesize keyword Added slapd-bdb/hdb checksum keyword Fixed slapd-bdb/hdb indexing of entryDN (ITS#5790) Fixed slapd-bdb/hdb lookup of entryDN with equality (ITS#5791) Fixed slapd-bdb/hdb uninitialized bli_flag Fixed slapd-ldap snprintf buffer overflow test (ITS#4467) Fixed slapd-ldap search stop on minor failure (ITS#5816) Fixed slapd-ldif file rename on windows (ITS#5774) Fixed slapd-null read controls support (ITS#5757) Fixed slapd-sql value length with right index (ITS#5779) Fixed slapo-chain/translucent back-config support (ITS#5736) Fixed slapo-chain SEGV with search references (ITS#5742) Fixed slapo-collect compile with C89 (ITS#5747) Added slapo-constraint support for LDAP URI constraints (ITS#5704) Added slapo-constraint support for constraining rename (ITS#5703) Added slapo-constraint support for relax control (ITS#5705) Added slapo-constraint "set" type (ITS#5702) Fixed slapo-constraint filter parsing error (ITS#5751) Added slapo-dynlist URI restriction ability (ITS#5761) Fixed slapo-ppolicy unaligned BerElement (ITS#5770) Fixed slapo-rwm objectClass preservation (ITS#5760) Fixed slapo-rwm rewriting undefined filter (ITS#5731) Fixed slapo-rwm rewritten DN-valued attrs (ITS#5772) Fixed slapo-rwm reusing freed filter (ITS#5732) Fixed slapo-rwm entry get (ITS#5773) Fixed slapo-syncprov runqueue removal (ITS#5776) Fixed slapo-syncprov unreplicatable ops (ITS#5709) Fixed slapo-syncprov psearch leak (ITS#5827) Added slapo-translucent try local bind when remote fails (ITS#5656) Added slapo-translucent support for PasswordModify exop (ITS#5656) Fixed tools simple bind without SASL (ITS#5753) Fixed tools unaligned BerElement (ITS#5770) Fixed contrib nssov crash on empty groups (ITS#5800) Fixed contrib nssov crash with nssov-map (ITS#5801) Fixed contrib nssov filter and search limits (ITS#5802) Added contrib smbk5pwd honor principal expiration (ITS#5766) Build Environment Added ldapurl command Added slapd GSSAPI refactoring (ITS#5369) Added slapo-deref overlay (ITS#5768) Documentation admin24 added olcLimits to example (ITS#5746) admin24 consolidated on whitespace (ITS#5759) slapd.conf,config(5) subordinate/olcSubordinate keyword (ITS#5788) slapd.conf(5) fixed disable keyword for limits (ITS#5821) slapo-dds(5) manageDIT to relax (ITS#5780) slapo-dds(5) rootdn requirement added (ITS#5811) slapo-syncprov(5) sessionlog clarification (ITS#5806) OpenLDAP 2.4.12 Release (2008/10/12) Fixed libldap ldap_utf8_strchar arguments (ITS#5720) Fixed libldap TLS_CRLFILE (ITS#5677) Fixed liblutil executables on Windows (ITS#5604) Fixed liblutil microsecond overflows on Windows (ITS#5668) Fixed librewrite memory handling (ITS#5691) Fixed slapd aci performance (ITS#5636) Fixed slapd aci's with sets (ITS#5627) Fixed slapd attribute leak (ITS#5683) Fixed slapd config backend with index greater than sibs (ITS#5684) Fixed slapd custom attribute inheritance (ITS#5642) Fixed slapd dynacl mask handling (ITS#5637) Fixed slapd firstComponentMatch normalization (ITS#5634) Added slapd caseIgnoreListMatch (ITS#5608) Fixed slapd connection events enabled twice (ITS#5725) Fixed slapd memory handling (ITS#5691) Fixed slapd objectClass canonicalization (ITS#5681) Fixed slapd objectClass termination (ITS#5682) Fixed slapd overlay control registration (ITS#5649) Fixed slapd runqueue checking (ITS#5726) Fixed slapd spurious text output (ITS#5688) Fixed slapd socket closing on Windows (ITS#5606) Fixed slapd sortvals comparison (ITS#5578) Added slapd substitute syntax support (ITS#5663) Fixed slapd syncrepl contextCSN detection (ITS#5675) Fixed slapd syncrepl error logging (ITS#5618) Fixed slapd syncrepl runqueue interval (ITS#5719) Fixed slapd-bdb entry return if attr not present (ITS#5650) Fixed slapd-bdb olcDbMode syntax (ITS#5713) Fixed slapd-bdb/hdb release search entries earlier (ITS#5728,ITS#5730) Fixed slapd-bdb/hdb subtree search with empty suffix (ITS#5729) Fixed slapd-dnssrv memory handling (ITS#5691) Fixed slapd-ldap,slapd-meta invalid filter behavior (ITS#5614) Fixed slapd-meta memory handling (ITS#5691) Fixed slapd-meta objectClass filtering (ITS#5647) Fixed slapd-meta quarantine behavior (ITS#5592) Added slapd-ndb experimental backend Fixed slapd-relay initialization (ITS#5643) Fixed slapd-sql freeing of connection (ITS#5607) Fixed slapd-sql fault on NULL fields (ITS#5653) Fixed slapo-accesslog entryCSN generation on purge (ITS#5694) Fixed slapo-constraint string termination (ITS#5609) Fixed slapo-dynlist expansion with mapped attributes (ITS#5717) Fixed slapo-memberof internal operations DN (ITS#5622) Fixed slapo-pcache attrset crash (ITS#5665) Fixed slapo-pcache caching with invalid schema (ITS#5680) Fixed slapo-ppolicy control return on password modify exop (ITS#5711) Fixed slapo-rwm callback cleanup (ITS#5601,ITS#5687) Fixed slapo-rwm attr mapping and merging (ITS#5624) Fixed slapo-rwm objectClass filtering (ITS#5647) Fixed slapo-translucent back-config support (ITS#5689) Fixed slapo-translucent filter usage on merged entries (ITS#5679) Fixed slapo-unique filter validation (ITS#5581) Fixed slapo-unique suffix testing (ITS#5641) Build Environment Fixed ODBC library detection (ITS#5602) Removed pre-BerkeleyDB 4.4 support Added BerkeleyDB 4.7 support (ITS#5523) Included patch for BerkeleyDB 4.7.25 (build/db.4.7.25.patch) Added slapo-collect overlay with enhancements(ITS#5659) Documentation Added slapd-ldap(5), slapd-meta(5) noundeffilter (ITS#5614) Fixed slapd-ldap(5), slapd-meta(5), slapo-pcache(5) schema requirements (ITS#5680) Added slapo-collect(5) man page (ITS#5706) Added slapo-pcache(5) proxycheckcacheability option (ITS#5680) Added slapo-retcode(5) retcode.conf location (ITS#5633) admin24 dontusecopy control update (ITS#5718) admin24 guide updates (ITS#5616) admin24 octetString fix (ITS#5670) OpenLDAP 2.4.11 Release (2008/07/16) Fixed liblber ber_get_next length decoding (ITS#5580) Added libldap assertion control (ITS#5560) Fixed libldap GnuTLS CRL result handling (ITS#5577) Fixed libldap GnuTLS SSF computation (ITS#5585) Fixed liblutil missing return code (ITS#5615) Fixed slapd cert serial number parsing (ITS#5588) Fixed slapd check for structural_class failures (ITS#5540) Fixed slapd config backend renumbering (ITS#5571) Fixed slapd configContext OID (ITS#5383) Fixed slapd crash with no listeners (ITS#5563) Fixed slapd equality rules for olcRootDN/olcSchemaDN (ITS#5540) Fixed slapd sets memory leak (ITS#5557) Fixed slapd sortvals binary search (ITS#5578) Fixed slapd syncrepl updates with multiple providers (ITS#5597) Fixed slapd syncrepl superior objectClass delete/add (ITS#5600) Fixed slapd syncrepl/slapo-syncprov contextCSN updates as internal ops (ITS#5596) Added slapd-ldap/slapd-meta option to filter out search references (ITS#5593) Fixed slapd-meta link to slapd-ldap (ITS#5355) Fixed slapd-sock, back-shell buffer count (ITS#5558) Fixed slapo-dynlist dg attrs lookup (ITS#5583) Fixed slapo-dynlist entry release (ITS#5135) Fixed slapo-memberof replace handling (ITS#5584) Added slapo-nssov contrib module Fixed slapo-pcache handling of negative search caches (ITS#5546) Fixed slapo-ppolicy DNs with whitespaces (ITS#5552) Fixed slapo-ppolicy modify with internal ops (ITS#5569) Fixed slapo-syncprov ACL evaluation (ITS#5548) Fixed slapo-syncprov crash with delcsn (ITS#5589) Fixed slapo-syncprov full reload (ITS#5564) Fixed slapo-syncprov missing olcSpReloadHint attr(ITS#5591) Fixed slapo-unique filter normalization (ITS#5581) Fixed contrib smbk5pwd terminator (ITS#5575) Build Environment Fixed test048 to skip if threads is not available (ITS#5529) Documentation Added slapo-pcache(5) sizelimit caching (ITS#5559) Added slapd-access(5) add and delete privs (ITS#5566) admin24 GnuTLS documentation (ITS#5554) OpenLDAP 2.4.10 Release (2008/06/08) Fixed libldap file descriptor leak with SELinux (ITS#5507) Fixed libldap ld_defconn cleanup if it was freed (ITS#5518, ITS#5525) Fixed libldap msgid handling (ITS#5318) Fixed libldap t61 infinite loop (ITS#5542) Fixed libldap_r missing stubs (ITS#5519) Fixed slapd initialization of sr_msgid, rs->sr_tag (ITS#5461) Fixed slapd missing termination of integerFilter keys (ITS#5503) Fixed slapd multiple attrs in URI (ITS#5516) Fixed slapd sasl_ssf retrieval (ITS#5403) Fixed slapd socket assert (ITS#5489) Fixed slapd syncrepl cookie (ITS#5536) Fixed slapd-bdb/hdb MAXPATHLEN (ITS#5531) Fixed slapd-bdb indexing in single ADD/MOD (ITS#5521) Fixed slapd-ldap entry_get() op-dependent behavior (ITS#5513) Fixed slapd-meta quarantine crash (ITS#5522) Fixed slapo-refint to allow setting modifiers name (ITS#5505) Fixed slapo-syncprov contextCSN passing on syncprov consumers (ITS#5488) Fixed slapo-syncprov csn update with delta-syncrepl (ITS#5493) Fixed slapo-syncprov op2.o_extra reset (ITS#5501, #5506) Fixed slapo-syncprov searching wrong backend (ITS#5487) Fixed slapo-syncprov sending ops without queued CSNs (ITS#5465) Fixed slapo-syncprov max csn search on startup (ITS#5537) Fixed slapo-unique config structs (ITS#5526) Fixed slapo-unique filter terminator (ITS#5511) Documentation Add search privileges documentation (ITS#5512) admin24 security document updates (ITS#5524) OpenLDAP 2.4.9 Release (2008/05/07) Fixed libldap to use unsigned port (ITS#5436) Fixed libldap error message for missing close paren (ITS#5458) Fixed libldap_r tpool pause checks (ITS#5364, #5407) Fixed slapcat error checking (ITS#5387) Fixed slapd abstract objectClass inheritance check (ITS#5474) Fixed slapd add operations requiring naming attrs (ITS#5412) Fixed slapd connection handling (ITS#5469) Fixed slapd delta-syncrepl resync (ITS#5378) Fixed slapd frontendDB backend selection (ITS#5419) Fixed slapd pagedresults stale state (ITS#5409) Fixed slapd pointer dereference (ITS#5388) Fixed slapd null argument dereference (ITS#5435) Fixed slapd REP_ENTRY flags (ITS#5340) Fixed slapd sets attribute description parsing (ITS#5402) Fixed slapd syncrepl hang on back-config (ITS#5407) Fixed slapd syncrepl compare_csns crash (ITS#5413) Fixed slapd syncrepl contextCSN update clash (ITS#5426) Fixed slapd syncrepl/glue failure (ITS#5430) Fixed slapd syncrepl crash on empty CSN (ITS#5432) Fixed slapd syncrepl refreshAndPersist (ITS#5454) Fixed slapd syncrepl modrdn processing (ITS#5397) Fixed slapd syncrepl MPR partial refresh (ITS#5470) Fixed slapd value list termination (ITS#5450) Fixed slapd/slapo-accesslog rq mutex usage (ITS#5442) Fixed slapd-bdb ID_NOCACHE handling (ITS#5439) Fixed slapd-bdb entryinfo state if db_lock fails (ITS#5455) Fixed slapd-bdb referral rewrite (ITS#5339) Fixed slapd-config overlay stacking (ITS#5346) Fixed slapd-config attribute publishing (ITS#5383) Fixed slapd-ldap connection handler (ITS#5404) Fixed slapd-ldif file name handling & multi-suffix/dir catch (ITS#5408) Fixed slapd-meta connections on error (ITS#5440) Fixed slapd-meta crash on search (ITS#5481) Fixed slapo-accesslog null callback stack crash (ITS#5490) Fixed slapo-auditlog unnecessary syscall (ITS#5441) Added slapo-dynlist mapping to dynamic attrs generation (ITS#5466) Fixed slapo-refint dnSubtreeMatch (ITS#5427) Fixed slapo-refint global referential integrity (ITS#5428) Fixed slapo-syncprov psearch on closed connection (ITS#5401) Fixed slapo-syncprov psearch task delay (ITS#5405) Fixed slapo-syncprov psearch filter identity (ITS#5418, #5486) Fixed slapo-syncprov/glue contextCSN update (ITS#5433) Fixed slapo-syncprov/glue search ops (ITS#5434) Fixed slapo-syncprov null cookie (ITS#5437,#5444) Fixed slapo-syncprov double-free (ITS#5445) Fixed slapo-syncprov free syncop correctly (ITS#5484) Fixed slapo-syncprov glue deadlock (ITS#5451) Build Environment Fixed leave function naming for OSF1 (ITS#5411) Documentation Fixed slapd.access(5) authz-regexp documented behavior (ITS#5400) Fixed slapd.meta(5) idassert-* documentation (ITS#5406) admin24 delta-syncrepl documentation (ITS#5476) admin24 set documentation (ITS#5278,ITS#5279,ITS#5281) admin24 slapo-ppolicy documentation (ITS#5479) admin24 syncrepl directives update (ITS#5425) OpenLDAP 2.4.8 Release (2008/02/19) Fixed ldapmodify verbose logging (ITS#5247) Fixed ldapdelete with sizelimit (ITS#5294) Fixed ldapdelete with subentries control (ITS#5293) Fixed ldapsearch exit code init (ITS#5317) Fixed libldap extended decoding (ITS#5304) Fixed libldap filter abort (ITS#5300) Fixed libldap ldap_parse_sasl_bind_result (ITS#5263) Fixed libldap result codes for open (ITS#5338) Fixed libldap search timeout crash (ITS#5291) Fixed libldap paged results crash (ITS#5315) Fixed libldap cipher suite with GnuTLS (ITS#5341) Fixed slapd support for 2.1 CSN (ITS#5348) Fixed slapd include handling (ITS#5276) Fixed slapd modrdn check for valid new DN (ITS#5344) Fixed slapd multi-step SASL binds (ITS#5298) Fixed slapd non-atomic signal variables (ITS#5248) Fixed slapd overlay ordering when moving to slapd.d (ITS#5284) Fixed slapd NULL printf (ITS#5264) Fixed slapd NULL set values (ITS#5286) Fixed slapd SEGV with SASL/OTP (ITS#5259) Fixed slapd timestamp race condition (ITS#5370) Fixed slapd cn=config crash on delete (ITS#5343) Fixed slapd cn=config global acls (ITS#5352) Fixed slapd truncated cookie (ITS#5362) Fixed slapd sasl with CLEARTEXT (ITS#5368) Fixed slapd str2entry with no attrs (ITS#5308) Fixed slapd TLSVerifyClient default (ITS#5360) Fixed slapd HAVE_TLS dependency (ITS#5379) Fixed slapd delta-syncrepl refresh mode (ITS#5376) Fixed slapd ACL sets URI attrs (ITS#5384) Fixed slapd invalid entryUUID filter (ITS#5386) Fixed slapd-bdb idlcache on adds (ITS#5086) Fixed slapd-bdb crash with modrdn (ITS#5358) Fixed slapd-bdb SEGV with bdb4.6 (ITS#5322) Fixed slapd-bdb modrdn to same dn (ITS#5319) Fixed slapd-bdb MPR (ITS#5332) Added slapd-bdb/slapd-hdb DB encryption (ITS#5359) Fixed slapd-ldif delete (ITS#5265) Fixed slapd-meta link to slapd-ldap (ITS#5355) Fixed slapd-meta setting of sm_nvalues (ITS#5375) Fixed slapd-monitor crash (ITS#5311) Fixed slapd-relay compare (ITS#4937) Added slapd-sock (ITS#4094) Fixed slapo-accesslog cleanup on successful response (ITS#5374) Added slapo-autogroup contrib module (ITS#5145) Added slapo-constraint cross-attribute constraints (ITS#4987) Fixed slapo-memberof objectClass inheritance (ITS#5299) Added slapo-memberof global overlay support (ITS#5301) Fixed slapo-memberof leak (ITS#5302) Fixed slapo-ppolicy only password check with policy (ITS#5285) Fixed slapo-ppolicy del/replace password without new one (ITS#5373) Fixed slapo-syncprov hang on checkpoint (ITS#5261) Added slapo-translucent local searching (ITS#5283) Removed lint Build Environment Fixed libldap_r threaded library linking (ITS#4982) Fixed libldap use of %n (ITS#5324) Fixed test047 to skip if rwm is not available (ITS#5292) Documentation DB_CONFIG.example URL wrong in comments (ITS#5288) Add cn=config example for auditlog (ITS#5245) ldapmodify(1) clarification for RFC2849 (ITS#5312) OpenLDAP 2.4.7 Release (2007/12/14) Added slapd ordered indexing of integer attributes (ITS#5239) Fixed slapd paged results control handling (ITS#5191) Fixed slapd sasl-host parsing (ITS#5209) Fixed slapd filter normalization (ITS#5212) Fixed slapd multiple suffix checking (ITS#5186) Fixed slapd paged results handling when using rootdn (ITS#5230) Fixed slapd syncrepl presentlist handling (ITS#5231) Fixed slapd core schema 'c' definition for RFC4519 (ITS#5236) Fixed slapd 3-way multi-provider replication (ITS#5238) Fixed slapd hash collisions in index slots (ITS#5183) Fixed slapd replication of dSAOperation attributes (ITS#5268) Fixed slapadd contextCSN updating (ITS#5225) Fixed slapd-bdb/hdb to report and fail on internal errors (ITS#5232) Fixed slapd-bdb/hdb dn2entry lock bug (ITS#5257) Fixed slapd-bdb/hdb dn2id lock bug (ITS#5262) Fixed slapd-hdb caching on rename ops (ITS#5221) Fixed slapo-accesslog abandoned op cleanup (ITS#5161) Fixed slapo-dds deleting from nonexistent db (ITS#5267) Fixed slapo-memberOf deleted values saving (ITS#5258) Fixed slapo-pcache op->o_abandon handling (ITS#5187) Fixed slapo-ppolicy single password check on modify (ITS#5146) Fixed slapo-ppolicy internal search (ITS#5235) Fixed slapo-syncprov refresh and persist cookie sending (ITS#5210) Fixed slapo-syncprov ignore invalid cookies (ITS#5211) Fixed slapo-translucent interaction with slapo-rwm (ITS#4889) Updated contrib addpartial module (ITS#3593) Build Environment Fixed liblber socket library linking (ITS#5224) Fixed Windows slapd.def rules (ITS#5215) Documentation Fixed grammar errors (ITS#5223) Refint overlay doc contribution (ITS#5217) Dynamic Lists doc contribution to the admin guide (ITS#5216) Fixed ldappasswd(1) and ldapmodify(1) typos (ITS#5269) Fixed domain factor typos (ITS#5237) Fixed slapd.conf(5) maxderefdepth default value typo (ITS#5200) Clarified slapd.conf(5) limits issues in syncrepl (ITS#5243) Fixed slapd-config(5) maxderefdepth default value typo (ITS#5200) Patches for minor typos in man pages (ITS#5228) admin24/replication.sdf spelling (ITS#5270) OpenLDAP 2.4.6 Release (2007/10/31) Initial release for "general use". licenses/alt-openldap11/LICENSE000064400000004246152527227020012112 0ustar00The OpenLDAP Public License Version 2.8, 17 August 2003 Redistribution and use of this software and associated documentation ("Software"), with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source form must retain copyright statements and notices, 2. Redistributions in binary form must reproduce applicable copyright statements and notices, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution, and 3. Redistributions must contain a verbatim copy of this document. The OpenLDAP Foundation may revise this license from time to time. Each revision is distinguished by a version number. You may use this Software under terms of this license revision or under the terms of any subsequent revision of the license. THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE 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. The names of the authors and copyright holders must not be used in advertising or otherwise to promote the sale, use or other dealing in this Software without specific, written prior permission. Title to copyright in this Software shall at all times remain with copyright holders. OpenLDAP is a registered trademark of the OpenLDAP Foundation. Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, California, USA. All Rights Reserved. Permission to copy and distribute verbatim copies of this document is granted. licenses/alt-openldap11/COPYRIGHT000064400000004451152527227020012376 0ustar00Copyright 1998-2021 The OpenLDAP Foundation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. A copy of this license is available in the file LICENSE in the top-level directory of the distribution or, alternatively, at . OpenLDAP is a registered trademark of the OpenLDAP Foundation. Individual files and/or contributed packages may be copyright by other parties and/or subject to additional restrictions. This work is derived from the University of Michigan LDAP v3.3 distribution. Information concerning this software is available at . This work also contains materials derived from public sources. Additional information about OpenLDAP can be obtained at . --- Portions Copyright 1998-2012 Kurt D. Zeilenga. Portions Copyright 1998-2006 Net Boolean Incorporated. Portions Copyright 2001-2006 IBM Corporation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted only as authorized by the OpenLDAP Public License. --- Portions Copyright 1999-2008 Howard Y.H. Chu. Portions Copyright 1999-2008 Symas Corporation. Portions Copyright 1998-2003 Hallvard B. Furuseth. Portions Copyright 2007-2011 Gavin Henry. Portions Copyright 2007-2011 Suretec Systems Ltd. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that this notice is preserved. The names of the copyright holders may not be used to endorse or promote products derived from this software without their specific prior written permission. This software is provided ``as is'' without express or implied warranty. --- Portions Copyright (c) 1992-1996 Regents of the University of Michigan. All rights reserved. Redistribution and use in source and binary forms are permitted provided that this notice is preserved and that due credit is given to the University of Michigan at Ann Arbor. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. This software is provided ``as is'' without express or implied warranty. man/man5/ldif.5000064400000015116152527227020007173 0ustar00.lf 1 stdin .TH LDIF 5 "2021/06/03" "OpenLDAP 2.4.59" .\" $OpenLDAP$ .\" Copyright 1998-2021 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldif \- LDAP Data Interchange Format .SH DESCRIPTION The LDAP Data Interchange Format (LDIF) is used to represent LDAP entries and change records in text form. LDAP tools, such as .BR ldapadd (1) and .BR ldapsearch (1), read and write LDIF entry records. .BR ldapmodify (1) reads LDIF change records. .LP This manual page provides a basic description of LDIF. A formal specification of LDIF is published in RFC 2849. .SH ENTRY RECORDS .LP LDIF entry records are used to represent directory entries. The basic form of an entry record is: .LP .nf .ft tt dn: : : :: :< ... .ft .fi .LP The value may be specified as UTF-8 text or as base64 encoded data, or a URI may be provided to the location of the attribute value. .LP A line may be continued by starting the next line with a single space or tab, e.g., .LP .nf .ft tt dn: cn=Barbara J Jensen,dc=exam ple,dc=com .ft .fi .LP Lines beginning with a sharp sign ('#') are ignored. .LP Multiple attribute values are specified on separate lines, e.g., .LP .nf .ft tt cn: Barbara J Jensen cn: Babs Jensen .ft .fi .LP If an value contains a non-printing character, or begins with a space or a colon ':', the is followed by a double colon and the value is encoded in base 64 notation. e.g., the value " begins with a space" would be encoded like this: .LP .nf .ft tt cn:: IGJlZ2lucyB3aXRoIGEgc3BhY2U= .ft .fi .LP If the attribute value is located in a file, the is followed by a ':<' and a file: URI. e.g., the value contained in the file /tmp/value would be listed like this: .LP .nf .ft tt cn:< file:///tmp/value .ft .fi Other URI schemes (ftp,http) may be supported as well. .LP Multiple entries within the same LDIF file are separated by blank lines. .SH ENTRY RECORD EXAMPLE Here is an example of an LDIF file containing three entries. .LP .nf .ft tt dn: cn=Barbara J Jensen,dc=example,dc=com cn: Barbara J Jensen cn: Babs Jensen objectclass: person description:< file:///tmp/babs sn: Jensen dn: cn=Bjorn J Jensen,dc=example,dc=com cn: Bjorn J Jensen cn: Bjorn Jensen objectclass: person sn: Jensen dn: cn=Jennifer J Jensen,dc=example,dc=com cn: Jennifer J Jensen cn: Jennifer Jensen objectclass: person sn: Jensen jpegPhoto:: /9j/4AAQSkZJRgABAAAAAQABAAD/2wBDABALD A4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQ ERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVG ... .ft .fi .LP Note that the description in Barbara Jensen's entry is read from file:///tmp/babs and the jpegPhoto in Jennifer Jensen's entry is encoded using base 64. .SH CHANGE RECORDS LDIF change records are used to represent directory change requests. Each change record starts with line indicating the distinguished name of the entry being changed: .LP .nf dn: .fi .LP .nf changetype: <[modify|add|delete|modrdn]> .fi .LP Finally, the change information itself is given, the format of which depends on what kind of change was specified above. For a \fIchangetype\fP of \fImodify\fP, the format is one or more of the following: .LP .nf add: : : ... \- .fi .LP Or, for a replace modification: .LP .nf replace: : : ... \- .fi .LP If no \fIattributetype\fP lines are given to replace, the entire attribute is to be deleted (if present). .LP Or, for a delete modification: .LP .nf delete: : : ... \- .fi .LP If no \fIattributetype\fP lines are given to delete, the entire attribute is to be deleted. .LP For a \fIchangetype\fP of \fIadd\fP, the format is: .LP .nf : : ... : : .fi .LP For a \fIchangetype\fP of \fImodrdn\fP or \fImoddn\fP, the format is: .LP .nf newrdn: deleteoldrdn: 0 | 1 newsuperior: .fi .LP where a value of 1 for deleteoldrdn means to delete the values forming the old rdn from the entry, and a value of 0 means to leave the values as non-distinguished attributes in the entry. The newsuperior line is optional and, if present, specifies the new superior to move the entry to. .LP For a \fIchangetype\fP of \fIdelete\fP, no additional information is needed in the record. .LP Note that attribute values may be presented using base64 or in files as described for entry records. Lines in change records may be continued in the manner described for entry records as well. .SH CHANGE RECORD EXAMPLE The following sample LDIF file contains a change record of each type of change. .LP .nf dn: cn=Babs Jensen,dc=example,dc=com changetype: add objectclass: person objectclass: extensibleObject cn: babs cn: babs jensen sn: jensen dn: cn=Babs Jensen,dc=example,dc=com changetype: modify add: givenName givenName: Barbara givenName: babs \- replace: description description: the fabulous babs \- delete: sn sn: jensen \- dn: cn=Babs Jensen,dc=example,dc=com changetype: modrdn newrdn: cn=Barbara J Jensen deleteoldrdn: 0 newsuperior: ou=People,dc=example,dc=com dn: cn=Barbara J Jensen,ou=People,dc=example,dc=com changetype: delete .fi .SH INCLUDE STATEMENT The LDIF parser has been extended to support an .B include statement for referencing other LDIF files. The .B include statement must be separated from other records by a blank line. The referenced file is specified using a file: URI and all of its contents are incorporated as if they were part of the original LDIF file. As above, other URI schemes may be supported. For example: .LP .nf dn: dc=example,dc=com objectclass: domain dc: example include: file:///tmp/example.com.ldif dn: dc=example,dc=org objectclass: domain dc: example .fi This feature is not part of the LDIF specification in RFC 2849 but is expected to appear in a future revision of this spec. It is supported by the .BR ldapadd (1), .BR ldapmodify (1), and .BR slapadd (8) commands. .SH SEE ALSO .BR ldap (3), .BR ldapsearch (1), .BR ldapadd (1), .BR ldapmodify (1), .BR slapadd (8), .BR slapcat (8), .BR slapd\-ldif (5). .LP "LDAP Data Interchange Format," Good, G., RFC 2849. .SH ACKNOWLEDGEMENTS .lf 1 ./../Project .\" Shared Project Acknowledgement Text .B "OpenLDAP Software" is developed and maintained by The OpenLDAP Project . .B "OpenLDAP Software" is derived from the University of Michigan LDAP 3.3 Release. .lf 278 stdin man/man5/ldap.conf.5000064400000044241152527227020010122 0ustar00.lf 1 stdin .TH LDAP.CONF 5 "2021/06/03" "OpenLDAP 2.4.59" .\" $OpenLDAP$ .\" Copyright 1998-2021 The OpenLDAP Foundation All Rights Reserved. .\" Copying restrictions apply. See COPYRIGHT/LICENSE. .SH NAME ldap.conf, .ldaprc \- LDAP configuration file/environment variables .SH SYNOPSIS /opt/alt/openldap11/etc/openldap/ldap.conf, ldaprc, .ldaprc, $LDAP .SH DESCRIPTION If the environment variable \fBLDAPNOINIT\fP is defined, all defaulting is disabled. .LP The .I ldap.conf configuration file is used to set system-wide defaults to be applied when running .I ldap clients. .LP Users may create an optional configuration file, .I ldaprc or .IR .ldaprc , in their home directory which will be used to override the system-wide defaults file. The file .I ldaprc in the current working directory is also used. .LP .LP Additional configuration files can be specified using the \fBLDAPCONF\fP and \fBLDAPRC\fP environment variables. \fBLDAPCONF\fP may be set to the path of a configuration file. This path can be absolute or relative to the current working directory. The \fBLDAPRC\fP, if defined, should be the basename of a file in the current working directory or in the user's home directory. .LP Environmental variables may also be used to augment the file based defaults. The name of the variable is the option name with an added prefix of \fBLDAP\fP. For example, to define \fBBASE\fP via the environment, set the variable \fBLDAPBASE\fP to the desired value. .LP Some options are user-only. Such options are ignored if present in the .I ldap.conf (or file specified by .BR LDAPCONF ). .LP Thus the following files and variables are read, in order: .nf variable $LDAPNOINIT, and if that is not set: system file /opt/alt/openldap11/etc/openldap/ldap.conf, user files $HOME/ldaprc, $HOME/.ldaprc, ./ldaprc, system file $LDAPCONF, user files $HOME/$LDAPRC, $HOME/.$LDAPRC, ./$LDAPRC, variables $LDAP. .fi Settings late in the list override earlier ones. .SH SYNTAX The configuration options are case-insensitive; their value, on a case by case basis, may be case-sensitive. .LP Blank lines are ignored. .br Lines beginning with a hash mark (`#') are comments, and ignored. .LP Valid lines are made of an option's name (a sequence of non-blanks, conventionally written in uppercase, although not required), followed by a value. The value starts with the first non-blank character after the option's name, and terminates at the end of the line, or at the last sequence of blanks before the end of the line. The tokenization of the value, if any, is delegated to the handler(s) for that option, if any. Quoting values that contain blanks may be incorrect, as the quotes would become part of the value. For example, .nf # Wrong - erroneous quotes: URI "ldap:// ldaps://" # Right - space-separated list of URIs, without quotes: URI ldap:// ldaps:// # Right - DN syntax needs quoting for Example, Inc: BASE ou=IT staff,o="Example, Inc",c=US # or: BASE ou=IT staff,o=Example\\2C Inc,c=US # Wrong - comment on same line as option: DEREF never # Never follow aliases .fi .LP A line cannot be longer than LINE_MAX, which should be more than 2000 bytes on all platforms. There is no mechanism to split a long line on multiple lines, either for beautification or to overcome the above limit. .SH OPTIONS The different configuration options are: .TP .B URI Specifies the URI(s) of an LDAP server(s) to which the .I LDAP library should connect. The URI scheme may be any of .BR ldap , .B ldaps or .BR ldapi , which refer to LDAP over TCP, LDAP over SSL (TLS) and LDAP over IPC (UNIX domain sockets), respectively. Each server's name can be specified as a domain-style name or an IP address literal. Optionally, the server's name can followed by a ':' and the port number the LDAP server is listening on. If no port number is provided, the default port for the scheme is used (389 for ldap://, 636 for ldaps://). For LDAP over IPC, .B name is the name of the socket, and no .B port is required, nor allowed; note that directory separators must be URL-encoded, like any other characters that are special to URLs; so the socket /usr/local/var/ldapi must be specified as ldapi://%2Fusr%2Flocal%2Fvar%2Fldapi A space separated list of URIs may be provided. .TP .B BASE Specifies the default base DN to use when performing ldap operations. The base must be specified as a Distinguished Name in LDAP format. .TP .B BINDDN Specifies the default bind DN to use when performing ldap operations. The bind DN must be specified as a Distinguished Name in LDAP format. .B This is a user-only option. .TP .B DEREF Specifies how alias dereferencing is done when performing a search. The .B can be specified as one of the following keywords: .RS .TP .B never Aliases are never dereferenced. This is the default. .TP .B searching Aliases are dereferenced in subordinates of the base object, but not in locating the base object of the search. .TP .B finding Aliases are only dereferenced when locating the base object of the search. .TP .B always Aliases are dereferenced both in searching and in locating the base object of the search. .RE .TP .TP .B HOST Specifies the name(s) of an LDAP server(s) to which the .I LDAP library should connect. Each server's name can be specified as a domain-style name or an IP address and optionally followed by a ':' and the port number the ldap server is listening on. A space separated list of hosts may be provided. .B HOST is deprecated in favor of .BR URI . .TP .B NETWORK_TIMEOUT Specifies the timeout (in seconds) after which the poll(2)/select(2) following a connect(2) returns in case of no activity. .TP .B PORT Specifies the default port used when connecting to LDAP servers(s). The port may be specified as a number. .B PORT is deprecated in favor of .BR URI. .TP .B REFERRALS Specifies if the client should automatically follow referrals returned by LDAP servers. The default is on. Note that the command line tools .BR ldapsearch (1) &co always override this option. .\" This should only be allowed via ldap_set_option(3) .\".TP .\".B RESTART .\"Determines whether the library should implicitly restart connections (FIXME). .TP .B SIZELIMIT Specifies a size limit (number of entries) to use when performing searches. The number should be a non-negative integer. \fISIZELIMIT\fP of zero (0) specifies a request for unlimited search size. Please note that the server may still apply any server-side limit on the amount of entries that can be returned by a search operation. .TP .B TIMELIMIT Specifies a time limit (in seconds) to use when performing searches. The number should be a non-negative integer. \fITIMELIMIT\fP of zero (0) specifies unlimited search time to be used. Please note that the server may still apply any server-side limit on the duration of a search operation. .TP .B VERSION {2|3} Specifies what version of the LDAP protocol should be used. .TP .B TIMEOUT Specifies a timeout (in seconds) after which calls to synchronous LDAP APIs will abort if no response is received. Also used for any .BR ldap_result (3) calls where a NULL timeout parameter is supplied. .SH SASL OPTIONS If OpenLDAP is built with Simple Authentication and Security Layer support, there are more options you can specify. .TP .B SASL_MECH Specifies the SASL mechanism to use. .TP .B SASL_REALM Specifies the SASL realm. .TP .B SASL_AUTHCID Specifies the authentication identity. .B This is a user-only option. .TP .B SASL_AUTHZID Specifies the proxy authorization identity. .B This is a user-only option. .TP .B SASL_SECPROPS Specifies Cyrus SASL security properties. The .B can be specified as a comma-separated list of the following: .RS .TP .B none (without any other properties) causes the properties defaults ("noanonymous,noplain") to be cleared. .TP .B noplain disables mechanisms susceptible to simple passive attacks. .TP .B noactive disables mechanisms susceptible to active attacks. .TP .B nodict disables mechanisms susceptible to passive dictionary attacks. .TP .B noanonymous disables mechanisms which support anonymous login. .TP .B forwardsec requires forward secrecy between sessions. .TP .B passcred requires mechanisms which pass client credentials (and allows mechanisms which can pass credentials to do so). .TP .B minssf= specifies the minimum acceptable .I security strength factor as an integer approximating the effective key length used for encryption. 0 (zero) implies no protection, 1 implies integrity protection only, 56 allows DES or other weak ciphers, 112 allows triple DES and other strong ciphers, 128 allows RC4, Blowfish and other modern strong ciphers. The default is 0. .TP .B maxssf= specifies the maximum acceptable .I security strength factor as an integer (see .B minssf description). The default is .BR INT_MAX . .TP .B maxbufsize= specifies the maximum security layer receive buffer size allowed. 0 disables security layers. The default is 65536. .RE .TP .B SASL_NOCANON Do not perform reverse DNS lookups to canonicalize SASL host names. The default is off. .SH GSSAPI OPTIONS If OpenLDAP is built with Generic Security Services Application Programming Interface support, there are more options you can specify. .TP .B GSSAPI_SIGN Specifies if GSSAPI signing (GSS_C_INTEG_FLAG) should be used. The default is off. .TP .B GSSAPI_ENCRYPT Specifies if GSSAPI encryption (GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG) should be used. The default is off. .TP .B GSSAPI_ALLOW_REMOTE_PRINCIPAL Specifies if GSSAPI based authentication should try to form the target principal name out of the ldapServiceName or dnsHostName attribute of the targets RootDSE entry. The default is off. .SH TLS OPTIONS If OpenLDAP is built with Transport Layer Security support, there are more options you can specify. These options are used when an .B ldaps:// URI is selected (by default or otherwise) or when the application negotiates TLS by issuing the LDAP StartTLS operation. .LP When using OpenSSL, if neither \fBTLS_CACERT\fP nor \fBTLS_CACERTDIR\fP is set, the system-wide default set of CA certificates is used. .TP .B TLS_CACERT Specifies the file that contains certificates for all of the Certificate Authorities the client will recognize. .TP .B TLS_CACERTDIR Specifies the path of a directory that contains Certificate Authority certificates in separate individual files. The .B TLS_CACERT is always used before .B TLS_CACERTDIR. The specified directory must be managed with the OpenSSL c_rehash utility. This parameter is ignored with GnuTLS. When using Mozilla NSS, may contain a Mozilla NSS cert/key database. If contains a Mozilla NSS cert/key database and CA cert files, OpenLDAP will use the cert/key database and will ignore the CA cert files. .TP .B TLS_CERT Specifies the file that contains the client certificate. .B This is a user-only option. When using Mozilla NSS, if using a cert/key database (specified with TLS_CACERTDIR), TLS_CERT specifies the name of the certificate to use: .nf TLS_CERT Certificate for Sam Carter .fi If using a token other than the internal built in token, specify the token name first, followed by a colon: .nf TLS_CERT my hardware device:Certificate for Sam Carter .fi Use certutil \-L to list the certificates by name: .nf certutil \-d /path/to/certdbdir \-L .fi .TP .B TLS_ECNAME Specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman ephemeral key exchange. This option is only used for OpenSSL. This option is not used with GnuTLS; the curves may be chosen in the GnuTLS ciphersuite specification. .TP .B TLS_KEY Specifies the file that contains the private key that matches the certificate stored in the .B TLS_CERT file. Currently, the private key must not be protected with a password, so it is of critical importance that the key file is protected carefully. .B This is a user-only option. When using Mozilla NSS, TLS_KEY specifies the name of a file that contains the password for the key for the certificate specified with TLS_CERT. The modutil command can be used to turn off password protection for the cert/key database. For example, if TLS_CACERTDIR specifies /home/scarter/.moznss as the location of the cert/key database, use modutil to change the password to the empty string: .nf modutil \-dbdir ~/.moznss \-changepw 'NSS Certificate DB' .fi You must have the old password, if any. Ignore the WARNING about the running browser. Press 'Enter' for the new password. .TP .B TLS_CIPHER_SUITE Specifies acceptable cipher suite and preference order. should be a cipher specification for the TLS library in use (OpenSSL, GnuTLS, or Mozilla NSS). Example: .RS .RS .TP .I OpenSSL: TLS_CIPHER_SUITE HIGH:MEDIUM:+SSLv2 .TP .I GnuTLS: TLS_CIPHER_SUITE SECURE256:!AES-128-CBC .RE To check what ciphers a given spec selects in OpenSSL, use: .nf openssl ciphers \-v .fi With GnuTLS the available specs can be found in the manual page of .BR gnutls\-cli (1) (see the description of the option .BR \-\-priority ). In older versions of GnuTLS, where gnutls\-cli does not support the option \-\-priority, you can obtain the \(em more limited \(em list of ciphers by calling: .nf gnutls\-cli \-l .fi When using Mozilla NSS, the OpenSSL cipher suite specifications are used and translated into the format used internally by Mozilla NSS. There isn't an easy way to list the cipher suites from the command line. The authoritative list is in the source code for Mozilla NSS in the file sslinfo.c in the structure .nf static const SSLCipherSuiteInfo suiteInfo[] .fi .RE .TP .B TLS_PROTOCOL_MIN [.] Specifies minimum SSL/TLS protocol version that will be negotiated. If the server doesn't support at least that version, the SSL handshake will fail. To require TLS 1.x or higher, set this option to 3.(x+1), e.g., .nf TLS_PROTOCOL_MIN 3.2 .fi would require TLS 1.1. Specifying a minimum that is higher than that supported by the OpenLDAP implementation will result in it requiring the highest level that it does support. This parameter is ignored with GnuTLS. .TP .B TLS_RANDFILE Specifies the file to obtain random bits from when /dev/[u]random is not available. Generally set to the name of the EGD/PRNGD socket. The environment variable RANDFILE can also be used to specify the filename. This parameter is ignored with GnuTLS and Mozilla NSS. .TP .B TLS_REQCERT Specifies what checks to perform on server certificates in a TLS session, if any. The .B can be specified as one of the following keywords: .RS .TP .B never The client will not request or check any server certificate. .TP .B allow The server certificate is requested. If no certificate is provided, the session proceeds normally. If a bad certificate is provided, it will be ignored and the session proceeds normally. .TP .B try The server certificate is requested. If no certificate is provided, the session proceeds normally. If a bad certificate is provided, the session is immediately terminated. .TP .B demand | hard These keywords are equivalent. The server certificate is requested. If no certificate is provided, or a bad certificate is provided, the session is immediately terminated. This is the default setting. .RE .TP .B TLS_REQSAN Specifies what checks to perform on the subjectAlternativeName (SAN) extensions in a server certificate when validating the certificate name against the specified hostname of the server. The .B can be specified as one of the following keywords: .RS .TP .B never The client will not check any SAN in the certificate. .TP .B allow The SAN is checked against the specified hostname. If a SAN is present but none match the specified hostname, the SANs are ignored and the usual check against the certificate DN is used. .TP .B try The SAN is checked against the specified hostname. If no SAN is present in the server certificate, the usual check against the certificate DN is used. If a SAN is present but doesn't match the specified hostname, the session is immediately terminated. This setting may be preferred when a mix of certs with and without SANs are in use. This is the default setting. .TP .B demand | hard These keywords are equivalent. The SAN is checked against the specified hostname. If no SAN is present in the server certificate, or no SANs match, the session is immediately terminated. This setting should be used when only certificates with SANs are in use. .RE .TP .B TLS_CRLCHECK Specifies if the Certificate Revocation List (CRL) of the CA should be used to verify if the server certificates have not been revoked. This requires .B TLS_CACERTDIR parameter to be set. This parameter is ignored with GnuTLS and Mozilla NSS. .B can be specified as one of the following keywords: .RS .TP .B none No CRL checks are performed .TP .B peer Check the CRL of the peer certificate .TP .B all Check the CRL for a whole certificate chain .RE .TP .B TLS_CRLFILE Specifies the file containing a Certificate Revocation List to be used to verify if the server certificates have not been revoked. This parameter is only supported with GnuTLS and Mozilla NSS. .SH "ENVIRONMENT VARIABLES" .TP LDAPNOINIT disable all defaulting .TP LDAPCONF path of a configuration file .TP LDAPRC basename of ldaprc file in $HOME or $CWD .TP LDAP Set as from ldap.conf .SH FILES .TP .I /opt/alt/openldap11/etc/openldap/ldap.conf system-wide ldap configuration file .TP .I $HOME/ldaprc, $HOME/.ldaprc user ldap configuration file .TP .I $CWD/ldaprc local ldap configuration file .SH "SEE ALSO" .BR ldap (3), .BR ldap_set_option (3), .BR ldap_result (3), .BR openssl (1), .BR sasl (3) .SH AUTHOR Kurt Zeilenga, The OpenLDAP Project .SH ACKNOWLEDGEMENTS .lf 1 ./../Project .\" Shared Project Acknowledgement Text .B "OpenLDAP Software" is developed and maintained by The OpenLDAP Project . .B "OpenLDAP Software" is derived from the University of Michigan LDAP 3.3 Release. .lf 559 stdin doc/alt-sqlite/README.md000064400000051152152527274720010670 0ustar00

SQLite Source Repository

This repository contains the complete source code for the [SQLite database engine](https://sqlite.org/) going back to 2000-05-29. The tree includes many tests and some documentation, though additional tests and most documentation are managed separately. See the [on-line documentation](https://sqlite.org/) for more information about what SQLite is and how it works from a user's perspective. This README file is about the source code that goes into building SQLite, not about how SQLite is used. ## Version Control SQLite sources are managed using [Fossil](https://fossil-scm.org/), a distributed version control system that was specifically designed and written to support SQLite development. The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext. If you are reading this on GitHub or some other Git repository or service, then you are looking at a mirror. The names of check-ins and other artifacts in a Git mirror are different from the official names for those objects. The official names for check-ins are found in a footer on the check-in comment for authorized mirrors. The official check-in name can also be seen in the `manifest.uuid` file in the root of the tree. Always use the official name, not the Git-name, when communicating about an SQLite check-in. If you pulled your SQLite source code from a secondary source and want to verify its integrity, there are hints on how to do that in the [Verifying Code Authenticity](#vauth) section below. ## Contacting The SQLite Developers The preferred way to ask questions or make comments about SQLite or to report bugs against SQLite is to visit the [SQLite Forum](https://sqlite.org/forum) at . Anonymous postings are permitted. If you think you have found a bug that has security implications and you do not want to report it on the public forum, you can send a private email to drh at sqlite dot org. ## Public Domain The SQLite source code is in the public domain. See for details. Because SQLite is in the public domain, we do not normally accept pull requests, because if we did take a pull request, the changes in that pull request might carry a copyright and the SQLite source code would then no longer be fully in the public domain. ## Obtaining The SQLite Source Code Source code tarballs or ZIP archives are available at: * [Latest trunk check-in](https://sqlite.org/src/rchvdwnld/trunk). * [Latest release](https://sqlite.org/src/rchvdwnld/release) * For other check-ins, browse the [project timeline](https://sqlite.org/src/timeline?y=ci) and click on the check-in hash of the check-in you want to download. On the resulting "info" page, click one of the options to the right of the "**Downloads:**" label in the "**Overview**" section near the top. To access sources directly using [Fossil](https://fossil-scm.org/home), first install Fossil version 2.0 or later. Source tarballs and precompiled binaries for Fossil are available at . Fossil is a stand-alone program. To install, simply download or build the single executable file and put that file someplace on your $PATH or %PATH%. Then run commands like this: mkdir -p ~/sqlite cd ~/sqlite fossil open https://sqlite.org/src The initial "fossil open" command will take two or three minutes. Afterwards, you can do fast, bandwidth-efficient updates to the whatever versions of SQLite you like. Some examples: fossil update trunk ;# latest trunk check-in fossil update release ;# latest official release fossil update trunk:2024-01-01 ;# First trunk check-in after 2024-01-01 fossil update version-3.39.0 ;# Version 3.39.0 Or type "fossil ui" to get a web-based user interface. ## Compiling for Unix-like systems First create a directory in which to place the build products. It is recommended, but not required, that the build directory be separate from the source directory. Cd into the build directory and then from the build directory run the configure script found at the root of the source tree. Then run "make". See the [compile-for-unix.md](doc/compile-for-unix.md) document for more detail. For example: apt install gcc make tcl-dev ;# Install the necessary build tools tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" mkdir bld ;# Build happens in a sibling directory cd bld ;# Change to the build directory ../sqlite/configure ;# Run the configure script make sqlite3 ;# The "sqlite3" command-line tool make sqlite3.c ;# The "amalgamation" source file make sqldiff ;# The "sqldiff" command-line tool #### Targets below require tcl-dev #### make tclextension-install ;# Install the SQLite TCL extension make devtest ;# Run development tests make releasetest ;# Run full release tests make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool See the makefile for additional targets. For debugging builds, the core developers typically run "configure" with options like this: ../sqlite/configure --all --debug CFLAGS='-O0 -g' For release builds, the core developers usually do: ../sqlite/configure --all Core deliverables (sqlite3.c, sqlite3) can be built without a TCL, but many makefile targets require a "tclsh" TCL interpreter version 8.6 or later. The "tclextension-install" target and the test targets that follow all require TCL development libraries too. ("apt install tcl-dev"). It is helpful, but is not required, to install the SQLite TCL extension (the "tclextension-install" target) prior to running tests. The "releasetest" target has additional requirements, such as "valgrind". On "make" command-lines, one can add "OPTIONS=..." to specify additional compile-time options over and above those set by ./configure. For example, to compile with the SQLITE_OMIT_DEPRECATED compile-time option, one could say: ./configure --all make OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3 The configure script uses [autosetup](https://msteveb.github.io/autosetup/). If the configure script does not work out for you, there is a generic makefile named "Makefile.linux-gcc" in the top directory of the source tree that you can copy and edit to suit your needs. Comments on the generic makefile show what changes are needed. ## Compiling for Windows Using MSVC On Windows, everything can be compiled with MSVC. You will also need a working installation of TCL if you want to run tests, though TCL is not required if you just want to build SQLite itself. See the [compile-for-windows.md](doc/compile-for-windows.md) document for additional information about how to install MSVC and TCL and configure your build environment. If you want to run tests, you need to let SQLite know the location of your TCL library, using a command like this: set TCLDIR=c:\Tcl SQLite itself does not contain any TCL code, but it does use TCL to run tests. You may need to install TCL development libraries in order to successfully complete some makefile targets. It is helpful, but is not required, to install the SQLite TCL extension (the "tclextension-install" target) prior to running tests. The source tree contains a "make.bat" file that allows the same "make" commands of Unix to work on Windows. In the following, you can substitute "nmake /f Makefile.msc" in place of "make", if you prefer to avoid this BAT file: make sqlite3.exe make sqlite3.c make sqldiff.exe #### Targets below require TCL development libraries #### make tclextension-install make devtest make releasetest make sqlite3_analyzer.exe There are many other makefile targets. See comments in Makefile.msc for details. As with the unix Makefile, the OPTIONS=... argument can be passed on the nmake command-line to enable new compile-time options. For example: make OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3.exe ## Source Tree Map * **src/** - This directory contains the primary source code for the SQLite core. For historical reasons, C-code used for testing is also found here. Source files intended for testing begin with "`test`". The `tclsqlite3.c` and `tclsqlite3.h` files are the TCL interface for SQLite and are also not part of the core. * **test/** - This directory and its subdirectories contains code used for testing. Files that end in "`.test`" are TCL scripts that run tests using an augmented TCL interpreter named "testfixture". Use a command like "`make testfixture`" to build that augmented TCL interpreter, then run individual tests using commands like "`testfixture test/main.test`". This test/ subdirectory also contains additional C code modules and scripts for other kinds of testing. * **tool/** - This directory contains programs and scripts used to build some of the machine-generated code that goes into the SQLite core, as well as to build and run tests and perform diagnostics. The source code to [the Lemon parser generator](./doc/lemon.html) is found here. There are also TCL scripts used to build and/or transform source code files. For example, the tool/mksqlite3h.tcl script reads the src/sqlite.h.in file and uses it as a template to construct the deliverable "sqlite3.h" file that defines the SQLite interface. * **ext/** - Various extensions to SQLite are found under this directory. For example, the FTS5 subsystem is in "ext/fts5/". Some of these extensions (ex: FTS3/4, FTS5, RTREE) might get built into the SQLite amalgamation, but not all of them. The "ext/misc/" subdirectory contains an assortment of one-file extensions, many of which are omitted from the SQLite core, but which are included in the [SQLite CLI](https://sqlite.org/cli.html). * **doc/** - Some documentation files about SQLite internals are found here. Note, however, that the primary documentation designed for application developers and users of SQLite is in a completely separate repository. Note also that the primary API documentation is derived from specially constructed comments in the src/sqlite.h.in file. ### Generated Source Code Files Several of the C-language source files used by SQLite are generated from other sources rather than being typed in manually by a programmer. This section will summarize those automatically-generated files. To create all of the automatically-generated files, simply run "make target_source". The "target_source" make target will create a subdirectory "tsrc/" and fill it with all the source files needed to build SQLite, both manually-edited files and automatically-generated files. The SQLite interface is defined by the **sqlite3.h** header file, which is generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The [Tcl script](https://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion. The manifest.uuid file contains the SHA3 hash of the particular check-in and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file contains the current SQLite version number. The sqlite3.h header is really just a copy of src/sqlite.h.in with the source-id and version number inserted at just the right spots. Note that comment text in the sqlite3.h file is used to generate much of the SQLite API documentation. The Tcl scripts used to generate that documentation are in a separate source repository. The SQL language parser is **parse.c** which is generated from a grammar in the src/parse.y file. The conversion of "parse.y" into "parse.c" is done by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a template for generating its parser. Lemon also generates the **parse.h** header file, at the same time it generates parse.c. The **opcodes.h** header file contains macros that define the numbers corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h file is generated by scanning the src/vdbe.c source file. The Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h. A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate the **opcodes.c** source file, which contains a reverse mapping from opcode-number to opcode-name that is used for EXPLAIN output. The **keywordhash.h** header file contains the definition of a hash table that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into the numeric codes used by the parse.c parser. The keywordhash.h file is generated by a C-language program at tool mkkeywordhash.c. The **pragma.h** header file contains various definitions used to parse and implement the PRAGMA statements. The header is generated by a script **tool/mkpragmatab.tcl**. If you want to add a new PRAGMA, edit the **tool/mkpragmatab.tcl** file to insert the information needed by the parser for your new PRAGMA, then run the script to regenerate the **pragma.h** header file. ### The Amalgamation All of the individual C source code and header files (both manually-edited and automatically-generated) can be combined into a single big source file **sqlite3.c** called "the amalgamation". The amalgamation is the recommended way of using SQLite in a larger application. Combining all individual source code files into a single big source code file allows the C compiler to perform more cross-procedure analysis and generate better code. SQLite runs about 5% faster when compiled from the amalgamation versus when compiled from individual source files. The amalgamation is generated from the tool/mksqlite3c.tcl Tcl script. First, all of the individual source files must be gathered into the tsrc/ subdirectory (using the equivalent of "make target_source") then the tool/mksqlite3c.tcl script is run to copy them all together in just the right order while resolving internal "#include" references. The amalgamation source file is more than 200K lines long. Some symbolic debuggers (most notably MSVC) are unable to deal with files longer than 64K lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl, can be run on the amalgamation to break it up into a single small C file called **sqlite3-all.c** that does #include on about seven other files named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-7.c**. In this way, all of the source code is contained within a single translation unit so that the compiler can do extra cross-procedure optimization, but no individual source file exceeds 32K lines in length. ## How It All Fits Together SQLite is modular in design. See the [architectural description](https://sqlite.org/arch.html) for details. Other documents that are useful in helping to understand how SQLite works include the [file format](https://sqlite.org/fileformat2.html) description, the [virtual machine](https://sqlite.org/opcode.html) that runs prepared statements, the description of [how transactions work](https://sqlite.org/atomiccommit.html), and the [overview of the query planner](https://sqlite.org/optoverview.html). Decades of effort have gone into optimizing SQLite, both for small size and high performance. And optimizations tend to result in complex code. So there is a lot of complexity in the current SQLite implementation. It will not be the easiest library in the world to hack. ### Key source code files * **sqlite.h.in** - This file defines the public interface to the SQLite library. Readers will need to be familiar with this interface before trying to understand how the library works internally. This file is really a template that is transformed into the "sqlite3.h" deliverable using a script invoked by the makefile. * **sqliteInt.h** - this header file defines many of the data objects used internally by SQLite. In addition to "sqliteInt.h", some subsystems inside of sQLite have their own header files. These internal interfaces are not for use by applications. They can and do change from one release of SQLite to the next. * **parse.y** - This file describes the LALR(1) grammar that SQLite uses to parse SQL statements, and the actions that are taken at each step in the parsing process. The file is processed by the [Lemon Parser Generator](./doc/lemon.html) to produce the actual C code used for parsing. * **vdbe.c** - This file implements the virtual machine that runs prepared statements. There are various helper files whose names begin with "vdbe". The VDBE has access to the vdbeInt.h header file which defines internal data objects. The rest of SQLite interacts with the VDBE through an interface defined by vdbe.h. * **where.c** - This file (together with its helper files named by "where*.c") analyzes the WHERE clause and generates virtual machine code to run queries efficiently. This file is sometimes called the "query optimizer". It has its own private header file, whereInt.h, that defines data objects used internally. * **btree.c** - This file contains the implementation of the B-Tree storage engine used by SQLite. The interface to the rest of the system is defined by "btree.h". The "btreeInt.h" header defines objects used internally by btree.c and not published to the rest of the system. * **pager.c** - This file contains the "pager" implementation, the module that implements transactions. The "pager.h" header file defines the interface between pager.c and the rest of the system. * **os_unix.c** and **os_win.c** - These two files implement the interface between SQLite and the underlying operating system using the run-time pluggable VFS interface. * **shell.c.in** - This file is not part of the core SQLite library. This is the file that, when linked against sqlite3.a, generates the "sqlite3.exe" command-line shell. The "shell.c.in" file is transformed into "shell.c" as part of the build process. * **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It is not part of the core SQLite library. But as most of the tests in this repository are written in Tcl, the Tcl language bindings are important. * **test\*.c** - Files in the src/ folder that begin with "test" go into building the "testfixture.exe" program. The testfixture.exe program is an enhanced Tcl shell. The testfixture.exe program runs scripts in the test/ folder to validate the core SQLite code. The testfixture program (and some other test programs too) is built and run when you type "make test". * **VERSION**, **manifest**, **manifest.tags**, and **manifest.uuid** - These files define the current SQLite version number. The "VERSION" file is human generated, but the "manifest", "manifest.tags", and "manifest.uuid" files are automatically generated by the [Fossil version control system](https://fossil-scm.org/). There are many other source files. Each has a succinct header comment that describes its purpose and role within the larger system. ## Verifying Code Authenticity The `manifest` file at the root directory of the source tree contains either a SHA3-256 hash or a SHA1 hash for every source file in the repository. The name of the version of the entire source tree is just the SHA3-256 hash of the `manifest` file itself, possibly with the last line of that file omitted if the last line begins with "`# Remove this line`". The `manifest.uuid` file should contain the SHA3-256 hash of the `manifest` file. If all of the above hash comparisons are correct, then you can be confident that your source tree is authentic and unadulterated. Details on the format for the `manifest` files are available [on the Fossil website](https://fossil-scm.org/home/doc/trunk/www/fileformat.wiki#manifest). The process of checking source code authenticity is automated by the makefile: > make verify-source Using the makefile to verify source integrity is good for detecting accidental changes to the source tree, but malicious changes could be hidden by also modifying the makefiles. ## Contacts The main SQLite website is [https://sqlite.org/](https://sqlite.org/) with geographically distributed backups at [https://www2.sqlite.org/](https://www2.sqlite.org) and [https://www3.sqlite.org/](https://www3.sqlite.org). Contact the SQLite developers through the [SQLite Forum](https://sqlite.org/forum/). In an emergency, you can send private email to the lead developer at drh at sqlite dot org. man/man1/sqlite3.1000064400000012303152527274720007635 0ustar00.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH SQLITE3 1 "Fri Aug 11 23:50:12 CET 2023" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME .B sqlite3 \- A command line interface for SQLite version 3 .SH SYNOPSIS .B sqlite3 .RI [ options ] .RI [ databasefile ] .RI [ SQL ] .SH SUMMARY .PP .B sqlite3 is a terminal-based front-end to the SQLite library that can evaluate queries interactively and display the results in multiple formats. .B sqlite3 can also be used within shell scripts and other applications to provide batch processing features. .SH DESCRIPTION To start a .B sqlite3 interactive session, invoke the .B sqlite3 command and optionally provide the name of a database file. If the database file does not exist, it will be created. If the database file does exist, it will be opened. For example, to create a new database file named "mydata.db", create a table named "memos" and insert a couple of records into that table: .sp $ .B sqlite3 mydata.db .br SQLite version 3.43.0 2023-08-11 17:45:23 .br Enter ".help" for usage hints. .br sqlite> .B create table memos(text, priority INTEGER); .br sqlite> .B insert into memos values('deliver project description', 10); .br sqlite> .B insert into memos values('lunch with Christine', 100); .br sqlite> .B select * from memos; .br deliver project description|10 .br lunch with Christine|100 .br sqlite> .sp If no database name is supplied, the ATTACH sql command can be used to attach to existing or create new database files. ATTACH can also be used to attach to multiple databases within the same interactive session. This is useful for migrating data between databases, possibly changing the schema along the way. Optionally, a SQL statement or set of SQL statements can be supplied as a single argument. Multiple statements should be separated by semi-colons. For example: .sp $ .B sqlite3 -line mydata.db 'select * from memos where priority > 20;' .br text = lunch with Christine .br priority = 100 .br .sp .SS SQLITE META-COMMANDS .PP The interactive interpreter offers a set of meta-commands that can be used to control the output format, examine the currently attached database files, or perform administrative operations upon the attached databases (such as rebuilding indices). Meta-commands are always prefixed with a dot (.). A list of available meta-commands can be viewed at any time by issuing the '.help' command. For example: .sp sqlite> .B .help .nf .tr %. ... .sp .fi The available commands differ by version and build options, so they are not listed here. Please refer to your local copy for all available options. .SH INIT FILE .B sqlite3 reads an initialization file to set the configuration of the interactive environment. Throughout initialization, any previously specified setting can be overridden. The sequence of initialization is as follows: o The default configuration is established as follows: .sp .nf .cc | mode = LIST separator = "|" main prompt = "sqlite> " continue prompt = " ...> " |cc . .sp .fi o If the environment variable XDG_CONFIG_HOME is set then .B ${XDG_CONFIG_HOME}/sqlite3/sqliterc is checked, else .B ~/.config/sqlite3/sqliterc is checked. If the selected file does not exist then the fallback of .B ~/.sqliterc is used. It should generally only contain meta-commands. o If the -init option is present, the specified file is processed. o All other command line options are processed. .SH HISTORY FILE .B sqlite3 may be configured to use a history file to save SQL statements and meta-commands entered interactively. These statements and commands can be retrieved, edited and, reused at the main and continue prompts. If the environment variable .B SQLITE_HISTORY is set, it will be used as the name of the history file, whether it already exists or not. If it is not set but the XDG_STATE_HOME environment variable is then .B ${XDG_STATE_HOME}/sqlite_history is used. If XDG_STATE_HOME is not set then .B ~/.local/state/sqlite_history is used. If the selected file does not exist then .B ~/.sqlite_history will be used as the history file. If any history file is found, it will be written if the shell exits interactive mode normally, regardless of whether it existed previously, though saving will silently fail if the history file's directory does not exist. .SH SEE ALSO https://sqlite.org/cli.html .br https://sqlite.org/fiddle (a WebAssembly build of the CLI app) .br The sqlite3-doc package. .SH AUTHOR This manual page was originally written by Andreas Rottmann , for the Debian GNU/Linux system (but may be used by others). It was subsequently revised by Bill Bumgarner , Laszlo Boszormenyi , and the sqlite3 developers. aclocal/libmcrypt.m4000064400000020662152527435220010426 0ustar00dnl Autoconf macros for libmcrypt dnl $id$ # This script detects libmcrypt version and defines # LIBMCRYPT_CFLAGS, LIBMCRYPT_LIBS # and LIBMCRYPT24 or LIBMCRYPT22 depending on libmcrypt version # found. # Modified for LIBMCRYPT -- nmav # Configure paths for LIBGCRYPT # Shamelessly stolen from the one of XDELTA by Owen Taylor # Werner Koch 99-12-09 dnl AM_PATH_LIBMCRYPT([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libmcrypt, and define LIBMCRYPT_CFLAGS and LIBMCRYPT_LIBS dnl AC_DEFUN([AM_PATH_LIBMCRYPT], [dnl dnl Get the cflags and libraries from the libmcrypt-config script dnl AC_ARG_WITH(libmcrypt-prefix, [ --with-libmcrypt-prefix=PFX Prefix where libmcrypt is installed (optional)], libmcrypt_config_prefix="$withval", libmcrypt_config_prefix="") if test x$libmcrypt_config_prefix != x ; then libmcrypt_config_args="$libmcrypt_config_args --prefix=$libmcrypt_config_prefix" if test x${LIBMCRYPT_CONFIG+set} != xset ; then LIBMCRYPT_CONFIG=$libmcrypt_config_prefix/bin/libmcrypt-config fi fi AC_PATH_PROG(LIBMCRYPT_CONFIG, libmcrypt-config, no) min_libmcrypt_version=ifelse([$1], ,2.4.0,$1) AC_MSG_CHECKING(for libmcrypt - version >= $min_libmcrypt_version) no_libmcrypt="" if test "$LIBMCRYPT_CONFIG" = "no" ; then dnl libmcrypt-config was not found (pre 2.4.11 versions) dnl Try to detect libmcrypt version AC_TRY_RUN([ #include #include #include #include int main () { #if MCRYPT_API_VERSION <= 19991015 /* version 2.2 */ return 0; #else /* version 2.4 */ return 1; #endif /* 19991015 */ } ], libmcrypt_config_version="2.2.0" if test x$libmcrypt_config_prefix != x ; then TTLIBS="-L${libmcrypt_config_prefix}/libs" TTINCLUDE="-I${libmcrypt_config_prefix}/include" fi LIBMCRYPT_CFLAGS="${TTINCLUDE}" LIBMCRYPT_LIBS="${TTLIBS} -lmcrypt" AC_DEFINE(LIBMCRYPT22, 1, [have libmcrypt 2.2]) , libmcrypt_config_version="2.4.0" if test x$libmcrypt_config_prefix != x ; then TTLIBS="-L${libmcrypt_config_prefix}/libs" TTINCLUDE="-I${libmcrypt_config_prefix}/include" fi LIBMCRYPT_CFLAGS="${TTINCLUDE}" LIBMCRYPT_LIBS="${TTLIBS} -lmcrypt -lltdl ${LIBADD_DL}" AC_DEFINE(LIBMCRYPT24, 1, [have libmcrypt 2.4])) else dnl libmcrypt-config was found LIBMCRYPT_CFLAGS=`$LIBMCRYPT_CONFIG $libmcrypt_config_args --cflags` LIBMCRYPT_LIBS=`$LIBMCRYPT_CONFIG $libmcrypt_config_args --libs` libmcrypt_config_version=`$LIBMCRYPT_CONFIG $libmcrypt_config_args --version` AC_DEFINE(LIBMCRYPT24, 1, [have libmcrypt 2.4]) fi ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $LIBMCRYPT_CFLAGS" LIBS="$LIBS $LIBMCRYPT_LIBS" dnl dnl Now check if the installed libmcrypt is sufficiently new. Also sanity dnl checks the results of libmcrypt-config to some extent dnl rm -f conf.libmcrypttest AC_TRY_RUN([ #include #include #include #include #define TWO "2.2" int main () { #if MCRYPT_API_VERSION <= 20010201 #if MCRYPT_API_VERSION <= 19991015 /* version 2.2 */ int x = mcrypt_get_key_size(MCRYPT_TWOFISH_128); system ("touch conf.libmcrypttest"); if( strncmp( TWO, "$min_libmcrypt_version", strlen(TWO))) { printf("\n*** Requested libmcrypt %s, but LIBMCRYPT (%s)\n", "$min_libmcrypt_version", TWO ); printf("*** was found!\n"); return 1; } return 0; #else /* version 2.4 before 11 */ MCRYPT td = mcrypt_module_open("twofish", NULL, "cbc", NULL); system ("touch conf.libmcrypttest"); mcrypt_module_close(td); return 0; #endif /* 19991015 */ #else system ("touch conf.libmcrypttest"); if( strcmp( mcrypt_check_version(NULL), "$libmcrypt_config_version" ) ) { printf("\n*** 'libmcrypt-config --version' returned %s, but LIBMCRYPT (%s)\n", "$libmcrypt_config_version", mcrypt_check_version(NULL) ); printf("*** was found! If libmcrypt-config was correct, then it is best\n"); printf("*** to remove the old version of LIBMCRYPT. You may also be able to fix the error\n"); printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); printf("*** required on your system.\n"); printf("*** If libmcrypt-config was wrong, set the environment variable LIBMCRYPT_CONFIG\n"); printf("*** to point to the correct copy of libmcrypt-config, and remove the file config.cache\n"); printf("*** before re-running configure\n"); } else if ( strcmp(mcrypt_check_version(NULL), LIBMCRYPT_VERSION ) ) { printf("\n*** LIBMCRYPT header file (version %s) does not match\n", LIBMCRYPT_VERSION); printf("*** library (version %s)\n", mcrypt_check_version(NULL) ); } else { if ( mcrypt_check_version( "$min_libmcrypt_version" ) ) { return 0; } else { printf("no\n*** An old version of LIBMCRYPT (%s) was found.\n", mcrypt_check_version(NULL) ); printf("*** You need a version of LIBMCRYPT newer than %s. The latest version of\n", "$min_libmcrypt_version" ); printf("*** LIBMCRYPT is always available from ftp://mcrypt.hellug.gr/pub/mcrypt.\n"); printf("*** \n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the libmcrypt-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of LIBMCRYPT, but you can also set the LIBMCRYPT_CONFIG environment to point to the\n"); printf("*** correct copy of libmcrypt-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time)\n"); } } return 1; #endif /* 20010201 */ } ],, no_libmcrypt=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" if test "x$no_libmcrypt" = x ; then AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) else if test -f conf.libmcrypttest ; then : else AC_MSG_RESULT(no) fi if test -f conf.libmcrypttest ; then : else echo "*** Could not run libmcrypt test program, checking why..." CFLAGS="$CFLAGS $LIBMCRYPT_CFLAGS" LIBS="$LIBS $LIBMCRYPT_LIBS" AC_TRY_LINK([ #include #include #include #include ], [ #if MCRYPT_API_VERSION <= 20010201 #if MCRYPT_API_VERSION <= 19991015 /* version 2.2 */ int x = mcrypt_get_key_size(MCRYPT_TWOFISH_128); return 0; #else /* version 2.4 before 11 */ MCRYPT td = mcrypt_module_open("twofish", NULL, "cbc", NULL); mcrypt_module_close(td); return 0; #endif /* 19991015 */ #else return !!mcrypt_check_version(NULL); #endif /* 20010201 */ ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding LIBMCRYPT or finding the wrong" echo "*** version of LIBMCRYPT. If it is not finding LIBMCRYPT, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" echo "***" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means LIBMCRYPT was incorrectly installed" echo "*** or that you have moved LIBMCRYPT since it was installed. In the latter case, you" echo "*** may want to edit the libmcrypt-config script: $LIBMCRYPT_CONFIG" ]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi LIBMCRYPT_CFLAGS="" LIBMCRYPT_LIBS="" ifelse([$3], , :, [$3]) fi rm -f conf.libmcrypttest AC_SUBST(LIBMCRYPT_CFLAGS) AC_SUBST(LIBMCRYPT_LIBS) ]) dnl *-*wedit:notab*-* Please keep this as the last line. doc/alt-libssh211/COPYING000064400000003647152527621010010645 0ustar00/* Copyright (C) 2004-2007 Sara Golemon * Copyright (C) 2005,2006 Mikhail Gusarov * Copyright (C) 2006-2007 The Written Word, Inc. * Copyright (C) 2007 Eli Fant * Copyright (C) 2009-2023 Daniel Stenberg * Copyright (C) 2008, 2009 Simon Josefsson * Copyright (C) 2000 Markus Friedl * Copyright (C) 2015 Microsoft Corp. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * 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. * * Neither the name of the copyright holder nor the names * of any other contributors may be used to endorse or * promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "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 COPYRIGHT OWNER OR * CONTRIBUTORS 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. */ doc/alt-libssh211/README000064400000000721152527621010010460 0ustar00libssh2 - SSH2 library ====================== libssh2 is a library implementing the SSH2 protocol, available under the revised BSD license. Web site: https://libssh2.org/ Mailing list: https://lists.haxx.se/listinfo/libssh2-devel License: see COPYING Source code: https://github.com/libssh2/libssh2 Web site source code: https://github.com/libssh2/www Installation instructions are in: - docs/INSTALL_CMAKE for CMake - docs/INSTALL_AUTOTOOLS for Autotools doc/alt-libssh211/ChangeLog000064400000000011152527621010011342 0ustar00see NEWS doc/alt-libssh211/NEWS000064400001242234152527621010010307 0ustar00 Changelog for the libssh2 project. Generated with git2news.pl Daniel Stenberg (16 Oct 2024) - RELEASE-NOTES: 1.11.1 Viktor Szakats (8 Oct 2024) - RELEASE-NOTES: sync [ci skip] - [Anders Borum brought this change] session: support server banners up to 8192 bytes (was: 256) If server had banner exceeding 256 bytes there wasn't enough room in `_LIBSSH2_SESSION.banner_TxRx_banner`. Only the first 256 bytes would be read making the first packet read fail but also dooming key exchange as `session->remote.banner` didn't include everything. This change bumps the banner buffer to 8KB to match OpenSSH. Fixes #1442 Closes #1443 - RELEASE-NOTES: sync [ci skip] - cmake: sync and improve Find modules, add `pkg-config` native detection - sync code between Find modules. - wolfssl: replace `pkg-config` hints with native detection. - libgcrypt, mbedtls: add `pkg-config`-based native detection. - libgcrypt: add version detection. - limit `pkg-config` use for `UNIX`, vcpkg, and non-cross MinGW builds, and builds with no manual customization via `*_INCLUDE_DIR` or `*_LIBRARY`. - replace and sync Find module header comments. - ci: delete manual mbedTLS config that's now redundant. Based on similar work done in curl. Second attempt at #1420 Closes #1445 - cmake: initialize `LIBSSH2_LIBDIRS` [ci skip] Follow-up to c87f12963037b22e6b60411c9c2d6513c06e2f03 #1466 - ci/appveyor: fix and bump OpenSSL 3 path, add path check Follow-up to b5e68bdc37c6afa0dc777794dda8307167919d04 #1461 Closes #1468 - cmake: link to OpenSSL::Crypto, not OpenSSL::SSL Follow-up to 82b09f9b3aae97f641fbcc2d746d2a6383abe857 #1322 Follow-up to c84745e34e53f863ffba997ceeee7d43d1c63a4b #1128 Cherry-picked from #1445 Closes #1467 - cmake: generate `LIBSSH2_PC_LIBS_PRIVATE` dynamically Generate `LIBSSH2_PC_LIBS_PRIVATE` from `LIBSSH2_LIBS`. Also add extra libdirs (`-L`) to `Libs` and `Libs.private`. Logic copied from curl. Closes #1466 - cmake: initialize `LIBSSH2_PC_REQUIRES_PRIVATE` [ci skip] Follow-up to 0fce9dcc2909ffff5f4a1a1bc3d359fc7f409299 #1464 - cmake: add comment about `ibssh2.pc.in` variables [ci skip] - cmake: support absolute `CMAKE_INSTALL_INCLUDEDIR`/`CMAKE_INSTALL_LIBDIR` in `libssh2.pc`. Also use `${exec_prefix}` (instead of `${prefix}`) as a base for `libdir`. Closes #1465 - cmake: rename two variables and initialize them - `LIBRARIES` -> `LIBSSH2_LIBS` - `SOCKET_LIBRARIES` -> `LIBSSH2_LIBS_SOCKET` Also initialize them before use. Cherry-picked from #1445 Closes #1464 - ci/appveyor: reduce test runs (workaround for infrastructure permafails) Jobs consistently fail to connect to the test server (run in GHA) since 2024-Aug-29: https://ci.appveyor.com/project/libssh2org/libssh2/builds/50498393 There was an earlier phase of failures one month before that, that got fixed by increasing the wait for the server in bf3af90b3f1bb14cf452df7a8eb55cc9088f3e7f. Thus, skip running tests in AppVeyor CI jobs, except: After some experiments, it seems that running tests with the last OpenSSL job and the last WinCrypt job _work_, which still leaves some coverage. It remains to be seen how stable this is. This is meant as a temporary fix till there is a solution to make all jobs run tests reliable like up until a few months ago. Closes #1461 - [Patrick Monnerat brought this change] os400: drop vsprintf() use Follow-up to discussion in #1457 Plus e-mail address update. Closes #1462 - RELEASE-NOTES: sync [ci skip] Daniel Stenberg (30 Sep 2024) - openssl: free allocated resources when using openssl3 Reproduces consistently with curl test case 638 Closes #1459 Viktor Szakats (28 Sep 2024) - checksrc: update, check all sources, fix fallouts update from curl: https://github.com/curl/curl/blob/cff75acfeca65738da8297aee0b30427b004b240/scripts/checksrc.pl Closes #1457 - cmake: prefer `find_dependency()` in `libssh2-config.cmake` CMake manual suggest using `find_dependency()` (over `find_package()`) in `config.cmake` scripts. Ref: https://cmake.org/cmake/help/latest/module/CMakeFindDependencyMacro.html Closes #1460 - ci: use Ninja with cmake Closes #1458 GitHub (27 Sep 2024) - [dksslq brought this change] Fix memory leaks in _libssh2_ecdsa_curve_name_with_octal_new and _libssh2_ecdsa_verify (#1449) Better error handling in`_libssh2_ecdsa_curve_name_with_octal_new` and `_libssh2_ecdsa_verify` to prevent leaks. Credit: dksslq - [rolag brought this change] Fix unstable connections over nonblocking sockets (#1454) The `send_existing()` function allows partially sent packets to be sent fully before any further packets are sent. Originally this returned `LIBSSH2_ERROR_BAD_USE` when a different caller or thread tried to send an existing packet created by a different caller or thread causing the connection to disconnect. Commit 33dddd2f8ac3bc81 removed the return allowing any caller to continue sending another caller's packet. This caused connection instability as discussed in #1397 and confused the client and server causing occasional duplicate packets to be sent and giving the error `rcvd too much data` as discussed in #1431. We return `LIBSSH2_ERROR_EAGAIN` instead to allow existing callers to finish sending their own packets. Fixes #1397 Fixes #1431 Related #720 Credit: klux21, rolag - [Will Cosgrove brought this change] Prevent possible double free of hostkey (#1452) NULL server hostkey based on fuzzer failure case. Viktor Szakats (7 Sep 2024) - cmake: tidy up syntax, minor improvements - make internal variables underscore-lowercase. - unfold lines. - fold lines setting header directories. - fix indent. - drop interim variable `EXAMPLES`. - initialize some variables before populating them. - clear a variable after use. - add `libssh2_dumpvars()` function for debugging. - allow to override default `CMAKE_UNITY_BUILD_BATCH_SIZE`. - bump up default `CMAKE_UNITY_BUILD_BATCH_SIZE` to 0 (was 32). - tidy up option descriptions. Closes #1446 - cmake: rename mbedTLS and wolfSSL Find modules To match the curl ones. Cherry-picked from #1445 - RELEASE-NOTES: sync [ci skip] - cmake: fixup version detection in mbedTLS find module - avoid warning with 2.x versions about missing header file while extracting the version number. - clear temp variables. Closes #1444 - buildconf: drop Use `autoreconf -fi` instead. Follow-up to fc5d77881eb6bb179f831e626d15f4f29179aad5 Closes #1441 - [Michael Buckley brought this change] Implement chacha20-poly1305@openssh.com Probably the biggest and potentially most controversial change we have to upstream. Because earlier versions of OpenSSL implemented the algorithm before standardization, using an older version of OpenSSL can cause problems connecting to OpenSSH servers. Because of this, we use the public domain reference implementation instead of the crypto backends, just like OpenSSH does. We've been holding this one for a few years. We were about to upstream it around the same time as aes128gcm landed upstream, and the two changes were completely incompatible. Honestly, it took me weeks to reconcile these two implementations, and it could be much better. Our original implementation changed every crypt method to decrypt the entire message at once. the AESGCM implementation instead went with this firstlast design, where a firstlast paramater indicates whether this is the first or last call to the crypt method for each message. That added a lot of bookkeeping overhead, and wasn't compatible with the chacha public domain implementation. As far as I could tell, OpenSSH uses the technique of decrypting the entire message in one go, and doesn't have anything like firstlast. However, I could not get out aes128gcm implementation to work that way, nor could I get the chacha implementation to work with firstlast, so I split it down the middle and let each implementation work differently. It's kind of a mess, and probably should be cleaned up, but I don't have the time to spend on it anymore, and it's probably better to have everything upstream. Fixes #584 Closes #1426 - tidy-up: do/while formatting Also fix an indentation and delete empty lines. Closes #1440 - wolfssl: drop header path hack The wolfSSL OpenSSL headers reside in `wolfssl/openssl/*.h`. Before this patch the wolfSSL OpenSSL compatibilty header includes were shared with the native OpenSSL codepath, and used `openssl/*h`. For wolfSSL builds this required a hack to append the `/wolfssl` directory to the header search path, to find the headers. This patch changes the source to use the correct header references, allowing to drop the header path hack. Also fix to use the correct variable to set up the header path in CMake: `WOLFSSL_INCLUDE_DIRS` (was: `WOLFSSL_INCLUDE_DIR`, without the `S`) Closes #1439 - cmake: mbedTLS detection tidy-ups - set and use `MBEDTLS_INCLUDE_DIRS`. - stop marking `MBEDTLS_LIBRARIES` as advanced. Closes #1438 - cmake: add quotes, delete ending dirseps Follow-up to 3fa5282d6284efba62dc591697e6a687152bdcb1 #1166 Closes #1437 - CI/appveyor: increase wait for SSH server on GHA [ci skip] Blind attempt to make AppVeyor CI tests work again. - disable DSA by default Also: - add `LIBSSH2_DSA_ENABLE` to enable it explicitly. - test the above option in CI. - say 'deprecated' in docs and public header. - disable DSA in the CI server config. (OpenSSH 9.8 no longer builds with it by default) https://www.openssh.com/txt/release-9.8 Patch-by: Jose Quaresma - disable more DSA code when not enabled. Fixes #1433 Closes #1435 GitHub (30 Jul 2024) - [Viktor Szakats brought this change] tidy-up: link updates (#1434) Marc Hoersken (27 Jul 2024) - ci/GHA: revert concurrency and improve permissions Statuses are per AppVeyor event and commit, not pull-request. Also align permissions approach with curl, least priviledge. Partially reverts b08cfbc99fa4df3459db4e1ccf4263fd260e9b15. GitHub (23 Jul 2024) - [Will Cosgrove brought this change] Always init mbedtls_pk_context (#1430) In the failure case, mbedtls_pk_context could be free'd without first being initialized. - [Viktor Szakats brought this change] mbedtls: tidy-up (#1429) - [Will Cosgrove brought this change] Correctly initialize values (#1428) Fix regression with commit from #1421 Viktor Szakats (14 Jul 2024) - RELEASE-NOTES: sync [ci skip] - [Seo Suchan brought this change] mbedtls: expose `mbedtls_pk_load_file()` for our use While it's moved to pk_internal, it won't removed in mbedTLS 3.6 LTS so it's safe to redeclare it on our side to find it. This is implementing emergency fix suggested from https://github.com/libssh2/libssh2/commit/2e4c5ec4627b3ecf4b6da16f365c011dec9a31b4#commitcomment-141379351 Follow-up to e973493f992313b3be73f51d3f7ca6d52e288558 #1393 Follow-up to 2e4c5ec4627b3ecf4b6da16f365c011dec9a31b4 #1349 Closes #1421 GitHub (13 Jul 2024) - [Viktor Szakats brought this change] ci/GHA: simplify mbedTLS build hack for autotools (#1425) Follow-up to e973493f992313b3be73f51d3f7ca6d52e288558 #1393 - [Michael Buckley brought this change] Always check for null pointers before calling _libssh2_bn_set_word (#1423) - [Viktor Szakats brought this change] ci/GHA: FreeBSD 14.1, actions bump (#1424) - [Michael Buckley brought this change] Increase SFTP_HANDLE_MAXLEN back to 4092 (#1422) Match OpenSSH for compatibility. Viktor Szakats (10 Jul 2024) - ci/GHA: tidy up casing [ci skip] - REUSE: fix typo in comment - REUSE: shorten and improve Follow-up to 70b8bf314cf4566a7529c5d6eae63097a926abb0 #1419 - REUSE: upgrade to `REUSE.toml` Closes #1419 - build: stop detecting `sys/param.h` header This header is no longer used. Follow-up to 12427f4fb8e789adcee4a6e30974932883915e88 #1415 Closes #1418 - [Nicolas Mora brought this change] tests: avoid using `MAXPATHLEN`, for portability `MAXPATHLEN` is not present in some systems, e.g. GNU Hurd. Co-authored-by: Viktor Szakats Ref: 54bef4c5dad868a9d45fdbfca9729b191c0abab5 #198 Fixes #1414 Closes #1415 - cmake: sync formatting in `cmake/Find*` modules - [Michael Buckley brought this change] sftp: implement posix-rename@openssh.com Add a new function `libssh2_sftp_posix_rename_ex()` and `libssh2_sftp_posix_rename()`, which implement the posix-rename@openssh.com extension. If the server does not support this extension, the function returns `LIBSSH2_FX_OP_UNSUPPORTED` and it's up to the user to recover, possibly by calling `libssh2_sftp_rename()`. Co-authored-by: Viktor Szakats (bump to size_t) Closes #1386 - src: use `UINT32_MAX` Needs to be defined for platforms missing it, e.g. VS2008. Closes #1413 GitHub (25 Jun 2024) - [Michael Buckley brought this change] Fix a memory leak in key exchange. (#1412) Original fix submitted as a patch by Trzik. Co-authored-by: Michael Buckley Viktor Szakats (25 Jun 2024) - RELEASE-NOTES: sync [ci skip] - wolfssl: fix `EVP_Cipher()` use with v5.6.0 and older Add workaround for the wolfSSL `EVP_Cipher(*p, NULL, NULL, 0)` bug to make libssh2 work with wolfSSL v5.6.0 and older. wolfSSL fixed this issue in v5.7.0: https://github.com/wolfSSL/wolfssl/pull/7143 https://github.com/wolfSSL/wolfssl/commit/b0de0a1c95119786cf5651dd76dd7d7bdfac5a04 Without our local workaround: - v5.3.0 and older fail most tests: Ref: https://github.com/libssh2/libssh2/actions/runs/9646827522/job/26604211476#step:17:1263 - v5.4.0, v5.5.x, v5.6.0 fail these: ``` 29 - test_read-aes128-cbc (Failed) 30 - test_read-aes128-ctr (Failed) 32 - test_read-aes192-cbc (Failed) 33 - test_read-aes192-ctr (Failed) 34 - test_read-aes256-cbc (Failed) 35 - test_read-aes256-ctr (Failed) ``` Ref: https://github.com/libssh2/libssh2/actions/runs/9646827522/job/26604233819#step:17:978 Oddly enough the workaround breaks OpenSSL tests, so only enable it for the affected wolfSSL versions. Also add new build-from-source wolfSSL CI job to test the new codepath. wolfSSL has a build bug where `wolfssl/options.h` and `wolfssl/version.h` are not copied to the `install` destination with autotools. With CMake it has a different bug where `wolfcrypt/sp_int.h` is not copied (with v5.4.0). And another with CMake where `FIPS_mode()` remains missing (with v5.6.0 and earlier.) Therefore use CMake with v5.5.4 and a workaround for `FIPS_mode()`. Another option is autotools with v5.4.0 and a workaround for `install`, but CMake builds quicker. Regression-from 3c953c05d67eb1ebcfd3316f279f12c4b1d600b4 #797 Fixes #1020 Fixes #1299 Assisted-by: Michael Buckley via #1394 Closes #1394 (another attempt to fix the mentioned wolfSSL bug) Closes #1407 - wolfssl: bump version in upstream issue comment [ci skip] - wolfssl: require v5.4.0 for AES-GCM Earlier versions crash while running tests. This patch is part of a series of fixes to make wolfSSL AES-GCM support work together with libssh2. Possibly related is this wolfSSL bugfix patch, released in v5.4.0: https://github.com/wolfSSL/wolfssl/pull/5205 https://github.com/wolfSSL/wolfssl/commit/fb3c611275dfe454c331baa0818445a0406c208a "Fix another AES-GCM EVP control command issue" Ref: #1020 Ref: #1299 Cherry-picked from #1407 Closes #1411 - tests: fix excluding AES-GCM tests Replace hard-coded crypto backends and rely on `LIBSSH2_GCM` macro to decide whether to run AES-GCM tests. Without this, build attempted to run AES-GCM tests (and failed) for crypto backends that have conditional support for this feature, e.g. wolfSSL without the necessary features built-in (as in before Homewbrew wolfssl 5.7.0_1, or OpenSSL v1.1.0 and older). This patch is part of a series of fixes to make wolfSSL AES-GCM support work together with libssh2. Cherry-picked from #1407 Closes #1410 - ci/GHA: fix wolfSSL-from-source AES-GCM tests Turns out these tests: ``` 31 - test_read-aes128-gcm@openssh.com (Failed) 36 - test_read-aes256-gcm@openssh.com (Failed) ``` were failing because AES-GCM wasn't enabled in libssh2. This in turn happened because the `WOLFSSL_AESGCM_STREAM` macro wasn't enabled while building wolfSSL. Which happened because this macro isn't enabled by any CMake-level wolfSSL option. Passing it as `CPPFLAGS` fixes it. This allows enabling tests with wolfSSL 5.7.0. Follow-up to d4cea53f53c78febad14b4caa600e25d1aaf92fd #1408 Closes #1409 - ci/GHA: add Linux job with latest wolfSSL built from source After this patch it's possible to run tests with wolfSSL 5.7.0. wolfSSL 5.7.0 fixes this bug that affects open issues #1020 and #1299: https://github.com/wolfSSL/wolfssl/pull/7143 `-DWOLFSSL_OPENSSLALL=ON` is necessary for `wolfSSL_FIPS_mode()` Closes #1408 - ci/GHA: tidy up build-from-source steps [ci skip] - make curl downloads less verbose. - fix cmake warning: ``` CMake Warning: No source or binary directory provided. Both will be assumed to be the same as the current working directory, but note that this warning will become a fatal error in future CMake releases. ``` Ref: https://github.com/libssh2/libssh2/actions/runs/9509866494/job/26213472410#step:5:32 - [Adam brought this change] src: fix type warning in `libssh2_sftp_unlink` macro The `libssh2_sftp_unlink` macro was implicitly casting the `size_t` returned by `strlen` to the `unsigned int` type expected by `libssh2_sftp_unlink_ex`. This fix adds an explicit cast to match similar macro definitions in the same file (e.g. `libssh2_sftp_rename`, `libssh2_sftp_mkdir`). Closes #1406 - libssh2.pc: reference mbedcrypto pkgconfig mbedtls 3.6.0 got pkgconfig support: https://github.com/Mbed-TLS/mbedtls/commit/a4d17b34f354557838e05d2cb47200e8dcaaf59b Reference it from `libssh2.pc`. Closes #1405 - tidy-up: typo in comment [ci skip] - RELEASE-NOTES: sync [ci skip] Also bump planned deprecation dates. - ci/GHA: show configure logs on failure and other tidy-ups - dump cmake error log on configure failure. (for cmake 3.26 and newer) - dump `config.log` on autotools configure failure. - convert specs filename to Windows format before passing to CMake. - add missing quotes. Closes #1403 - ci/GHA: bump parallel jobs to nproc+1 Ref: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories Closes #1402 - ci/GHA: show test logs on failure Closes #1401 - ci/GHA: fix `Dockerfile` failing after Ubuntu package update Likely due an upstream Ubuntu package update (requiring an apt-get install call beforehand), tests run via autotools started failing with no change in the libssh2 repo: ``` FAIL: test_aa_warmup ==================== Error running command 'docker build --quiet -t libssh2/openssh_server %s' (exit 256): Dockerfile:10 -------------------- 8 | && apt-get clean \ 9 | && rm -rf /var/lib/apt/lists/* 10 | >>> RUN mkdir /var/run/sshd 11 | 12 | # Chmodding because, when building on Windows, files are copied in with -------------------- ERROR: failed to solve: process "/bin/sh -c mkdir /var/run/sshd" did not complete successfully: exit code: 1 Failed to build docker image Cannot stop session - none started Cannot stop container - none started Command: docker build --quiet -t libssh2/openssh_server ../../tests/openssh_server FAIL test_aa_warmup (exit status: 1) ``` Ref: https://github.com/libssh2/libssh2/actions/runs/9322194756/job/25662748095#step:11:390 Fix it by skipping `mkdir` if `/var/run/sshd` already exists. (Why cmake-based jobs aren't affected, I don't know.) Ref: https://github.com/libssh2/libssh2/commit/50143d5867d35df76a6cf589ca8a13b22105aa64#commitcomment-142560875 Closes #1400 - ci/GHA: use ubuntu-latest with OmniOS job It's the same as ubuntu-22.04. Also update OmniOS package search link. - ci: disable dependency tracking in autotools builds For better build performance. Dependency tracking causes a build overhead while compiling to help a subsequent build, but in CI there is never one and the extra work is discarded. Closes #1396 - mbedtls: fail to compile with v3.6.0 outside CI A compile-time failure is preferred over an unexpected one at runtime. The problem is silenced with a macro in CI and this macro will have to be added to more platforms when mbedTLS v3.6.0 reaches them. Follow-up to 2e4c5ec4627b3ecf4b6da16f365c011dec9a31b4 #1349 Closes #1393 - tests: drop default cygpath option `-u` - tidy-up: fix typo found by codespell Ref: https://github.com/libssh2/libssh2/actions/runs/9224795055/job/25380857082?pr=1393#step:4:5 - ci/GHA: shell syntax tidy-up Closes #1390 - RELEASE-NOTES: sync [ci skip] - ci/GHA: bump NetBSD/OpenBSD, add NetBSD arm64 job OpenBSD arm64 jobs were very slow, so skipped that. Closes #1388 - autotools: fix to update `LDFLAGS` for each detected dependency autotools lib detection routine failed to extend LDFLAGS for each detection. This could cause successful detection of a dependency, but later failing to use it. This did not cause an issue as long as all dependencies lived under the same prefix, but started breaking on macOS ARM + Homebrew where this was no longer true for mbedTLS and zlib in particular. Follow-up to 844115393bffb4e92c6569204cbe4cd8e553480d #1381 Follow-up to ae2770de25949bc7c74e60b4cc6a011bbe1d3d7c #1377 Closes #1384 GitHub (8 May 2024) - [Michael Buckley brought this change] OpenSSL 3: Fix calculating DSA public key (#1380) Viktor Szakats (8 May 2024) - ci/GHA: tidy-up wolfSSL autotools config on macOS Closes #1383 - ci/GHA: shorter mbedTLS autotools workaround Follow-up to 844115393bffb4e92c6569204cbe4cd8e553480d #1381 Closes #1382 GitHub (8 May 2024) - [Michael Buckley brought this change] ci: fix mbedtls runners on macOS (#1381) Sets LDFLAGS while configuring the autoconf mbedTLS build for macOS. Viktor Szakats (29 Apr 2024) - RELEASE-NOTES: sync [ci skip] - [binary1248 brought this change] wincng: fix `DH_GEX_MAXGROUP` set higher than supported In 1c3a03ebc3166cf69735111aba2b8cee57cdba51 #493, `LIBSSH2_DH_GEX_MAXGROUP` was introduced to specify crypto-backend-specific modulus sizes. Unfortunately, the max size for the wincng DH modulus was defined to 8192, probably because this is the value most other backends support. According to Microsoft documentation [1], `BCryptGenerateKeyPair` currently only supports up to 4096-bit keys when the selected algorithm is `BCRYPT_DH_ALGORITHM`. Requesting larger keys when calling `BCryptGenerateKeyPair` in `_libssh2_dh_key_pair` always results in `STATUS_INVALID_PARAMETER` being returned and ultimately key exchange failing. When attempting to connect to any server that offers 8192 bit DH, this causes key exchange to always fail when using the wincng backend. Reducing `LIBSSH2_DH_GEX_MAXGROUP` to 4096 fixes the issue. [1] https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgeneratekeypair Closes #1372 - build: silence warnings inside `FD_SET()`/`FD_ISSET()` macros Use an ugly workaround to silence `-Wsign-conversion` warnings triggered by the internals of `FD_SET()`/`FD_ISSET()` macros. They've been showing up in OmniOS CI builds when compiling `example` programs. They also have been seen with older Cygwin and other envs and configurations. Also scope two related variables in examples. E.g.: ``` ../../example/direct_tcpip.c:251:9: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] 251 | FD_SET(forwardsock, &fds); | ^~~~~~ ../../example/direct_tcpip.c:251:9: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:251:9: warning: conversion to 'long unsigned int' from 'long int' may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:251:9: warning: conversion to 'long int' from 'long unsigned int' may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:259:18: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] 259 | if(rc && FD_ISSET(forwardsock, &fds)) { | ^~~~~~~~ ../../example/direct_tcpip.c:259:18: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:259:18: warning: conversion to 'long unsigned int' from 'long int' may change the sign of the result [-Wsign-conversion] ``` Ref: https://github.com/libssh2/libssh2/actions/runs/8854199687/job/24316762831#step:3:2020 Closes #1379 - autotools: use `AM_CFLAGS` Use `AM_CFLAGS` to pass custom, per-target C flags. This replaces using `CFLAGS` which triggered this warning when running `autoreconf -fi`: ``` tests/Makefile.am:8: warning: 'CFLAGS' is a user variable, you should not override it; tests/Makefile.am:8: use 'AM_CFLAGS' instead ``` (Only for `tests`, even though `example` and `src` also used this method. The warning is also missing from curl, that also uses `CFLAGS`.) Follow-up to 3ec53f3ea26f61cbf2e0fbbeccb852fca7f9b156 #1286 Closes #1378 GitHub (25 Apr 2024) - [Viktor Szakats brought this change] ci/GHA: fix gcrypt with autotools/macOS/Homebrew/ARM64 (#1377) mbedtls configure fails to detect anything due to this: ``` configure:23101: gcc -o conftest -g -O2 -I/opt/homebrew/include conftest.c -lmbedcrypto -lz >&5 ld: library 'mbedcrypto' not found clang: error: linker command failed with exit code 1 (use -v to see invocation) ``` Viktor Szakats (25 Apr 2024) - autotools: delete bogus square bracket from help text [ci skip] Follow-up to 3f98bfb0900b5e68445a339cfebc60b307a24650 #1368 GitHub (25 Apr 2024) - [Viktor Szakats brought this change] ci/GHA: fix verbose option for autotools jobs (#1376) Also enable verbose for macOS `make` step. - [Viktor Szakats brought this change] ci/GHA: dump `config.log` on failure for macOS autotools jobs (#1375) - [Viktor Szakats brought this change] ci/GHA: fix `autoreconf` failure on macOS/Homebrew (#1374) By manually installing `libtool`. ``` autoreconf -fi shell: /bin/bash -e {0} configure.ac:75: error: possibly undefined macro: AC_LIBTOOL_WIN32_DLL If this token and others are legitimate, please use m4_pattern_allow. See the Autoconf documentation. configure.ac:76: error: possibly undefined macro: AC_PROG_LIBTOOL autoreconf: error: /opt/homebrew/Cellar/autoconf/2.72/bin/autoconf failed with exit status: 1 ``` Ref: https://github.com/libssh2/libssh2/actions/runs/8833608758/job/24253334557#step:4:1 - [Viktor Szakats brought this change] ci/GHA: fixup Homebrew location (for ARM runners) (#1373) GHA macOS runners became ARM64 machines. Make the Homebrew prefix dynamic to adapt to these installations. Viktor Szakats (14 Apr 2024) - RELEASE-NOTES: sync [ci skip] - [Patrick Monnerat brought this change] os400: Add two recent files to the distribution Closes #1364 - wincng: add to ci/GHA, add `./configure` option `--enable-ecdsa-wincng` - add `./configure` option `--enable-ecdsa-wincng` - add WinCNG autotools jobs to GHA. - enable WinCNG ECDSA in some GHA jobs (both CMake and autotools). Follow-up to 3e72343737e5b17ac98236c03d5591d429b119ae #1315 Closes #1368 GitHub (14 Apr 2024) - [Johannes Passing brought this change] wincng: add ECDSA support for host and user authentication (#1315) The WinCNG backend currently only supports DSA and RSA. This PR adds ECDSA support for host and user authentication. * Disable WinCNG ECDSA support by default to maintain backward compatibility for projects that target versions below Windows 10. * Add cmake option `ENABLE_ECDSA_WINCNG` to guard ECDSA support. * Update AppVeyor job matrix to only enable ECDSA on Server 2016+ Viktor Szakats (14 Apr 2024) - ci: enable Unity mode for most CMake builds Ref: 7129ea9ca8cca86dac80a6bac2d63937987efe9d #1034 Closes #1367 - os400: fix shellcheck warnings in scripts (fixups) - Build scripts must be executed by the os/400 shell (sh), not bash which is a PASE program: The `-ot` non-POSIX test extension works in os/400 as well. Ref: https://github.com/libssh2/libssh2/pull/1364#issue-2241646754 - Drop/fixup mods trying to make some syntax highlighters happier. Follow-up to c6625707b94d9093f38f1a0a4d89c11b64f12ba8 #1358 Assisted-by: Patrick Monnerat Closes #1364 Closes #1366 - cmake: style tidy-up (more) Follow-up to 3fa5282d6284efba62dc591697e6a687152bdcb1 #1166 Closes #1365 - RELEASE-NOTES: sync [ci skip] - os400: fix shellcheck warnings in scripts - use `$()` instead of backticks, and re-arrange double-quotes inside. - add missing `|| exit 1` to `cd` calls. (could be dropped by using `set -eu`.) - add `-n` to a few `if`s. - shorten redirections by using `{} >` (as shellcheck recommended). - silence warnings where variables were detected as unused (SC2034). - a couple misc updates to silence warnings. - switch to bash shebang for `-ot` feature. - split two lines to unbreak syntax highlighting in my editor. (`$(expr \`, `$(dirname \`) Also enable CI checks for OS/400 shell scripts. Ref: d88b9bcdafe9d19aad2fb120d0a0acb3edab64f7 Closes #1358 - RELEASE-NOTES: sync [ci skip] - ci: add shellcheck job and script Add FIXME for OS/400 scripts. Cherry-picked from #1358 - tests: fix shellcheck issues in `test_sshd.test` Cherry-picked from #1358 - RELEASE-NOTES: sync [ci skip] GitHub (9 Apr 2024) - [Viktor Szakats brought this change] ci/appveyor: re-enable OpenSSL 3, also bump to 3.2.1 (#1363) Ref: 104744f4a523de574ce3767c50948d9b8385be4c #1348 Viktor Szakats (9 Apr 2024) - ci: use a better test timestamp [ci skip] Mar 27 2024 08:00:00 GMT+0000 Follow-up to 2d765e454d98b794a5e5bbc497b1fcba4a9b8c4b #1360 GitHub (9 Apr 2024) - [Viktor Szakats brought this change] ci: verify build and install from tarball (#1362) Install verification based on: https://github.com/curl/curl/blob/28c5ddf13ac311d10bc4e8f9fc4ce0858a19b888/scripts/installcheck.sh Viktor Szakats (9 Apr 2024) - tidy-up: dir names, command-line [ci skip] Follow-up to 2d765e454d98b794a5e5bbc497b1fcba4a9b8c4b #1360 - cmake: tidy up function name casing in `CopyRuntimeDependencies.cmake` Use lowercase to match callers. GitHub (9 Apr 2024) - [Viktor Szakats brought this change] ci: add reproducibility test for `maketgz` (#1360) Viktor Szakats (9 Apr 2024) - maketgz: add reproducible dir entries to tarballs In the initial implementation of reproducible tarballs, they were missing directory entries, while .zip archives had them. It meant that on extracting the tarball, on-disk directory entries got the current timestamp. This patch fixes this by including directory entries in the tarball, with reproducible timestamps. It also moves sorting inside tar, to ensure reproducible directory entry timestamps on extract (without the need of `--delay-directory-restore` option, when extracting with GNU tar. BSD tar got that right by default.) GNU tar 1.28 (2014-07-28) introduced `--sort=`. Follow-up to d52fe1b4358fab891037d86b5c73c098079567db #1357 Closes #1359 - ci/GHA: improve version number in `maketgz` test Follow-up to cba7f97506c1b8e5ff131bbbc57b5796ac634c56 #1353 GitHub (8 Apr 2024) - [Michael Buckley brought this change] src: check the return value from `_libssh2_bn_*()` functions (#1354) Found by oss-fuzz. In `diffie_hellman_sha_algo()`, we were calling `_libssh2_bn_from_bin()` with data recieved by the server without checking whether that data was zero-length or ridiculously long. In the OpenSSL backend, this would cause `_libssh2_bn_from_bin()` to fail an allocation, which would eventually lead to a NULL dereference when the bignum was used. Add the same check for `_libssh2_bn_set_word()` and `_libssh2_bn_to_bin()`. Viktor Szakats (8 Apr 2024) - maketgz: reproducible tarballs/zip, display tarball hashes - support `SOURCE_DATE_EPOCH` for reproducibility. - make tarballs reproducible. - make file timestamps in tarball/zip reproducible. - make directory timestamps in zip reproducible. - make timestamps of tarballs/zip reproducible. - make file order in tarball/zip reproducible. - use POSIX ustar tarball format to avoid supply chain vulnerability: https://seclists.org/oss-sec/2021/q4/0 - make uid/gid in tarball reproducible. - omit owner user/group names from tarball for reproducibility and privacy. - omit current timestamp from .gz header for reproducibility. - display SHA-256 hashes of produced tarballs/zip. (Requires `sha256sum`) - re-sync formatting with curl's `maketgz`. Closes #1357 - maketgz: `set -eu`, reproducibility, improve zip, add CI test - set bash `-eu`. - fix bash `-eu` issues. - apply `TZ=UTC` and `LC_ALL=C` for reproducibility. - sort `.zip` entries for reproducibility. - zip with `--no-extra` for reproducibliity. - use maximum zip compression. - add the gpg sign command-line. Copied from curl. - add CI test for `maketgz`. Closes #1353 - RELEASE-NOTES: sync and cleanups [ci skip] GitHub (3 Apr 2024) - [Tejaswikandula brought this change] Support RSA SHA2 cert-based authentication (rsa-sha2-512_cert and rsa-sha2-256_cert) (#1314) Replicating OpenSSH's behavior to handle RSA certificate authentication differently based on the remote server version. 1. For OpenSSH versions >= 7.8, ascertain server's support for RSA Cert types by checking if the certificate's signature type is present in the `server-sig-algs`. 2. For OpenSSH versions < 7.8, Set the "SSH_BUG_SIGTYPE" flag when the RSA key in question is a certificate to ignore `server-sig-algs` and only offer ssh-rsa signature algorithm for RSA certs. This arises from the fact that OpenSSH versions up to 7.7 accept RSA-SHA2 keys but not RSA-SHA2 certificate types. Although OpenSSH <=7.7 includes RSA-SHA2 keys in the `server-sig-algs`, versions <=7.7 do not actually support RSA certs. Therefore, server sending RSA-SHA2 keys in `server-sig-algs` should not be interpreted as indicating support for RSA-SHA2 certs. So, `server-sig-algs` are ignored when the RSA key in question is a cert, and the remote server version is 7.7 or below. Relevant sections of the OpenSSH source code: Assisted-by: Will Cosgrove Reviewed-by: Viktor Szakats Viktor Szakats (3 Apr 2024) - RELEASE-NOTES: sync [ci skip] Also fix to include 3-digit issue/PR references. - mbedtls: add workaround + FIXME to build with 3.6.0 This is just a stub to make `_libssh2_mbedtls_ecdsa_new_private` compile. mbedtls 3.6.0 silently deleted its public API `mbedtls_pk_load_file`, which this function relies on. Closes #1349 GitHub (3 Apr 2024) - [Viktor Szakats brought this change] ci/appveyor: OpenSSL 3 no longer found by CMake, revert to 1.1.1 (#1348) Ref: https://github.com/appveyor/build-images/commit/702e8cdca01f28f6a40687783f493c786cebbe2c Ref: https://github.com/appveyor/build-images/pull/149 Viktor Szakats (3 Apr 2024) - docs: improve `libssh2_userauth_publickey_from*` manpages Reported-by: Lyndon Brown Assisted-by: Ryan Kelley Fixes #652 Closes #1308 Closes #xxxx - RELEASE-NOTES: sync [ci skip] GitHub (2 Apr 2024) - [Viktor Szakats brought this change] test debian:testing-slim post xz backdoor removal (#1346) The unexplained CI fallouts are gone with the latest debian:testing (20240330). Ref #1328 #1329 #1338. Closes #1346 Viktor Szakats (30 Mar 2024) - ci: use Linux runner for BSDs, add arm64 FreeBSD 14 job - bump cross-platform-actions to 0.23.0. Ref: https://github.com/cross-platform-actions/action/releases/tag/v0.23.0 - switch to Linux runners (from macOS) for cross-platform-actions. It's significantly faster. - switch back FreeBSD 14 job to cross-platform-actions. Also switch back to default shell. - add FreeBSD 14 arm64 job. Closes #1343 - ci: use single quotes in yaml [ci skip] - ci: tidy-up job order [ci skip] - build: drop `-Wformat-nonliteral` warning suppressions Also markup a vararg function as such. In functions marked up as vararg functions, there is no need to suppress `-Wformat-nonliteral` warnings. It's done automatically by the compiler. Closes #1342 - ci: delete flaky FreeBSD 13.2 job Keep FreeBSD 14. - RELEASE-NOTES: sync [ci skip] - example: restore `sys/time.h` for AIX In AIX, `time.h` header file doesn't have definitions like `fd_set`, `struct timeval`, which are found in `sys/time.h`. Add `sys/time.h` to files affected when available. Regression from e53aae0e16dbf53ddd1a4fcfc50e365a15fcb8b9 #1001. Reported-by: shubhamhii on GitHub Assisted-by: shubhamhii on GitHub Fixes #1334 Fixes #1335 Closes #1340 - userauth: avoid oob with huge interactive kbd response - If the length of a response is `UINT_MAX - 3` or larger, an unsigned integer overflow occurs on 64-bit systems. Avoid such truncation to always allocate enough memory to avoid subsequent out of boundary writes. Patch-by: Tobias Stoeckmann - also add FIXME to bump up length field to `size_t` (ABI break) Closes #1337 GitHub (28 Mar 2024) - [Josef Cejka brought this change] transport: check ETM on remote end when receiving (#1332) We should check if encrypt-then-MAC feature is enabled in remote end's configuration. Fixes #1331 - [Josef Cejka brought this change] kex: always add extension indicators to kex_algorithms (#1327) KEX pseudo-methods "ext-info-c" and "kex-strict-c-v00@openssh.com" are in default kex method list but they were lost after configuring custom kex method list in libssh2_session_method_pref(). Fixes #1326 - [Jiwoo Park brought this change] cmake: use the imported target of FindOpenSSL module (#1322) * Use the imported target of FindOpenSSL module * Build libssh2 before test runner * Use find_package() in the CMake config file * Use find_dependency() rather than find_package() * Install CMake module files and use them in the config file * Use elseif() to choose the crypto backend - [Andrei Augustin brought this change] docs: update INSTALL_AUTOTOOLS (#1316) corrected --with-libmbedtls-prefix to current option --with-libmbedcrypto-prefix Viktor Szakats (28 Mar 2024) - ci: don't parallelize `distcheck` job A while ago the `distcheck` CI job became flaky. This continued after switching to Debian stable (from testing). Try stabilzing it by running it single-threaded. Closes #1339 - Dockerfile: switch to Debian stable (from testing) This fixes flakiness experienced recently with two OpenSSL jobs and one libgcrypt job, and/or intermittently causing all Docker-based tests to fail. Reported-by: András Fekete Fixes #1328 Fixes #1329 Closes #1338 GitHub (22 Feb 2024) - [Michael Buckley brought this change] Supply empty hash functions for mac_method_hmac_aesgcm to avoid a crash when e.g. setting LIBSSH2_METHOD_CRYPT_CS (#1321) - [Michael Buckley brought this change] gen_publickey_from_dsa: Initialize BIGNUMs to NULL for OpenSSL 3 (#1320) Viktor Szakats (23 Jan 2024) - RELEASE-NOTES: add algo deprecation notices [ci skip] Closes #1307 - RELEASE-NOTES: sync [ci skip] GitHub (22 Jan 2024) - [Juliusz Sosinowicz brought this change] wolfssl: enable debug logging in wolfSSL when compiled in (#1310) Co-authored-by: Viktor Szakats - [monnerat brought this change] os400: maintain up to date (#1309) - Handle MD5 conditionals in os400qc3. - Check for errors in os400qc3 pbkdf1. - Implement an optional build options override file. - Sync ILE/RPG copy files with current C header files. - Allow a null session within a string conversion cache. - Add an ILE/RPG example. - Adjust outdated copyrights in changed files. Viktor Szakats (18 Jan 2024) - RELEASE-NOTES: sync - src: check hash update/final success Also: - delete unused internal macro `libssh2_md5()` where defined. - prefix `libssh2_os400qc3_hash*()` function names with underscore. These are public/visible, but internal. - add FIXMEs to OS/400 code to verify update/final calls; some OS API, some internal. Ref: https://github.com/libssh2/libssh2/pull/1301#discussion_r1446861650 Reviewed-by: Michael Buckley Reviewed-by: Patrick Monnerat Closes #1303 - RELEASE-NOTES: sync [ci skip] GitHub (18 Jan 2024) - [Ryan Kelley brought this change] openssl: fix cppcheck found NULL dereferences (#1304) * Fix NULL dereference in gen_publickey_from_rsa_evp and gen_publickey_from_dsa_evp. * Add checks for en_publickey_from_ec_evp and en_publickey_from_ed_evp Viktor Szakats (12 Jan 2024) - openssl: delete internal `read_openssh_private_key_from_memory()` It was wrapping another internal function with no added logic. Closes #1306 - openssl: formatting/whitespace Also use `NULL` instead of `0` for pointers. Closes #1305 - HACKING-CRYPTO: more fixups [ci skip] Follow-up to f64885b6ab9bbdae2da9ebd70f4dd5cea56e838a #1297 - HACKING-CRYPTO: fixups [ci skip] Follow-up to f64885b6ab9bbdae2da9ebd70f4dd5cea56e838a #1297 - RELEASE-NOTES: sync [ci skip] - src: check hash init success Before this patch, SHA2 and SHA1 init function results were cast to `void`. This patch makes sure to verify these values. Also: - exclude an `assert(0)` from release builds in `_libssh2_sha_algo_ctx_init()`. (return error instead) - fix indentation / whitespace Reviewed-by: Michael Buckley Closes #1301 - mac: handle low-level errors - update low-level hmac functions from macros to functions. - libgcrypt: propagate low-level hmac errors. - libgcrypt: add error checks for hmac calls. - os400qc3: add error checks, propagate them. Assisted-by: Patrick Monnerat - mbedtls: fix propagating low-level hmac errors. - wincng: fix propagating low-level hmac errors. - mac: verify success of low-level hmac functions. - knownhost: verify success of low-level hmac functions. - transport: verify success of MAC hash call. - minor type cleanup in wincng. - delete unused ripemd wrapper in wincng. - delete unused SHA384 wrapper in mbedtls. Reported-by: Paul Howarth Reviewed-by: Michael Buckley Closes #1297 GitHub (8 Jan 2024) - [Michael Buckley brought this change] Fix an out-of-bounds read in _libssh2_kex_agree_instr when searching for a KEX not in the server list (#1302) Viktor Szakats (21 Dec 2023) - RELEASE-NOTES: sync [ci skip] - ci/appveyor: re-enable parallel mode The comment cited earlier is no longer true with recent CMake versions. This options does actually enable parallel builds with MSVC since CMake v3.26.0: https://gitlab.kitware.com/cmake/cmake/-/issues/20564 The effect isn't much for libssh2, because it spends most time in tests, but let's enable it anyway for efficiency. Ref: 0d08974633cfc02641e6593db8d569ddb3644255 #884 Ref: 7a039d9a7a2945c10b4622f38eeed21ba6b4ec55 #867 Closes #1294 - ci/gha: review/fixup auto-cancel settings - use the group expression from `reuse.yml` (via curl). - add auto-cancel for `ci` and `cifuzz`. - add auto-cancel to `appveyor_docker`. I'm just guessing here. The hope is that it fixes AppVeyor CI runs when re-pushing a PR. This frequently caused the freshly pushed session to fail waiting for a connection. - sync group expression in `appveyor_status` with `reuse`. Closes #1292 - RELEASE-NOTES: fix casing in GitHub names [ci skip] - RELEASE-NOTES: synced [ci skip] Closes #1279 - [Michael Buckley brought this change] src: add 'strict KEX' to fix CVE-2023-48795 "Terrapin Attack" Refs: https://terrapin-attack.com/ https://seclists.org/oss-sec/2023/q4/292 https://osv.dev/list?ecosystem=&q=CVE-2023-48795 https://github.com/advisories/GHSA-45x7-px36-x8w8 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795 Fixes #1290 Closes #1291 - session: add `libssh2_session_callback_set2()` Add new `libssh2_session_callback_set2()` API that deprecates `libssh2_session_callback_set()`. The new implementation offers the same functionality, but accepts and returns a generic function pointer (of type `libssh2_cb_generic *`), as opposed to the old function that used data pointers (`void *`). The new solution thus avoids data to function (and vice versa) pointer conversions, which has undefined behaviour in standard C. About the name: It seems the `*2` suffix was used in the past for replacement functions for deprecated ones. Let's stick with that. `*_ex` was preferred for new functions that extend existing ones with new features. Closes #1285 - build: enable `-pedantic-errors` According to the manual, this isn't the same as `-Werror -pedantic`. Enable it together with `-Werror`. https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-pedantic-errors-1 This option results in autotools feature detection going into crazies. To avoid this, we add it to `CFLAGS` late. Idea copied from curl. This option has an effect only with gcc 5.0 and newer as of this commit. Let's enable it for clang and older versions too for simplicity. Ref: https://github.com/curl/curl/commit/d5c0351055d5709da8f3e16c91348092fdb481aa https://github.com/curl/curl/pull/2747 Closes #1286 - build: add mingw-w64 support to `LIBSSH2_PRINTF()` attribute And fix the warning it detected. Closes #1287 - libssh2.h: add deprecated function warnings With deprecated-at versions and suggested replacement function. It's possible to silence them by defining `LIBSSH2_DISABLE_DEPRECATION`. Also add depcreated-at versions to documentation, and unify wording. Ref: https://github.com/libssh2/libssh2/pull/1260#issuecomment-1837017987 Closes #1289 - ci/spellcheck: delete redundant option [ci skip] `--check-hidden` not necessary when passing filenames explicitly. Follow-up to a79218d3a058a333bb9de14079548a3511679a04 - tidy-up: add empty line for clarity [ci skip] - build: FIXME `-Wsign-conversion` to be errors [ci skip] - src: disable `-Wsign-conversion` warnings, add option to re-enable To avoid the log noise till we fix those ~360 compiler warnings. Also add macro `LIBSSH2_WARN_SIGN_CONVERSION` to re-enable them. Follow-up to afa6b865604019ab27ec033294edfe3ded9ae0c0 #1257 Closes #1284 - cmake: fix indentation [ci skip] - example, tests: call `WSACleanup()` for each `WSAStartup()` On Windows. Closes #1283 - RELEASE-NOTES: update credits [ci skip] Ref: https://github.com/libssh2/libssh2/pull/1241#issuecomment-1830118584 - RELEASE-NOTES: avoid splitting names, fix typo, refine order [ci skip] - RELEASE-NOTES: synced [ci skip] - add portable `LIBSSH2_SOCKET_CLOSE()` macro Add `LIBSSH2_SOCKET_CLOSE()` to the public `libssh2.h` header, for user code. It translates to `closesocket()` on Windows and `close()` on other platforms. Use it in example code. It makes them more readable by reducing the number of `_WIN32` guards. Closes #1278 - ci: add FreeBSD 14 job, fix issues - install bash to fix error when running tests: ``` ERROR: test_sshd.test - missing test plan ERROR: test_sshd.test - exited with status 127 (command not found?) ===================================== [...] # TOTAL: 4 # PASS: 2 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 2 [...] env: bash: No such file or directory ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7133852508/job/19427420687#step:3:3998 - fix sshd issue when running tests: ``` # sshd log: # Server listening on :: port 4711. # Server listening on 0.0.0.0 port 4711. # Authentication refused: bad ownership or modes for file /home/runner/work/libssh2/libssh2/tests/key_rsa.pub # Authentication refused: bad ownership or modes for file /home/runner/work/libssh2/libssh2/tests/openssh_server/authorized_keys ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7134629175/job/19429828342#step:3:4059 Cherry-picked from #1277 Closes #1277 - ci: add OmniOS job, fix issues - use GNU Make, to avoid errors: ``` make: Fatal error in reader: Makefile, line 983: Badly formed macro assignment ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7134629175/job/19429838379#step:3:1956 Caused by `?=` in `Makefile.am`. Fix it just in case. ``` make: Fatal error in reader: Makefile, line 438: Unexpected end of line seen ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7135524843/job/19432451767#step:3:1966 It's around line 43 in `Makefile.am`, reason undiscovered. - fix error: ``` ../../src/hostkey.c:1227:44: error: pointer targets in passing argument 5 of '_libssh2_ed25519_sign' differ in signedness [-Werror=pointer-sign] 1227 | datavec[0].iov_base, datavec[0].iov_len); | ~~~~~~~~~~^~~~~~~~~ | | | caddr_t {aka char *} ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7135102832/job/19431233967#step:3:2225 https://docs.oracle.com/cd/E36784_01/html/E36887/iovec-9s.html - FIXME: new `-Wsign-conversion` warnings appeared in examples: ``` ../../example/direct_tcpip.c:251:9: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] 251 | FD_SET(forwardsock, &fds); | ^~~~~~ ../../example/direct_tcpip.c:251:9: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:251:9: warning: conversion to 'long unsigned int' from 'long int' may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:251:9: warning: conversion to 'long int' from 'long unsigned int' may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:259:18: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] 259 | if(rc && FD_ISSET(forwardsock, &fds)) { | ^~~~~~~~ ../../example/direct_tcpip.c:259:18: warning: conversion to 'long unsigned int' from 'libssh2_socket_t' {aka 'int'} may change the sign of the result [-Wsign-conversion] ../../example/direct_tcpip.c:259:18: warning: conversion to 'long unsigned int' from 'long int' may change the sign of the result [-Wsign-conversion] [...] ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7136086865/job/19433997429#step:3:3450 Cherry-picked from #1277 - example: use `libssh2_socket_t` in X11 example Cherry-picked from #1277 - [Aaron Stone brought this change] Handle EINTR from send/recv/poll/select to try again as the error is not fatal Integration-patches-by: Viktor Szakats Fixes #955 Closes #1058 - appveyor: delete UWP job broken since Visual Studio upgrade Few days ago UWP job started permafailing. fail: https://ci.appveyor.com/project/libssh2org/libssh2/builds/48678129/job/yb8n2pox8mfjwv6m good: https://ci.appveyor.com/project/libssh2org/libssh2/builds/48673013 Other projects also affected: https://ci.appveyor.com/project/c-ares/c-ares/builds/48687390/job/l0fo4b0sijvqkw9r No related local update. Same CMake version. Same CI image. This seems to be the culprit, which could mean that this update broke CMake detection, needs a different CMake configuration on our end, or that this MSVC update pulled support for UWP apps: fail: -- The C compiler identification is MSVC 19.38.33130.0 (~ Visual Studio 2022 v17.8) good: -- The C compiler identification is MSVC 19.37.32825.0 (~ Visual Studio 2022 v17.7) If this is v17.8, release notes don't readily suggest a feature removal: https://learn.microsoft.com/en-us/visualstudio/releases/2022/release-notes-v17.8 So it might just be UWP accidentally broken in this release. Closes #1275 - checksrc: sync with curl Closes #1272 - autotools: delete `--disable-tests` option, fix CI tests Originally added to improve build performance by skipping building tests. But, there seems to be no point in this, because autotools doesn't build tests by default, unless explicitly invoking `make check`. Delete this option from Cygwin and FreeBSD CI tests, where it caused `make check` to do nothing. Tests are built now, and runtime tests are too, where supported. Also disable Docker-based tests for these, and add a missing `make -j3` for FreeBSD. Reverts 7483edfada1f7e17cf8f9ac1c87ffa3d814c987e #715 Closes #1271 GitHub (6 Dec 2023) - [ren mingshuai brought this change] build: add `LIBSSH2_NO_DEPRECATED` option (#1266) The following APIs have been deprecated for over 10 years and use `LIBSSH2_NO_DEPRECATED` to mark them as deprecated: libssh2_session_startup() libssh2_banner_set() libssh2_channel_receive_window_adjust() libssh2_channel_handle_extended_data() libssh2_scp_recv() Add these options to disable them: - autotools: `--disable-deprecated` - cmake: `-DLIBSSH2_NO_DEPRECATED=ON` - `CPPFLAGS`: `-DLIBSSH2_NO_DEPRECATED` Fixes #1259 Replaces #1260 Co-authored-by: Viktor Szakats Closes #1267 Viktor Szakats (5 Dec 2023) - autotools: show the default for `hidden-symbols` option Closes #1269 - tidy-up: bump casts from int to long for large C99 types in printfs Cast large integer types to avoid dealing with printf masks for `size_t` and other C99 types. Some of existing code used `int` for this, bump them to `long`. Ref: afa6b865604019ab27ec033294edfe3ded9ae0c0 #1257 Closes #1264 - build: enable missing OpenSSF-recommended warnings, with fixes Ref: https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html (2023-11-29) Enable new warnings: - replace `-Wno-sign-conversion` with `-Wsign-conversion`. Fix them in example, tests and wincng. There remain about 360 of these warnings in `src`. Add a TODO item for those and disable `-Werror` for this particular warning. - enable `-Wformat=2` for clang (in both cmake and autotools). - enable `__attribute__((format))` for `_libssh2_debug()`, `_libssh2_snprintf()` and in tests for `run_command()`. `LIBSSH2_PRINTF()` copied from `CURL_TEMP_PRINTF()` in curl. - enable `-Wimplicit-fallthrough`. - enable `-Wtrampolines`. Fix them: - src: replace obsolete fall-through-comments with `__attribute__((fallthrough))`. - wincng: fix `-Wsign-conversion` warnings. - tests: fix `-Wsign-conversion` warnings. - example: fix `-Wsign-conversion` warnings. - src: fix `-Wformat` issues in trace calls. Also, where necessary fix `int` and `unsigned char` casts to `unsigned int` and adjust printf format strings. These were not causing compiler warnings. Cast large types to `long` to avoid dealing with printf masks for `size_t` and other C99 types. Existing code often used `int` for this. I'll update them to `long` in an upcoming commit. - tests: fix `-Wformat` warning. - silence `-Wformat-nonliteral` warnings. - mbedtls: silence `-Wsign-conversion`/`-Warith-conversion` in external header. Closes #1257 - packet: whitespace fix Tested via #1257 - tidy-up: unsigned -> unsigned int In the `interval` argument of public `libssh2_keepalive_config()`. Tested via #1257 - tests: sync port number type with the rest of codebase Tested via #1257 - autotools: enable `-Wunused-macros` with gcc It works with gcc without the libtool warnings seen with clang on Windows in 96682bd5e14c20828e18bf10ed5b4b5c7543924a #1227. Sync usage of of this macro with CMake and autotools + clang + non-Windows. Making it enabled everywhere except autotools + clang + Windows due to the libtool stub issue. Follow-up to 7ecc309cd10454c54814b478c4f85d0041da6721 #1224 Closes #1262 - TODO: disable or drop weak algos [ci skip] Closes #1261 - example, tests: fix/silence `-Wformat-truncation=2` gcc warnings Then sync this warning option with curl. Seems like a false positive and/or couldn't figure how to fix it, so silence: ``` example/ssh2.c:227:38: error: '%s' directive output may be truncated writing likely 1 or more bytes into a region of size 0 [-Werror=format-truncation=] 227 | snprintf(fn1, fn1sz, "%s/%s", h, pubkey); | ^~ example/ssh2.c:227:34: note: assuming directive output of 1 byte 227 | snprintf(fn1, fn1sz, "%s/%s", h, pubkey); | ^~~~~~~ example/ssh2.c:227:13: note: 'snprintf' output 3 or more bytes (assuming 4) into a destination of size 2 227 | snprintf(fn1, fn1sz, "%s/%s", h, pubkey); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ example/ssh2.c:228:38: error: '%s' directive output may be truncated writing likely 1 or more bytes into a region of size 0 [-Werror=format-truncation=] 228 | snprintf(fn2, fn2sz, "%s/%s", h, privkey); | ^~ example/ssh2.c:228:34: note: assuming directive output of 1 byte 228 | snprintf(fn2, fn2sz, "%s/%s", h, privkey); | ^~~~~~~ example/ssh2.c:228:13: note: 'snprintf' output 3 or more bytes (assuming 4) into a destination of size 2 228 | snprintf(fn2, fn2sz, "%s/%s", h, privkey); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7055480458/job/19205970397#step:10:98 Fix: ``` tests/openssh_fixture.c:116:38: error: ' 2>&1' directive output may be truncated writing 5 bytes into a region of size between 1 and 1024 [-Werror=format-truncation=] tests/openssh_fixture.c:116:11: note: 'snprintf' output between 6 and 1029 bytes into a destination of size 1024 ``` Ref: https://github.com/libssh2/libssh2/actions/runs/7055480458/job/19205969221#step:10:51 Tested via #1257 - example: fix indentation follow-up Fix long line and fix more indentations. Follow-up to 9e896e1b80911a53d6aabb322e034e6ca51b6898 - example: fix indentation Tested via #1257 - autotools: fix missed `-pedantic` and `-Wall` options for gcc Follow-up to 5996fefe2bad80cfba85b2569ce6ab6ef575142c #1223 Tested via #1257 - ci: show compiler in cross/cygwin job names Tested via #1257 - mbedtls: further improve disabling `-Wredundant-decls` Move warning option suppression to `src/mbedtls.h` to surround the actual external header #includes that need it. Follow-up to ecec68a2c13a9c63fe8c2dc457ae785a513e157c #1226 Follow-up to 7ecc309cd10454c54814b478c4f85d0041da6721 #1224 Tested via #1257 GitHub (1 Dec 2023) - [ren mingshuai brought this change] example: replace remaining libssh2_scp_recv with libssh2_scp_recv2 in output messages (#1258) libssh2_scp_recv is deprecated and has been replaced by libssh2_scp_recv2 in prior commit. Follow-up to 6c84a426beb494980579e5c1d244ea54d3fc1a3f Viktor Szakats (27 Nov 2023) - openssl: use OpenSSL 3 HMAC API, add `no-deprecated` CI job - use OpenSSL 3 API when available for HMAC. This fixes building with OpenSSL 3 `no-deprecated` builds. - ensure we support pure OpenSSL 3 API by adding a CI job using OpenSSL 3 custom-built with `no-deprecated`. Follow-up to b0ab005fe79260e6e9fe08f8d73b58dd4856943d #1207 Fixes #1235 Closes #1243 - ci: restore lost comment for FreeBSD [ci skip] Follow-up to eee4e8055ab375c9f9061d4feb39086737f41a9c - ci: add OpenBSD (v7.4) job + fix build error in example - Use CMake, LibreSSL and clang from the base install. - This uncovered a build error in `example/subsystem_netconf.c`, caused by using the `%n` printf mask. This is a security risk and some systems (notably OpenBSD) disable this feature. Fix it by applying this patch from OpenBSD ports (from 2021-09-11): https://cvsweb.openbsd.org/ports/security/libssh2/patches/patch-example_subsystem_netconf_c?rev=1.1&content-type=text/x-cvsweb-markup https://github.com/openbsd/ports/commit/2c5b2f3e94381914a3e8ade960ce8c997ca9d6d7 "The old code is also broken, as it passes a pointer to a variable of a different size (on LP64). There is no check for truncation, but buf[] is 1MB in size." Patch-by: naddy ``` /home/runner/work/libssh2/libssh2/example/subsystem_netconf.c:252:17: error: '%n' format specifier support is deactivated and will call abort(3) [-Werror] "]]>]]>\n%n", (int *)&len); ~^ /home/runner/work/libssh2/libssh2/example/subsystem_netconf.c:270:17: error: '%n' format specifier support is deactivated and will call abort(3) [-Werror] "]]>]]>\n%n", (int *)&len); ~^ 2 errors generated. ``` Ref: https://github.com/libssh2/libssh2/actions/runs/6991449778/job/19022024280#step:3:420 Also made tests with arm64, but it takes consistently almost 14m to finish the job, vs. 2-3m for the native amd64: https://github.com/libssh2/libssh2/actions/runs/6991648984/job/19022440525 https://github.com/libssh2/libssh2/actions/runs/6991551220/job/19022233651 Cherry-picked from #1250 Closes #1250 - ci: add NetBSD (v9.3) job Use CMake, OpenSSL (v1.1) and clang from the base install. Cherry-picked from #1250 - ci: update and speed up FreeBSD job - switch to an alternate GitHub action. This one seems (more) actively maintained, and runs faster: https://github.com/cross-platform-actions/action - use clang instead of gcc. clang is already present in the base install, saving install time and bandwidth. - stop installing `openssl-quictls` and use the OpenSSL (v1.1) from the base system. (I'm suspecting that quictls before this patch wasn't detected by the build.) https://wiki.freebsd.org/OpenSSL Cherry-picked from #1250 - stop using leading underscores in macro names Underscored macros are reserved for the compiler / standard lib / etc. Stop using them in user code. We used them as header guards in `src` and in `__FILESIZE` in `example`. Closes #1248 - ci: use absolute path in `CMAKE_INSTALL_PREFIX` To make the installed locations unambiguous in the build logs. Closes #1247 - openssl: make a function static, add `#ifdef` comments Follow-up to 03092292597ac601c3f9f0c267ecb145dda75e4e #248 where the function was added. Also add comments to make `#ifdef` branches easier to follow in `openssl.h`. Closes #1246 - ci: boost mbedTLS build speed Build times down to 4 seconds (from 18-20). Closes #1245 - openssl: fix DSA code to use OpenSSL 3 API - fix missing `DSA` type when building for OpenSSL 3 `no-deprecated`. - fix fallouts after fixing the above by switching away from `DSA` with OpenSSL 3. Follow-up to b0ab005fe79260e6e9fe08f8d73b58dd4856943d #1207 Closes #1244 - openssl: formatting (delete empty lines) [ci skip] - tests: fall back to `$LOGNAME` for username If the `$USER` variable is empty, fall back to using `$LOGNAME` to retrieve the logged-in username. In POSIX, `$LOGNAME` is a mandatory variable, while `$USER` isn't, and on some systems it may not be set. Without this value, tests were unable to provide the correct username when logging into the SSH server running under the active user's session. Reported-by: Nicolas Mora Suggested-by: Nicolas Mora Ref: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1056348 Fixes #1240 Closes #1241 - libssh2.h: use `_WIN32` for Windows detection instead of rolling our own Sync up `libssh2.h` Windows detection with the libssh2 source code. `libssh2.h` was using `WIN32` and `LIBSSH2_WIN32` for Windows detection, next to the official `_WIN32`. After this patch it only uses `_WIN32` for this. Also, make it stop defining `LIBSSH2_WIN32`. There is a slight chance these break compatibility with Windows compilers that fail to define `_WIN32`. I'm not aware of any obsolete or modern compiler affected, but in case there is one, one possible solution is to define this macro manually. Closes #1238 - openssl: fix `EC_KEY` reference with OpenSSL 3 `no-deprecated` build Fixes: ``` src/openssl.c:650:5: error: use of undeclared identifier 'EC_KEY' EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); ^ src/openssl.c:650:13: error: use of undeclared identifier 'ec_key' EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); ^ src/openssl.c:650:22: error: implicit declaration of function 'EC_KEY_new_by_curve_name' is invalid in C99 [-Werror,-Wimplicit-function-declaration] EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve); ^ src/openssl.c:650:22: note: did you mean 'EC_GROUP_new_by_curve_name'? ./quictls/_a64-mac-sys/usr/include/openssl/ec.h:483:11: note: 'EC_GROUP_new_by_curve_name' declared here EC_GROUP *EC_GROUP_new_by_curve_name(int nid); ^ In file included from ./_a64-mac-sys-bld/src/CMakeFiles/libssh2_static.dir/Unity/unity_0_c.c:19: In file included from src/crypto.c:10: src/openssl.c:652:8: error: use of undeclared identifier 'ec_key' if(ec_key) { ^ ``` Ref: https://github.com/curl/curl-for-win/actions/runs/6950001225/job/18909297867#step:3:4341 Follow-up to b0ab005fe79260e6e9fe08f8d73b58dd4856943d #1207 Bug #1235 Closes #1236 - openssl: formatting Sync up these lines with the other two similar occurrences in the code. Cherry-picked from #1236 GitHub (21 Nov 2023) - [Michael Buckley brought this change] openssl: use non-deprecated APIs with OpenSSL 3.x (#1207) Assisted-by: Viktor Szakats Viktor Szakats (21 Nov 2023) - ci: add BoringSSL job (cmake, gcc, amd64) Closes #1233 - autotools: fix dotless gcc and Apple clang version detections - fix parsing dotless (major-only) gcc versions. Follow-up to 00a3b88c51cdb407fbbb347a2e38c5c7d89875ad #1187 - sync gcc detection variable names with curl. - fix Apple clang version detection for releases between 'Apple LLVM version 7.3.0' and 'Apple LLVM version 10.0.1' where the version was under-detected as 3.7 llvm/clang equivalent. - fix Apple clang version detection for 'Apple clang version 11.0.0' and newer where the Apple clang version was detected, instead of its llvm/clang equivalent. - revert to show `clang` instead of `Apple clang`, because we follow it with an llvm/clang version number. (Apple-ness still visible in raw version.) Used this collection for Apple clang / llvm/clang translation and test inputs: https://gist.github.com/yamaya/2924292 Closes #1232 - acinclude.m4: revert accidental edit [ci skip] Follow-up to 8c320a93a48775b74f40415e46f84bf68b4d5ae8 - autotools: show more clang/gcc version details Also: - show if we detected Apple clang. - delete duplicate version detection for clang. Closes #1230 - acinclude.m4: re-sync with curl [ci skip] - autotools: avoid warnings in libtool stub code Seen on Windows with clang64, in libtool-generated stub code for examples and tests. The error didn't break the CI job for some reason. msys2 (autotools, clang64, clang-x86_64: ``` [...] 2023-11-17T20:14:17.8639574Z ./.libs/lt-test_read.c:91:10: error: macro is not used [-Werror,-Wunused-macros] [...] 2023-11-17T20:14:39.8729255Z ./.libs/lt-sftp_write_nonblock.c:91:10: error: macro is not used [-Werror,-Wunused-macros] [...] ``` Ref: https://github.com/libssh2/libssh2/actions/runs/6908585056/job/18798193405?pr=1226#step:8:474 Follow-up to 7ecc309cd10454c54814b478c4f85d0041da6721 #1224 Closes #1227 - mbedtls: improve disabling `-Wredundant-decls` Disable these warnings specifically for the mbedTLS public headers and leave it on for the the rest of the code. This also fixes this issue for autotools. Previous solution was globally disabling this warning for the whole code when using mbedTLS and only with CMake. Follow-up to 7ecc309cd10454c54814b478c4f85d0041da6721 #1224 Closes #1226 - cmake: rename picky warnings script To match the camel-case style used in other CMake scripts and also to match the name used in curl. Closes #1225 - build: enable more compiler warnings and fix them Enable more picky compiler warnings. I've found these options in the nghttp3 project when implementing the CMake quick picky warning functionality for it. Fix issues found along the way: - wincng, mbedtls: delete duplicate function declarations. Most of this was due to re-#defining crypto functions to crypto-backend specific implementations These redefines also remapped the declarations in `crypto.h`, making the backend-specific declarations duplicates. This patch deletes the backend-specific declarations. - wincng mapped two crypto functions to the same local function. Also causing double declarations. Fix this by adding two disctinct wrappers and moving the common function to a static one. - delete unreachable `break;` statements. - kex: disable macros when unused. - agent: disable unused constants. - mbedtls: disable double declaration warnings because public mbedTLS headers trigger it. (with function `psa_set_key_domain_parameters`) - crypto.h: formatting. Ref: https://github.com/ngtcp2/nghttp3/blob/a70edb08e954d690e8fb2c1df999b5a056f8bf9f/cmake/PickyWarningsC.cmake Closes #1224 - autotools: sync warning enabler code with curl Tiny changes and minor updates to bring this code closer to curl's `m4/curl-compilers.m4`. Closes #1223 - acinclude.m4: fix indentation [ci skip] Also match indentation of curl's `m4/curl-compilers.m4` for easier syncing. - autotool: rename variable `WARN` -> `tmp_CFLAGS` To match curl and make syncing this code easier. Ref: https://github.com/curl/curl/blob/d1820768cce0e797d1f072343868ce1902170e93/m4/curl-compilers.m4#L479 Closes #1222 - autotools: picky warning options tidy-up - sync clang warning version limits with CMake. - make `WARN=` vs. `CURL_ADD_COMPILER_WARNINGS()` consistent with curl and between clang and gcc (`WARN=` is for `no-` options in general). Closes #1221 - build: picky warning updates - cmake, autotools: sync picky gcc warnings with curl. - cmake, autotools: add `-Wold-style-definition` for clang too. - cmake, autotools: add comment for `-Wformat-truncation=1`. - cmake: more precise version info for old clang options. Closes #1219 - ci: fixup FreeBSD version, bump mbedtls We haven't been using the FreeBSD version. Also it turns out, the single version supported is 13.2 at the moment: https://github.com/vmactions/freebsd-vm/tree/main/conf Stop trying to set the version and instead rely on the action providing the latest supported one automatically. Follow-up to a7d2a573be26238cc2b55e5ff6649bbe620cb8d9 Also: - add more details to the FreeBSD job description. - bump mbedtls version while here. Closes #1217 - cmake: fix multiple include of libssh2 package Also extend our integration test double inclusion. It will still not catch this case, because that requires `cmake_minimum_required(VERSION 3.18)` or higher. Fixes: ``` CMake Error at .../lib/cmake/libssh2/libssh2-config.cmake:8 (add_library): add_library cannot create ALIAS target "libssh2::libssh2" because another target with the same name already exists. Call Stack (most recent call first): CMakeLists.txt:24 (find_package) CMake Error at .../lib/cmake/libssh2/libssh2-config.cmake:13 (add_library): add_library cannot create ALIAS target "Libssh2::libssh2" because another target with the same name already exists. Call Stack (most recent call first): CMakeLists.txt:24 (find_package) ``` Test to reproduce: ```cmake cmake_minimum_required(VERSION 3.18) # must be 3.18 or higher project(test) find_package(libssh2 CONFIG) find_package(libssh2 CONFIG) # fails add_executable(test main.c) target_link_libraries(test libssh2::libssh2) ``` Ref: https://cmake.org/cmake/help/latest/release/3.18.html#other-changes Ref: https://cmake.org/cmake/help/v3.18/policy/CMP0107.html Assisted-by: Kai Pastor Assisted-by: Harry Mallon Ref: https://github.com/curl/curl/pull/11913 Closes #1216 - ci: add FreeBSD 13.2 job It runs over Linux via qemu. First two runs were (very) slow, then it became (much) more performant at just 2x slower than a native Linux build. Then got slow again, then fast again. Still seems acceptable for the value this adds. The build uses autotools and quictls. Successful builds: 1. https://github.com/libssh2/libssh2/actions/runs/6802676786/job/18496286419 (13m59s, -j3) 2. https://github.com/libssh2/libssh2/actions/runs/6802976375/job/18497243225 (11m5s, -j2) 3. https://github.com/libssh2/libssh2/actions/runs/6803142201/job/18497785049 (3m6s, -j1) 4. https://github.com/libssh2/libssh2/actions/runs/6803194839/job/18497962766 (3m10s, -j2) 5. https://github.com/libssh2/libssh2/actions/runs/6803267201/job/18498208501 (3m13s) 6. https://github.com/libssh2/libssh2/actions/runs/6803510333/job/18498993698 (15m25s) 7. https://github.com/libssh2/libssh2/actions/runs/6813602863/job/18528571057 (3m13s) Similar solution exists for Solaris (over macOS via VirtualBox), but it hangs forever at `Waiting for text: solaris console login`: https://github.com/libssh2/libssh2/actions/runs/6802388128/job/18495391869#step:4:185 Idea taken from LibreSSL. FIXME: Unrelated, the `distcheck` job became flaky in recent days: https://github.com/libssh2/libssh2/actions/runs/6802976375/job/18497256437#step:10:536 ``` FAIL: test_auth_pubkey_ok_rsa_aes256gcm ``` https://github.com/libssh2/libssh2/actions/runs/6813602863/job/18528588933#step:10:533 ``` FAIL: test_read ``` Closes #1215 - reuse: fix duplicate copyright warning ``` PendingDeprecationWarning: Copyright and licensing information for 'tests/openssh_server/Dockerfile' has been found in both 'tests/openssh_server/Dockerfile' and in the DEP5 file located at '.reuse/dep5'. The information for these two sources has been aggregated. In the future this behaviour will change, and you will need to explicitly enable aggregation. [...] ``` Ref: https://github.com/libssh2/libssh2/actions/runs/6789274955/job/18456085964#step:4:4 - Makefile.mk: delete Windows-focused raw GNU Make build We recommend using CMake instead. Especially in unity mode, it's faster and probably more familiar for most. It's also easily portable. (`Makefile.mk` was also portable, but in practice only usable for Windows. Other platforms required a manual config header.) Also: - migrate `LIBSSH2_NO_*` option CI tests to CMake. - make MSYS2 CMake builds verbose to show compilation options. Closes #1204 - tidy-up: around `stdint.h` - os400: delete unused `HAVE_STDINT_H`. - fuzz: delete redundant `stdint.h` use. `inttypes.h` is already included via `testinput.h`. - docs/TODO: adjust type in planned function. Closes #1212 - cmake: show crypto backend in feature summary This was visible as an enabled package before this patch, but it missed to show WinCNG. Closes #1211 - man: fix double spaces and dash escaping - `- ` -> `- ` - `. ` -> `. ` - `\- ` -> `- ` - `-1` -> `\-1` - fold long lines along the way This makes the minus sign come out as a Unicode minus sign (0x2212), and title separator dashes as Unicode hyphen (0x2010), with `groff -Tutf8` v1.23.0. Ref: https://lwn.net/Articles/947941/ Closes #1210 - src: fix gcc 13 `-Wconversion` warning on Darwin ``` src/session.c: In function 'libssh2_poll': src/session.c:1776:22: warning: conversion from 'long int' to '__darwin_suseconds_t' {aka 'int'} may change value [-Wconversion] 1776 | tv.tv_usec = (timeout_remaining % 1000) * 1000; | ^ ``` Ref: https://github.com/curl/curl-for-win/actions/runs/6711735060/job/18239768548#step:3:4368 Follow-up to 08354e0abbe86d4cc5088d210d53531be6d8981a Closes #1209 - openssl: silence `-Wunused-value` warnings Seen with gcc 12. Manual: https://www.openssl.org/docs/man3.1/man3/BIO_reset.html ``` ./quictls/linux-a64-musl/usr/include/openssl/bio.h:555:34: warning: value computed is not used [-Wunused-value] 555 | # define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ./libssh2/src/openssl.c:3518:5: note: in expansion of macro 'BIO_reset' ./libssh2/src/openssl.c:3884:5: note: in expansion of macro 'BIO_reset' ./libssh2/src/openssl.c:3995:5: note: in expansion of macro 'BIO_reset' ``` Ref: https://github.com/curl/curl-for-win/actions/runs/6696392318/job/18194032712#step:3:5060 Closes #1205 - Makefile.am: fix `cp` to preserve attributes and timestamp - cmake: simplify showing CMake version Move it to `CMakeLists.txt`. Drop `cmake --version` commands. Credit to the `zlib-ng` project for the idea: https://github.com/zlib-ng/zlib-ng/blob/61e181c8ae93dbf56040336179c9954078bd1399/CMakeLists.txt#L7 Closes #1203 - ci: mbedtls 3.5.0 v3.5.0 needs extra compiler option for i386 to avoid: ``` #error "Must use `-mpclmul -msse2 -maes` for MBEDTLS_AESNI_C" ``` Closes #1202 - tests: show cmake version used in integration tests Closes #1201 - readme.vms: fix typo [ci skip] Detected by codespell 2.2.6 - appveyor: YAML/PowerShell formatting, shorten variable name - use single-quotes in yaml and PowerShell. - shorten a variable name. - use indentation 2 for scripts. - use C else-style in PowerShell. Closes #1200 - ci: update actions, use shallow clones with appveyor - update GitHub Actions to their latest versions. - use shallow git clones in AppVeyor CI to save data over the wire. Closes #1199 - appveyor: move to pure PowerShell - replace batch commands with PowerShell. - merge separate command entries into single PowerShell blocks. Closes #1197 - windows: use built-in `_WIN32` macro to detect Windows Instead of `WIN32`. The compiler defines `_WIN32`. Windows SDK headers or build env defines `WIN32`, or we have to take care of it. The agreement seems to be that `_WIN32` is the preferred practice here. Minor downside is that CMake uses `WIN32` and we also adopted it in `Makefile.mk`. In public libssh2 headers we stick with accepting either `_WIN32` or `WIN32` and define our own namespaced `LIBSSH2_WIN32` based on them. grepping for `WIN32` remains useful to detect Windows-specific code. Closes #1195 - cmake: cleanup mbedTLS version detection more - lowercase, underscored local variables. - fix `find_library()` to use the multiple names passed. - rely more on `find_package_handle_standard_args()`. Logic based on our `Findwolfssl.cmake`. - delete ignored/unused `MBEDTLS_LIBRARY_DIR`. - revert CI configuration to use `MBEDCRTYPO_LIBRARY`. - clarify inputs/outputs in comment header. - use variable for regex. - formatting. Follow-up to 41594675072c578294674230d4cf5f47fa828778 #1192 Closes #1196 - cmake: delete duplicate `include()` - cmake: improve/fix mbedTLS detection - libssh2 needs the crypto lib only, stop dealing with the rest. - simplify logic. - drop hard-wired toolchain specific options that broke with e.g. MSVC. Reported by: AR Visions Fixes #1191 - add mbedTLS version detection for recent releases. - merge custom detection results display into a single line. - shorten mbedTLS configuration in macOS CI job. Used the curl mbedTLS detection logic for ideas: https://github.com/curl/curl/blob/a8c773845f4fdbfb09b08a6ec4b656c812568995/CMake/FindMbedTLS.cmake Closes #1192 GitHub (24 Sep 2023) - [concussious brought this change] libssh2_session_get_blocking.3: Add description (#1185) Viktor Szakats (21 Sep 2023) - autotools: fix selecting wincng in cross-builds (and more) - Fix explicitly selecting WinCNG in autotools cross-builds by moving `windows.h` header check before the WinCNG availability check. Follow-up to d43b8d9b0b9cd62668459fe5d582ed83aabf77e7 Reported-by: Jack L Fixes #1186 - Add Linux -> mingw-w64 cross-builds for autotools and CMake. This doesn't detect #1186, because that happened when explicitly specifying WinCNG via `--with-crypto=wincng`, but not when falling back to WinCNG by default. - autotools: fix to strip suffix from gcc version Before this patch we expected `n.n` `-dumpversion` output, but Ubuntu may return `n-win32` (also with `-dumpfullversion`). Causing these errors and failing to enable picky warnings: ``` ../configure: line 23845: test: : integer expression expected ``` Ref: https://github.com/libssh2/libssh2/actions/runs/6263453828/job/17007893718#step:5:143 Fix that by stripping any dash-suffix. gcc version detection is still half broken because we translate '10' to '10.10' because `cut -d. -f2` returns the first word if the delimiter missing. More possible `-dumpversion` output: `10-posix`, `10-win32`, `9.3-posix`, `9.3-win32`, `6`, `9.3.0`, `11`, `11.2`, `11.2.0` Ref: https://github.com/mamedev/mame/pull/9767 Closes #1187 GitHub (28 Aug 2023) - [Michael Buckley brought this change] Properly bounds check packet_authagent_open() (#1179) * Properly bounds check packet_authagent_open * packet.c: use strlen instead of sizeof for strings * Make LIBSSH_CHANNEL's channel_type_len a size_t * packet_authagent_open: use size_t for offset Credit: Michael Buckley, signed off by Will Cosgrove Viktor Szakats (28 Aug 2023) - os400qc3: move FIXME comment [ci skip] Follow-up to eb9f9de2c19ec67d12a444cce34bdd059fd26ddc - md5: allow disabling old-style encrypted private keys at build-time Before this patch, this happened at runtime when using an old (pre-3.0), FIPS-enabled OpenSSL backend. This patch makes it possible to disable this via the build-time option `LIBSSH2_NO_MD5_PEM`. Also: - make sure to exclude all MD5 internal APIs when both the above and `LIBSSH2_NO_MD5` are enabled. - fix tests to support build with`LIBSSH2_NO_MD5`, `LIBSSH2_NO_MD5_PEM` and `LIBSSH2_NO_3DES`. - add FIXME to apply this change to `os400qc3.*`. Old-style encrypted private keys require MD5 and they look like this: ``` -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC, -----END RSA PRIVATE KEY----- ``` E.g.: `tests/key_rsa_encrypted` Ref: https://github.com/libssh2/www/issues/20 Closes #1181 - cmake: tidy-up `foreach()` syntax Use `IN LISTS` and `IN ITEMS`. This appears to be the preferred way within CMake's own source code and possibly improves readability. Fixup a side-effect of `IN LISTS`, where it retains empty values at the end of the list, as opposed to the syntax used before, which dropped it. In our case this happened with lines read from a text file via `file(READ)`. https://cmake.org/cmake/help/v3.7/command/foreach.html Closes #1180 - ci: replace `mv` + `chmod` with `install` in `Dockerfile` Cherry-picked from #1175 Closes #1175 - ci: set file mode early in `appveyor_docker.yml` Also: - replace tab with spaces in generated config file - formatting Cherry-picked from #1175 - ci: add spellcheck (codespell) Also rename a variable in `src/os400qc3.c` to avoid a false positive. Cherry-picked from #1175 - cmake: also test for `libssh2_VERSION` Cherry-picked from #1175 - cmake: show cmake versions in ci Cherry-picked from #1175 - tests: formatting and tidy-ups - Dockerfile: use standard sep with `sed` - Dockerfile: use single quotes in shell command - appveyor.yml: use long-form option with `choco` - tests/cmake: add language to test project - reuse.yml: fix indentation ``` $ yamllint reuse.yml reuse.yml [...] 11:5 error wrong indentation: expected 6 but found 4 (indentation) 15:5 error wrong indentation: expected 6 but found 4 (indentation) [...] 27:5 error wrong indentation: expected 6 but found 4 (indentation) ``` Cherry-picked from #1175 - openssl.c: whitespace fixes Cherry-picked from #1175 - checksrc: fix spelling in comment [ci skip] - cmake: quote more strings Follow-up to 3fa5282d6284efba62dc591697e6a687152bdcb1 Closes #1173 - drop `www.` from `www.libssh2.org` is now a 301 permanent redirect to . Update all references to point directly to the new destination. Ref: https://github.com/libssh2/www/commit/ccf4a7de7f702a8ee17e2c697bcbef47fcf485ed Closes #1172 - cmake: add `ExternalProject` integration test - via `ExternalProject_Add()`: https://cmake.org/cmake/help/latest/module/ExternalProject.html (as documented in `docs/INSTALL_CMAKE.md`) - also make `FetchContent` fetch from local repo instead of live master. Closes #1171 - cmake: add integration tests Add a small project to test dependent/downstream CMake build using libssh2. Also added to the GHA CI, and you can also run it locally with `tests/cmake/test.sh`. Test three methods of integrating libssh2 into a project: - via `find_package()`: https://cmake.org/cmake/help/latest/command/find_package.html - via `add_subdirectory()`: https://cmake.org/cmake/help/latest/command/add_subdirectory.html - via `FetchContent`: https://cmake.org/cmake/help/latest/module/FetchContent.html Closes #1170 - cmake: (re-)add aliases for `add_subdirectory()` builds Add internal libssh2 library aliases to make these available for downstream/dependent projects building libssh2 via `add_subdirectory()`: - `libssh2:libssh2_static` - `libssh2:libssh2_shared` - `libssh2:libssh2` (shared, or static when not building shared) - `libssh2` (shared, or static when not building shared) Of these, `libssh2` was present in v1.10.0 and earlier releases, but missing from v1.11.0. Closes #1169 - cmake: delete empty line [ci skip] Follow-up to 3fa5282d6284efba62dc591697e6a687152bdcb1 - cmake: reflect minimum version in docs [ci skip] Follow-up to 9cd18f4578baa41dfca197f60557063cad12cd59 - cmake: style tidy up - quote text literals to improve readability. (exceptions: `FILES` items, `add_subdirectory` names, `find_package` names, literal target names, version numbers, 0/1, built-in CMake values and CMake keywords, list items in `cmake/max_warnings.cmake`) - quote standalone variables that could break syntax on empty values. - replace `libssh2_SOURCE_DIR` with `PROJECT_SOURCE_DIR`. - add missing mode to `message()` call. - `TRUE`/`FALSE` → `ON`/`OFF`. - add missing default value `OFF` to `option()` for clarity. - unfold some lines. - `INSTALL_CMAKE.md` fixes and updates. Show defaults. Closes #1166 - wincng: prefer `ULONG`/`DWORD` over `unsigned long` To match with the types used by the `Crypt*()` (uses `DWORD`) and `BCrypt*()` (uses `ULONG`) Windows APIs. This patch doesn't change data width or signedness. Closes #1165 - wincng: tidy-ups - make `_libssh2_wincng_key_sha_verify` static. - prefer `unsigned long` over `size_t` in two static functions. - prefer `ULONG` over `DWORD` to match `BCryptImportKeyPair()` and `BCryptGenerateKeyPair()`. - add a newline. Closes #1164 - ci: add MSYS builds (autotools and cmake) Use existing MSYS2 section and extend it with builds for the MSYS environment with both autotools and cmake. MSYS builds resemble Cygwin ones: The env is Unixy, where Windows headers are all available but we don't use them. Also: - extend existing autotools logic for Cygwin to skip detecting `windows.h` for MSYS targets too. - require `windows.h` for the WinCNG backend in autotools. Before this patch, autotools allowed selecting WinCNG on the Cygwin and MSYS platforms, but the builds then fell apart due to the resulting mixed Unixy + Windowsy environment. The general expectation for Cygwin/MSYS builds is not to use the Windows API directly in them. - stop manually selecting the `MSYS Makefiles` CMake generator for MSYS2-based GHA CI builds. mingw-w64 builds work fine without it, but it broke MSYS build which use `Unix Makefiles`. Deleting this setting fixes all build flavours. Closes #1162 - ci: cygwin job tidy-ups `CMAKE_C_COMPILER=gcc` not necessary, delete it. Follow-up to f1e96e733fefb495bc31b07f5c2a5845ff877c9c Cherry-picked from #1163 Closes #1163 - ci: add Cygwin builds (autotools and cmake) To avoid builds picking up non-Cygwin components coming by default with the CI machine, I used the solution recommended by Cygwin [1] and set `PATH` manually. To avoid repeating this for each step, I merged steps into a single one. Let us know if there is a more elegant way. Cygwin's Github Action uses cleartext HTTP. We upgrade this to HTTPS. autotools build seemed to take slightly longer than other jobs. To save turnaround time I disabled building tests. Cygwin package search: https://cygwin.com/cgi-bin2/package-grep.cgi [1] https://github.com/cygwin/cygwin-install-action/tree/v4#path Closes #1161 - cmake: add `LIB_NAME` variable It holds the name `libssh2`. Mainly to document its uses, and also syncing up with the same variable in libcurl. Closes #1159 - cmake: add one missed `PROJECT_NAME` variable Follow-up to 72fd25958a7dc6f8e68f2b2d5d72839a2da98f9c Closes #1158 - cmake: tidy-up concatenation in `CMAKE_MODULE_PATH` Former solution was appending an empty element to the array if `CMAKE_MODULE_PATH` was originally empty. The new syntax doesn't have this side-effect. There is no known issue caused by this. Fixing it for good measure. Closes #1157 - ci: add mingw-w64 UWP build Add a CI test for Windows UWP builds using mingw-w64. Before this patch we had UWP builds tested with MSVC only. Alike existing UWP jobs, it's not possible to run the binaries due to the missing UWP runtime DLL: https://github.com/libssh2/libssh2/actions/runs/5821297010/job/15783475118#step:11:42 We could install `winstorecompat-git` in the setup-msys2 step, but opted to do it manually to avoid the overhead for every matrix job. All this would work smoother with llvm-mingw, which features an UWP toolchain prefix and provides all necessary implibs by default. This also hit a CMake bug (with v3.26.4), where CMake gets confused and sets up `windres.exe` to use the MSVC rc.exe-style command-line: https://github.com/libssh2/libssh2/actions/runs/5819232677/job/15777236773#step:9:126 Notice that MS "sunset" UWP in 2021: https://github.com/microsoft/WindowsAppSDK/discussions/1615 If this particular CI job turns out to be not worth the maintenance burden or CPU time, or too much of a hack, feel free to delete it. Ref: https://github.com/libssh2/libssh2/pull/1147#issuecomment-1670850890 Closes #1155 - cmake: replace `libssh2` literals with `PROJECT_NAME` variable Where applicable. This also makes it more obvious which `libssh2` uses were referring to the project itself. Closes #1152 - cmake: fix `STREQUAL` check in error branch This caused a CMake error instead of our custom error when manually selecting the `WinCNG` crypto-backend for a non-Windows target. Also cleanup `STREQUAL` checks to use variable name without `${}` on the left side and quoted string literals on the right. Closes #1151 - misc: flatten `_libssh2_explicit_zero` if tree Closes #1149 - src: drop a redundant `#include` We include `misc.h` via `libssh2_priv.h` already. Closes #1153 - openssl: use automatic initialization with LibreSSL 2.7.0+ Stop calling `OpenSSL_add_all_*()` for LibreSSL 2.7.0 and later. LibreSSL 2.7.0 (2018-03-21) introduced automatic initialization and deprecated these functions. Stop calling these functions manually for LibreSSL version that no longer need them. Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.7.0-relnotes.txt Ref: https://github.com/libressl/openbsd/commit/46f29f11977800547519ee65e2d1850f2483720b Ref: https://github.com/libssh2/libssh2/issues/302 Also stop calling `ENGINE_*()` functions when initialization is automatic with LibreSSL 2.7.0+ and OpenSSL 1.1.0+. Engines are also initializated automatically with these. Closes #1146 - gha: restore curly braces in `if` Without curly braces it was less obvious which string is a GHA expression. Also fix an `if` expression that always missed its curly braces. Reverts cab3db588769d6deed97ba89ca9221fd7503405e Closes #1145 - ci: bump mbedtls - [renmingshuai brought this change] Add a new structure to separate memory read and file read. We use different APIs when we read one private key from memory, so it is improper to store the private key information in the structure that stores the private key file information. Fixes https://github.com/libssh2/libssh2/issues/773 Reported-by: mike-jumper - tests: replace FIXME with comments `key_dsa_wrong` is the same kind of (valid) key as `key_dsa`, both with an empty passphrase. Named "wrong" because it's intentionally not added to our `openssh_server/authorized_keys` file. - tidy-up: delete duplicate word from comment - cmake: cache more config values on Windows Set two cases of non-detection to save the time dynamically detecting these on each build init. Affects old MSVC versions. Before: https://ci.appveyor.com/project/libssh2org/libssh2/builds/47668870/job/i17e0e9yx8rgpv4i After: https://ci.appveyor.com/project/libssh2org/libssh2/builds/47674950/job/ysa1jq0pxtyhui3f Closes #1142 - revert: build: respect autotools `DLL_EXPORT` in `libssh2.h` Revert fb1195cf88268a11e2709b9912ab9dca8c23739c #917 On a second look this change did not improve anything with autotools builds. autotools seems to handle the dll export matter without it. This patch also broke (e.g.) curl-for-win autotools builds, where the curl build defines `DLL_EXPORT` while building libcurl DLL. `libssh2.h` picks it up, resulting in unresolved symbols while trying to link a static libssh2 on Windows. The best fix seems to be to revert this, instead of adding extra tweaks to dependents. Fixes: https://ci.appveyor.com/project/curlorg/curl-for-win/builds/47667412#L11035 ``` ld.lld-15: error: undefined symbol: __declspec(dllimport) libssh2_session_block_directions >>> referenced by vssh/.libs/libcurl_la-libssh2.o:(ssh_do) >>> referenced by vssh/.libs/libcurl_la-libssh2.o:(ssh_connect) >>> referenced by vssh/.libs/libcurl_la-libssh2.o:(ssh_multi_statemach) >>> referenced 8 more times ld.lld-15: error: undefined symbol: __declspec(dllimport) libssh2_session_init_ex >>> referenced by vssh/.libs/libcurl_la-libssh2.o:(ssh_connect) ld.lld-15: error: undefined symbol: __declspec(dllimport) libssh2_session_set_read_timeout [...] ``` Closes #1141 - gha: simplify `if` strings Closes #1140 - test_read: make it run without Docker Apply an existing fix to `test_read`, so that it falls back to use the current username instead of the hardcoded `libssh2` when run outside Docker. This allows to run algo tests with this command: ```shell cd tests ./test_sshd.test ./test_read_algos.test ``` Closes #1139 - cmake: streamline invocation Stop specifiying the current directory. Simplify build instructions. Closes #1138 - NMakefile: delete This make file was for long time unmaintained (last updated in 2014). Despite best efforts to keep it working in the recent round of major overhauls, it appears to be broken now. There is also no way to test it without an actual MSVC env and it's also missing from our CI. Based on our Issue tracker, it's also not widely used. Since its addition in 2005, libssh2 got support for CMake in 2014. CMake should be able to generate NMake makefiles with the option `-G "NMake Makefiles"`. (I haven't tested this.) Ref: https://github.com/libssh2/libssh2/discussions/1129 Closes #1134 - tests: add aes256-gcm encrypted key test Follow-up to #1133 Also update `tests/gen_keys.sh` to set `aes256-ctr` encryption method for `key_ed25519_encrypted' explicitly. Closes #1135 GitHub (26 Jul 2023) - [Jakob Egger brought this change] Fix private keys encrypted with aes-gcm methods (#1133) libssh2 1.11.0 fails to decrypt private keys encrypted with aes128-gcm@openssh.com and aes256-gcm@openssh.com ciphers. To reproduce the issue, you can create a test key with a command like the following: ```bash ssh-keygen -Z aes256-gcm@openssh.com -f id_aes256-gcm ``` If you attempt to use this key for authentication, libssh2 returns the not-so-helpful error message "Wrong passphrase or invalid/unrecognized private key file format". The problem is that OpenSSH encrypts keys differently than packets. It does not include the length as AAD, and the 16 byte authentication tag is appended after the encrypted key. The length of the authentication tag is not included in the encrypted key length. I have not found any documentation for this behaviour -- I discovered it by looking at the OpenSSH source. See the `private2_decrypt` function in . This patch fixes the code for reading OpenSSH private keys encrypted with AES-GCM methods. Viktor Szakats (26 Jul 2023) - ci: add missing timeout to 'autotools distcheck' step - cmake: merge `set_target_properties()` calls Also rename variable `LIBSSH2_VERSION` to `LIBSSH2_LIBVERSION` in context of lib versioning to avoid collision with another use. Closes #1132 - cmake: formatting [ci skip] - cmake: (re-)add zlib to `Libs.private` in `libssh2.pc` We mistakently added transitive zlib to `Requires.private` before, then removed it. This patch re-adds zlib, but this time to `Libs.private`, which is listing raw libs and should include transitive libs as well. Also add zlib when used as a direct dependency when zlib compression support is enabled. Follow-up to ef538069a661a43134fe7b848b1fe66b2b43bdac Closes #1131 - cmake: formatting [ci skip] - cmake: use `wolfssl/options.h` for detection, like autotools Closes #1130 - build: stop requiring libssl from openssl libssh2 does not use or need the TLS/SSL library of OpenSSL. It only needs libcrypto. Closes #1128 - cmake: add openssl libs to `Libs.private` in `libssh2.pc` Also to sync up with autotools-generated `libssh2.pc`, that already added them. Closes #1127 - Makefile.mk: stop linking unused mbedtls libs Stop linking libmbedtls and libmbedx509 (similarly to autotools). Only libmbedcrypto is necessary for libssh2. - cmake: bump minimum CMake version to v3.7.0 Fixes the warning below, which appeared in CMake v3.27.0: ``` CMake Deprecation Warning at CMakeLists.txt:39 (cmake_minimum_required): Compatibility with CMake < 3.5 will be removed from a future version of CMake. Update the VERSION argument value or use a ... suffix to tell CMake that the project does not need compatibility with older versions. ``` Bump straight up to v3.7.0 to sync up with the curl project: https://github.com/curl/curl/blob/2900c29218d2d24ab519853589da84caa850e8c7/CMakeLists.txt#L64 CMake release dates: v3.7.0 2016-11-11 v3.5.0 2016-03-08 v3.1.0 2014-12-17 Closes #1126 - build: tidy-up `libssh2.pc.in` variable names - prefix with `LIBSSH2_PC_` - match with the names of `pkg-config` values. - use the same names in autotools and CMake scripts. - use `LIBSSH2_VERSION` for the version number in autotools scripts, to match the name used in CMake. Closes #1125 - libssh2.pc: re-add & extend support for static-only libssh2 builds Adapted for libssh2 from the curl commit message by James Le Cuirot: "A project built entirely statically will call `pkg-config` with `--static`, which utilises the `Libs.private:` field. Conversely it will not use `--static` when not being built entirely statically, even if there is only a static build of libssh2 available. This will most likely cause the build to fail due to underlinking unless we merge the `Libs:` fields. Consider that this is what the Meson build system does when it generates `pkg-config` files." This patch extends the above to `Requires:`, to mirror `Libs:` with `pkg-config` package names. Follow-up to 1209c16d93cba3c5e0f68c12fa4a5049f49c00d8 #1114 Ref: https://github.com/libssh2/libssh2/pull/1114#issuecomment-1634334809 Ref: https://github.com/curl/curl/commit/98e5904165859679cd78825bcccb52306ee3bb66 Ref: https://github.com/curl/curl/pull/5373 Closes #1119 GitHub (14 Jul 2023) - [Nursan Valeyev brought this change] cmake: CMAKE_SOURCE_DIR -> PROJECT_SOURCE_DIR (#1121) Fixes compiling as dependency with FetchContent Co-authored-by: Viktor Szakats Viktor Szakats (14 Jul 2023) - autotools: use comma separator in `Requires.private` of `libssh2.pc` In `Requires*:`, the documented name separator is comma. We already used it in the CMake-generated `libssh2.pc`. Adjust the autotools-generated one to use it too, instead of spaces. Ref: https://linux.die.net/man/1/pkg-config Ref: https://gitlab.freedesktop.org/pkg-config/pkg-config/-/blob/d97db4fae4c1cd099b506970b285dc2afd818ea2/pkg-config.1 Closes #1124 - build: add/fix `Requires.private` packages in `libssh2.pc` - autotools was using `libwolfssl`. CMake left it empty. wolfSSL provides `wolfssl.pc`. This patch sets `Requires.private: wolfssl` with both build tools. - add `libgcrypt` to `Requires.private` with both autotools and CMake. Ref: https://github.com/gpg/libgcrypt/blob/e76e88eef7811ada4c6e1d57520ba8c439139782/src/libgcrypt.pc.in Present since 2005-04-22: https://github.com/gpg/libgcrypt/commit/32bf3f13e8b45497322177645bebf0b5d0c9cb8e Released in v1.3.0 2007-05-04: https://github.com/gpg/libgcrypt/releases/tag/libgcrypt-1.3.0 - also stop adding transitive `zlib` deps to `Requires.private`. The referenced crypto package is adding it as nedded. This makes deduplication of the list redundant, so stop doing it. Follow-up to 2fc367900701e6149efc42bd674c4b69127756dd (`libssh2.pc` not tested as a project dependency.) Closes #1123 - cmake: tidy-ups - dedupe `Requires.private` in `libssh2.pc`. `zlib` could appear on the list twice: ``` Requires.private: libssl,libcrypto,zlib,zlib ``` According to CMake docs `list(REMOVE_DUPLICATES ...)`, is supported by our minimum required CMake version (and by earlier ones even): https://cmake.org/cmake/help/v3.1/command/list.html#remove-duplicates - move `cmake_minimum_required()` to the top. - move `set(CMAKE_MODULE_PATH)` to the top. - delete duplicate `set(CMAKE_MODULE_PATH)`. - replace `CMAKE_CURRENT_SOURCE_DIR` with `PROJECT_SOURCE_DIR` in root `CMakeLists.txt` for robustness. - replace `gcovr` option with long-form for readability/consistency. - rename `GCOV_OPTIONS` to `GCOV_CFLAGS`. These are C options we enable when using gcov, not gcov tooling options. Closes #1122 - openssl: add missing check for `LIBRESSL_VERSION_NUMBER` before use Fixes: ``` openssl.h:101:5: warning: "LIBRESSL_VERSION_NUMBER" is not defined [-Wundef] LIBRESSL_VERSION_NUMBER >= 0x3050000fL ^ ``` Ref: https://github.com/libssh2/libssh2/issues/1115#issuecomment-1631845640 Closes #1117 - [Harmen Stoppels brought this change] Don't put `@LIBS@` in pc file - misc: delete redundant NULL check and assignment Follow-up to 724effcb47ebb713d3ef1776684b8f6407b4b6a5 #1109 Ref: https://github.com/libssh2/libssh2/pull/1109#discussion_r1246613274 Closes #1111 - [renmingshuai brought this change] We should check whether *key_method is a NULL pointer instead of key_method Signed-off-by: renmingshuai GitHub (30 Jun 2023) - [ren mingshuai brought this change] Add NULL pointer check for outlen before use (#1109) Before assigning a value to the outlen, we need to check whether it is NULL. Credit: Ren Mingshuai Viktor Szakats (25 Jun 2023) - cmake: re-add `Libssh2:libssh2` for compatibiliy + lowercase namespace - add `libssh2:libssh2` target that selects the shared lib if built, otherwise the static one. - re-add `Libssh2:libssh2` target for compatibility with v1.10.0 and earlier. This is an alias for `libssh2:libssh2`. - keep `libssh2:libssh2_shared` and `libssh2_libssh2_static` targets. - allow using `find_package(libssh2)` in dependents as an alternative to `find_package(Libssh2)`. Co-authored-by: Radek Brich Suggested-by: Haowei Hsu Fixes #1103 Fixes #731 Closes #1104 - example: fix regression in `ssh2_exec.c` Regression from b13936bd6a89993cd3bf4a18317ca5bd84bb08d7 #861 #846. Update a variable name missed above. Reported-by: PewPewPew Fixes #1105 Closes #1106 - docs: replace SHA1 with SHA256 in CMake example - checksrc: modernise perl file open Use regular variables and separate file open modes from filenames. Suggested by perlcritic Copied from https://github.com/curl/curl/commit/7f669aa0f1d40ef5d64543981f22bdc5af1272f5 Copied from https://github.com/curl/trurl/commit/f2784a9240f47ee28a845 - reuse: comply with 3.1 spec and 2.0.0 checker The checker tool was upgraded upstream to 2.0.0 and the REUSE Specification to version 3.1 (from 3.0), causing these new errors: ``` reuse.project - WARNING - Copyright and licensing information for 'docs/INSTALL_AUTOTOOLS' have been found in 'docs/INSTALL_AUTOTOOLS' and the DEP5 file located at '.reuse/dep5'. The information in the DEP5 file has been overridden. Please ensure that this is correct. reuse.project - WARNING - Copyright and licensing information for 'tests/openssh_server/Dockerfile' have been found in 'tests/openssh_server/Dockerfile' and the DEP5 file located at '.reuse/dep5'. The information in the DEP5 file has been overridden. Please ensure that this is correct. The following files have no licensing information: * docs/INSTALL_AUTOTOOLS * tests/openssh_server/Dockerfile ``` Via: https://github.com/libssh2/libssh2/actions/runs/5333572682/jobs/9664211341?pr=1098#step:4:4 Ref: https://github.com/fsfe/reuse-tool/releases/tag/v2.0.0 Ref: https://git.fsfe.org/reuse/docs/src/branch/stable/CHANGELOG.md#3-1-2023-06-21 Original discovery: https://github.com/libssh2/libssh2/pull/1098#issuecomment-1600719575 Fixes #1101 Closes #1102 - tests: trap signals in scripts Closes #1098 - test_sshd.test: fixup to distcheck failure Fixes: ``` ERROR: test_sshd.test - missing test plan ERROR: test_sshd.test - exited with status 1 ``` Ref: https://github.com/libssh2/libssh2/actions/runs/5322354271/jobs/9638694218#step:10:532 Caused by trying to create the log file in a read-only directory. Follow-up to 299c2040625830d06ad757d687807a166b57d6de Closes #1099 GitHub (21 Jun 2023) - [Viktor Szakats brought this change] test_sshd.test: show sshd and test connect logs on harness failure (#1097) - [Joel Depooter brought this change] Fix incorrect byte offset in debug message (#1096) Fixes debug log message Credit: Joel Depooter Viktor Szakats (16 Jun 2023) - tidy-up: delete whitespace at EOL [ci skip] - mbedtls: include `version.h` for `MBEDTLS_VERSION_NUMBER` Older (2021 or earlier?) mbedTLS releases require this. Reported-by: rahmanih on Github Fixes #1094 Closes #1095 - hostkey: do not advertise ssh-rsa when SHA1 is disabled Before this patch OpenSSL, mbedTLS, WinCNG and OS/400 advertised both SHA2 and SHA1 host key algos, even when SHA1 was not supported by the crypto backend or when forcefully disabled via `LIBSSH2_NO_RSA_SHA1`. Reported-by: João M. S. Silva Fixes #1092 Closes #1093 - openssl.h: whitespace tidy-up [ci skip] GitHub (14 Jun 2023) - [Dan Fandrich brought this change] test_sshd.test: set a safe PID directory (#1089) The compiled in default to sshd can be a non-writable location since it expects to be run as root. Viktor Szakats (13 Jun 2023) - mingw: fix printf mask for 64-bit integers Before 02f2700a61157ce5a264319bdb80754c92a40a24 #846 #876, we used `%I64d'. That patch changed this to `%lld`. This patch uses `PRId64` (defined in `inttypes.h`). Fixes #1090 Closes #1091 - test_sshd.test: minor cleanups Daniel Stenberg (7 Jun 2023) - provide SPDX identifiers - All files have prominent copyright and SPDX identifier - If not embedded in the file, in the .reuse/dep5 file - All used licenses are in LICENSES/ (not shipped in tarballs) - A new REUSE CI job verify that all files are OK Assisted-by: Viktor Szakats Closes #1084 Viktor Szakats (6 Jun 2023) - src: improve MSVC C4701 warning fix Simplify the code to avoid this warning. This might also help avoiding it with other compilers (e.g. gcc?). Improves 02f2700a61157ce5a264319bdb80754c92a40a24 #876 Might fix #1083 Closes #1086 Daniel Stenberg (5 Jun 2023) - configure.ac: remove AB_INIT Not used. Remove m4/autobuild.m4 as well Viktor Szakats (4 Jun 2023) - copyright: remove years from copyright headers Also: - uppercase `(C)`. - add missing 'All rights reserved.' lines. - drop duplicate 'Author' lines. - add copyright headers where missing. - enable copyright header check in checksrc. Reasons for deleting years (copied as-is from curl): - they are mostly pointless in all major jurisdictions - many big corporations and projects already don't use them - saves us from pointless churn - git keeps history for us - the year range is kept in COPYING Closes #1082 - tests: cast to avoid `-Wchar-subscripts` with Cygwin ``` In file included from $HOME/src/cygwin/libssh2/libssh2-1.11.0-1.x86_64/src/libssh2-1.11.0/tests/openssh_fixture.c:57: $HOME/src/cygwin/libssh2/libssh2-1.11.0-1.x86_64/src/libssh2-1.11.0/tests/openssh_fixture.c: In function 'run_command_varg': $HOME/src/cygwin/libssh2/libssh2-1.11.0-1.x86_64/src/libssh2-1.11.0/tests/openssh_fixture.c:136:37: warning: array subscript has type 'char' [-Wchar-subscripts] 136 | while(end > 0 && isspace(buf[end - 1])) { | ~~~^~~~~~~~~ ``` Ref: https://github.com/libssh2/libssh2/files/11644340/cygwin-x86_64-libssh2-1.11.0-1-check.log Reported-by: Brian Inglis Fixes #1080 Closes #1081 - tidy-up: avoid exclamations, prefer single quotes, in outputs Closes #1079 - autotools: improve libz position We repositioned crypto libs in 4f0f4bff5a92dce6a6cd7a5600a8ee5660402c3f via #941 and subsequently in d4f58f03438e326b8696edd31acadd6f3e028763 from d93ccf4901ef26443707d341553994715414e207 via #1013. This patch moves libz accordingly, to unbreak certain build scenarios. Reported-by: Kenneth Davidson Regression from 4f0f4bff5a92dce6a6cd7a5600a8ee5660402c3f #941 Fixes #1075 Closes #1077 - src: bump `hash_len` to `size_t` in `LIBSSH2_HOSTKEY_METHOD` Follow-up to 7b8e02257f01a6dac5f65305b18bb74a157fb5c4 Closes #1076 - ci: add non-static autotools i386 build, ignore GHA updates on AppVeyor Add a non-static autotools build to GitHub Actions. Make this build target i386 and libgcrypt, to test a new build combination if we are at it. Also: - GHA: add necessary generic bits for i386 autotools builds. - AppVeyor CI: teach it to ignore commits updating our GHA config. Follow-up to 572c57c9d8d4e89cfce19dde40125d55481256d1 #1072 Closes #1074 GitHub (31 May 2023) - [Xi Ruoyao brought this change] autotools: skip tests requiring static lib if `--disable-static` (#1072) Co-authored-by: Viktor Szakats Regression from 83853f8aea0e2f739cacd491632eb7fd3d03ad2d #663 Fixes #1056 Viktor Szakats (31 May 2023) - ci: prefer `=` operator in shell snippets Closes #1073 - src: bump DSA and ECDSA sign `hash_len` to `size_t` Closes #1055 - scp: fix missing cast for targets without large file support E.g. on 32-bit Linux. Issue revealed after adding i386 Linux CI build in abdf40c741c575f94bdea1c67a9d1182ff813ccb #1057. ``` /home/runner/work/libssh2/libssh2/src/scp.c: In function 'scp_recv': /home/runner/work/libssh2/libssh2/src/scp.c:765:23: error: conversion from 'libssh2_int64_t' {aka 'long long int'} to '__off_t' {aka 'long int'} may change value [-Werror=conversion] 765 | sb->st_size = session->scpRecv_size; | ^~~~~~~ ``` Ref: https://github.com/libssh2/libssh2/actions/runs/5126803482/jobs/9221746299?pr=1054#step:12:51 Regression from 5db836b2a829c6fff1e8c7acaa4b21b246ae1757 #1002 Closes #1060 - mbedtls.h: formatting [ci skip] For consistency with `mbedtls.c`. Follow-up to 1153ebdeba563ac657b525edd6bf6da68b1fe5e2 - libssh2.h: bump to 1.11.1_DEV [ci skip] - mbedtls: use more `size_t` to sync up with `crypto.h` Ref: 5a96f494ee0b00282afb2db2e091246fc5e1774a #846 #879 Fixes #1053 Closes #1054 - ci: drop redundant/unused vars, sync var names Closes #1059 - ci: add i386 Linux build (with mbedTLS) Also: - reorder Linux build matrix to make build tool more visible. - hide apt-get progress bar. - prepare package install step for i386 builds. Detects bug #1053 Closes #1057 - checksrc: switch to dot file Closes #1052 Version 1.11.0 (30 May 2023) Daniel Stenberg (30 May 2023) - libssh2.h: bump to 1.11.0 for release GitHub (30 May 2023) - [Will Cosgrove brought this change] Libssh2 1.11 release notes, copyright (#1048) * Libssh2 1.11 release notes, copyright Viktor Szakats (29 May 2023) - add copyright/credits Closes #1050 - ci: add LIBSSH2_NO_AES_CBC to GNU Make build Closes #1049 - ci: add wolfSSL Linux builds Exclude wolfSSL builds from tests. All fail: ``` 2/43 Test #2: test_aa_warmup ............................***Failed 5.59 sec libssh2_session_handshake failed (-44): Unable to ask for ssh-userauth service ``` Ref: https://github.com/libssh2/libssh2/actions/runs/5085775952/jobs/9139583212#step:12:942 (with logging) Ref: https://github.com/libssh2/libssh2/actions/runs/5085586301/jobs/9139192562#step:12:225 wolfSSL version: ``` Get:1 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libwolfssl32 amd64 5.2.0-2 [818 kB] Get:2 http://azure.archive.ubuntu.com/ubuntu jammy/universe amd64 libwolfssl-dev amd64 5.2.0-2 [1194 kB] ``` Cherry-picked from #1046 Closes #1046 - ci: mbedTLS build config tidy-up Cherry-picked from #1046 - wolfssl: fix detection of AES-GCM feature Follow-up to df513c0128e1a811ad863d153892618e728845f0 Ref: https://github.com/libssh2/libssh2/issues/1020#issuecomment-1562069241 Closes #1045 - build: fix 'unused' compiler warnings with all `NO` options set - add `LIBSSH2_NO_ED25519` build-time option to force-disable ED25519 support. Useful to replicate crypto-backend builds without ED25519, such as wolfSSL. - openssl: fix unused variable and function warnings with all supported `LIBSSH2_NO_*` options enabled. - mbedtls: fix misplaced `#endif` leaving out the required internal public function `libssh2_supported_key_sign_algorithms()`. - mbedtls: add missing prototype for two internal public functions. - delete a redundant block. All `NO` options: ```shell CPPFLAGS=' -DLIBSSH2_NO_MD5 -DLIBSSH2_NO_HMAC_RIPEMD -DLIBSSH2_NO_DSA -DLIBSSH2_NO_RSA -DLIBSSH2_NO_RSA_SHA1 -DLIBSSH2_NO_ECDSA -DLIBSSH2_NO_ED25519 -DLIBSSH2_NO_AES_CTR -DLIBSSH2_NO_BLOWFISH -DLIBSSH2_NO_RC4 -DLIBSSH2_NO_CAST -DLIBSSH2_NO_3DES' ``` Closes #1044 - cmake: avoid `list(PREPEND)` for compatibility `list(PREPEND)` requires CMake v3.15, our minimum is v3.1. `APPEND` should work fine for headers anyway. Also fix a wrongly placed comment. Ref: https://cmake.org/cmake/help/latest/command/list.html#prepend Regression from 1e3319a167d2f32d295603167486e9e88af9bb4e Closes #1043 - checksrc: verify label indent, fix fallouts Also update two labels to match the rest of the source. checksrc update credit: Emanuele Torre @emanuele6 Ref: https://github.com/curl/curl/pull/11134 Closes #1042 - tidy-up: minor nits - ci: drop default shared/static configuration options Both autotools and cmake build both shared and static lib by default. Ref: 896154bc17f000c0a1bb89b74bc879692ac0d47c Delete configuration enabling these explicitly in CI jobs. Cherry-picked from #1036 Closes #1036 - cmake: enable shared libssh2 library by default This brings default behaviour in sync with autotools, which builds both lib flavours by default. (Notice that on Windows, autotools includes the Windows Resource in the static library, when building both at the same time. CMake doesn't have this issue.) Enabling both lib flavours has a side-effect when using non-MinGW toolchains (e.g. MSVC): to resolve the filename conflict between import and static libraries, we add a suffix to the static lib, naming it `libssh2_static.lib`. This can break dependent builds relying on `libssh2.lib` for linking the static libssh2. Workarounds: - disable either shared or static libssh2 via `-DBUILD_STATIC_LIBS=OFF` or `-DBUILD_SHARED_LIBS=OFF`. This results in a libssh2 library (either static or shared) without a prefix: `libssh2.lib`. - set a custom static library suffix via: `-DSTATIC_LIB_SUFFIX=_my_static`. Resulting in `libssh2_my_static.lib`, and import library `libssh2.lib`. - set a custom import library suffix via: `-DIMPORT_LIB_SUFFIX=_my_implib`. Resulting in `libssh2_my_implib.lib` import library, and static library `libssh2.lib`. - customize the default static/import library suffix (incl. extension) via `-DCMAKE_STATIC_LIBRARY_SUFFIX=_my_static_suffix.lib` or `-DCMAKE_IMPORT_LIBRARY_SUFFIX=_my_import_suffix.lib`. Cherry-picked from #1036 - cmake: tweak static/import lib name collision avoidance logic The collision issue affects (typically) MSVC, when building both shared and static libssh2 in one go. Ref: https://stackoverflow.com/questions/2140129/what-is-proper-naming-convention-for-msvc-dlls-static-libraries-and-import-libr Initially we handled this by appending the `_imp` suffix to the import library filename. This is how curl tackles this, but on a second look, this solution seem to be accidental and has no widespread use. It seems more widely accepted to use the '_static' suffix for the static library. This patch implements this. (MinGW, Cygwin and unixy platforms are not affected by this issue.) Follow-up to 4e2580628dd1f8dc51ac65ac747ebcf0e93fa3d1 Cherry-picked from #1036 - cmake: add `IMPORT_LIB_SUFFIX` (like `STATIC_LIB_SUFFIX`) Allow resolving the import/static library name collision also by setting a custom _import_ library name suffix. Follow-up to 4e2580628dd1f8dc51ac65ac747ebcf0e93fa3d1 Cherry-picked from #1036 - ci: do not disable shared lib with msys2/autotools in GHA Cherry-picked from #1036 - Makefile.mk: fix `DYN=1 test` by skipping tests needing static lib `DYN=1` means to build examples/tests against the shared libssh2. Before this patch this was broken for building tests. This patch skips building tests that require the static libssh2 library, so the build now succeeds. Also move the list of tests that require static lib from `CMakeLists.txt` to `Makefile.inc`, so that we can reuse it in `Makefile.mk`. Couldn't find a way to also reuse it in `Makefile.am`. Move the `Makefile.am` specific definitions close to the shared list, to make it easier to keep them synced. Cherry-picked from #1036 - ci: make one of the AppVeyor CMake jobs shared-only This build combination did not have a CI test before. Cherry-picked from #1036 - cmake: allow tests with `BUILD_STATIC_LIBS=OFF` Before this patch, the CMake build did not allow to disable static libssh2 library while also building tests. This patch removes this constraint, and makes this combination possible. In this case the 3 (at the moment) tests that require a static libssh2 library, are skipped from the build and test runs. Cherry-picked from #1036 - build: fix to set `-DLIBSSH2DEBUG` for tests Required for tests using libssh2 internals. These are the ones requiring the libssh2 _static_ lib. Before this patch, `src` and `tests` declared the `session` structure differently, due to extra struct members added with the `LIBSSH2DEBUG` macro set. But, the macro was only set for `src` when using CMake. At runtime this caused struct members to be at different offsets between lib and test code, resulting in the test failures below. Due to another bug in the affected test, these failures did not reflect in the exit code, which always returned success, so this went unnoticed for a good while. Fixed in: 84d31d0ca7b647ad4c2aa92bf8f4a94b233f5d3b ``` Start 5: test_auth_keyboard_info_request [...] 5: Test case 1 passed 5: Test case 2 passed 5: Test case 3: expected return code to be 0 got -1 5: Test case 4: expected last error code to be "-6" got "-38" 5: Test case 5: expected last error code to be "-6" got "-38" 5: Test case 6: expected last error code to be "-6" got "-38" 5: Test case 7: expected last error message to be "Unable to decode keyboard-interactive number of keyboard prompts" got "userauth keyboard data buffer too small to get l 5: Test case 8: expected last error code to be "-41" got "-38" 5: Test case 9: expected return code to be 0 got -1 5: Test case 10: expected return code to be 0 got -1 5: Test case 11: expected last error code to be "-6" got "-38" 5: Test case 12: expected last error message to be "Unable to decode user auth keyboard prompt echo" got "userauth keyboard data buffer too small to get length" 5: Test case 13: expected return code to be 0 got -1 5: Test case 14: expected return code to be 0 got -1 5: Test case 15: expected last error code to be "-6" got "-38" 5: Test case 16: expected last error code to be "-6" got "-38" 5: Test case 17: expected last error code to be "-6" got "-38" 5: Test case 18: expected last error code to be "-6" got "-38" ``` Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46925869/job/i9uasceu3coss0i2#L440 Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46983040/job/c3vag25c26a77lyr#L485 Cherry-picked from #1037 Closes #1037 - test_auth_keyboard_info_request: fix to return failure Before this patch, this test returned success even when one of its tests failed. Fix it by returning 1 in case any of the tests fails. This issue masked a CMake build bug with logging enabled. Subject to an upcoming patch. Cherry-picked from #1037 - test_auth_keyboard_info_request: fix indentation Cherry-picked from #1037 - tidy-up: move comment off from copyright header Cherry-picked from #1037 - ci: enable shared libs in msys2/macOS cmake builds Shared libs improve example/tests build times. For "unity" builds the overhead of building shared lib is negligible, so this even reduced the overall build-time. Follow-up to 3d64a3f5100f7f4cf52202396eb4f1c3f3567771 Follow-up to d93ccf4901ef26443707d341553994715414e207 Tests: https://github.com/libssh2/libssh2/actions/runs/4906586658: unity builds enabled https://github.com/libssh2/libssh2/actions/runs/4906925743: unity builds enabled + parallel msys2 builds https://github.com/libssh2/libssh2/actions/runs/4906777629: unity + shared lib (this commit) https://github.com/libssh2/libssh2/actions/runs/4906927190: unity + shared lib (this commit) + parallel msys2 builds Consider making shared libs enabled by default also in CMake, to sync it with autotools? Closes #1035 - ci: add missed --parallel 3 from msys2 cmake builds Follow-up to 3d64a3f5100f7f4cf52202396eb4f1c3f3567771 - cmake: add and test "unity" builds "Unity" (aka "jumbo", aka "amalgamation" builds concatenate source files before compiling. It has these benefits for example: faster builds, improved code optimization, cleaner code. Let's support and test this. - enable unity builds for some existing CI builds to test this build scenario. - tune `UNITY_BUILD_BATCH_SIZE` size. - disable unity build for example and test programs (they use one source each already). You can enable it by passing `-DCMAKE_UNITY_BUILD=ON` to cmake. Supported by CMake 3.16 and newer. Ref: https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html Closes #1034 - tests: simplify passing `srcdir` to tests Before this patch libssh2 used a variety of solutions to pass the source directory to tests: `FIXTURE_WORKDIR` build-time macro (cmake), `FIXTURE_WORKDIR` envvar (unused), setting `srcdir` manually (autotools), setting current directory (cmake), and also `builddir` envvar (autotools) for passing current working dir to `mansyntax.sh`. This patch reduces this to using existing `srcdir` with autotools and setting it ourselves in CMake. This was mostly enabled by this recent patch: 4c9ed51f962f542b98789b15bedaaa427f4029a2 Details: - cmake: replace baked-in `FIXTURE_WORKDIR` macro with env. Added in 54bef4c5dad868a9d45fdbfca9729b191c0abab5 #198 (2018-03-21) - rename `FIXTURE_WORKDIR` to `srcdir`, to match autotools. - cmake: add missing `srcdir` for algo and sshd tests. - session_fixture: stop `chdir()`-ing, rely on prefixing with `srcdir`. Changing current directory should be unnecessary after 4c9ed51f962f542b98789b15bedaaa427f4029a2 #801 (2023-02-24), that prefixes referenced input filenames with the `srcdir` envvar. The `srcdir` envvar was already exported by autotools, and now we're also setting it from CMake. - cmake: stop setting `WORKING_DIRECTORY`, rely on `srcdir` env. `WORKING_DIRECTORY` is no longer necessary, after passing `srcdir` to all tests, so they can find our source tree and keys/etc in it regardless of the current directory. Also this past commit hints that `WORKING_DIRECTORY` wasn't always working for this purpose as expected: "tests: Xcode doesn't obey CMake's test working directory" Ref: https://github.com/libssh2/libssh2/pull/198/commits/10a5cbf945abcc60153ee3d59284d09fc64ea152 - autotools: delete explicit `srcdir` for test env. Added in 13f8addd1bc17e6c55d52491cc6304319ac38c6d (2015-07-02) automake documents `srcdir` as exported to the test environment: https://github.com/autotools-mirror/automake/blob/c04c4e8856e3c933239959ce18e16599fcc04a8b/doc/automake.texi#L9302-L9304 https://www.gnu.org/software/automake/manual/html_node/Scripts_002dbased-Testsuites.html It's mentioned in the docs back in 1997 and got a regression test in 2012. We can safely assume it to be available without setting it ourselves. - autotools: delete explicit `builddir`. Added in 13f8addd1bc17e6c55d52491cc6304319ac38c6d (2015-07-02) It seems this wasn't necessary to make the above fix work, and `mansyntax.sh` is able to figure out the build workdir by reading `$PWD`. Our out-of-tree and `make distcheck` CI builds also work without it. Let us know if there is a scenario we're missing and needs this. Closes #1032 - src: fix `libssh2_store_*()` for >u32 inputs `_libssh2_store_str()` and `_libssh2_store_bignum2_bytes()` accept inputs of `size_t` max, store the size as 32-bit unsigned integer, then store the complete input buffer. With inputs larger than `UINT_MAX` this means the stored size is smaller than the data that follows it. This patch truncates the stored data to the stored size, and now returns a boolean with false if the stored length differs from the requested one. Also add `assert()`s for this condition. This is still not a correct fix, as we now dump consistent, but still truncated data which is not what the caller wants. In future steps we'll need to update all callers that might pass large data to this function to check the return value and handle an error, or make sure to not call this function with more than UINT_MAX bytes of data. Ref: c3bcdd88a44c4636818407aeb894fabc90bb0ecd (2010-04-17) Ref: ed439a29bb0b4d1c3f681f87ccfcd3e5a66c3ba0 (2022-09-29) Closes #1025 - cmake: limit WinCNG to Windows After deleting the `bcrypt.h` check, no check remained. Restore a `WIN32` check here to ensure WinCNG is not enabled outside Windows. Follow-up to 1289033598546ee5089ff0fc4369d24e1e2be81f Tested-in #1032 - cmake: move `CMAKE_VS_GLOBALS` setting to CI configs To not force this setting for local builds where they might serve a good purpose. It makes our CI runs slightly faster and we don't need to track file changes in unattended, single, CI runs. Cherry-picked from #1031 - cmake: prefill for faster config phase on Windows Prefill known detection results on Windows with MinGW and MSVC, to avoid spending time on detecting these on every cmake configuration run. With MinGW + clang and MSVC, this elminates all detections. With MinGW + gcc, it reduces them to 3. Cherry-picked from #1031 - libssh2_setup.h: set `HAVE_INTTYPES_H` for MSVC To sync up the hand-crafted config with actual detection results by CMake and autotools. Sources compiled fine without it anyway. Cherry-picked from #1031 - cmake: re-add `select()` detection (regression) `select()` detection suffered two regressions: First I accidentally deleted it for non-Windows [1]. Then the Windows-specific setting got missed from the generated `libssh2_config.h` after a rearrangement in `CMakeLists.txt` files. [1] 31fb8860dbaae3e0b7d38f2a647ee527b4b2a95f (2023-03-07) [2] 803f19f004eb6a5b525c48fff6f46a493d25775c (2023-04-18) This patch restores detection. For Windows, enable it unconditionally, not only for speed reasons, but because detection needs `ws2_32`, and even that is broken on the x86 platform. According to the original `cmake/SocketLibraries.cmake`, caused by a calling convention mismatch. FWIW autotools detects it correctly. Cherry-picked from #1031 - ci: merge make job into msys2 section, enable zlib + openssl Follow up to dd625766271a0ba13f5ac661bdc2fa40bbfa580a Cherry-picked from #1030 - ci: add missing timeouts for autotools tests Cherry-picked from #1030 - ci: add mingw-w64 clang and gcc CMake jobs Cherry-picked from #1030 - cmake: assume `bcrypt.h` with WinCNG autotools already didn't check for `bcrypt.h`, and such check is only required for old/legacy mingw without obsolete/incomplete Windows headers. curl deprecated old-mingw support just recently and will delete support in September 2023. This patch saves some complexity and detection time by dropping this check for CMake. Meaning that mingw-w64 is now required to compile libssh2 when using the WinCNG backend for 32-bit builds. Other backends and CPU platforms are not affected. Ref: https://github.com/curl/curl/commit/e4d5685cb5d6eb07e1b43156fd7e3ba3563afba5 Closes #1026 - cmake: do not check for `poll()` on Windows While it seems to exist on mingw in theory, it's not detected as of this writing. It also has issues, and not ready for production use: https://stackoverflow.com/questions/1671827/poll-c-function-on-windows On MSVC it's even less supported. Skip checking this to save CMake detection time. Closes #1027 - agent_win: make a struct static and other build improvements Also: - merge back `agent.h` into `agent.c` where it was earlier. Ref: c998f79384116e9f6633cb69c2731c60d3a442bb - introduce `HAVE_WIN32_AGENT` internal macro. - fix two guards to exclude more code unused in UWP builds. Follow-up to 1c1317cb768688eee0e5496c72683190aaf63b29 Closes #1028 - tidy-up: formatting nits Whitespace and redundant parenthesis in `return`s. Closes #1029 GitHub (3 May 2023) - [Nick Woodruff brought this change] sftp: parse attribute extensions, if present, to avoid stream parsing errors (#1019) Prevents directory listing errors when attribute extensions are present by advancing stream parsing past extensions. Viktor Szakats (3 May 2023) - tests: merge `sshd_fixture.sh` into `test_sshd.test` Merge the loop executing multiple tests and the script that actually launches the tests into a single script. This same script is now called from both autotools and CMake. autotools loads the list of tests from `Makefile.inc`, CMake passes it via the command-line. It's also possible to call the script manually with a custom list of tests or individual ones. With this setup we're now launching a single sshd session for all tests, instead of launching and killing it for each test. This did not improve reliability of these test on CI machines, and it's easy to go back to the previous behaviour if necessary. Also: - allow passing custom sshd options via `SSHD_FLAGS`. - add `SSHD_TESTS_LIMIT_TO` to limit the number of tests to its value. E.g. `SSHD_TESTS_LIMIT_TO=1` executes the first test only. Meant for debugging. - use `ssh` to test the connection (if available) instead of fixed amount of wait. Made to also work on Windows. - set `PermitRootLogin yes` in `sshd`, to allow running tests as root. - show `sshd` path and version. Cherry-picked from #1017 (the last one) Closes #1024 - ci: make sure to run tests after all builds in GHA Whenever possible. Due to flakiness/hangs/timeouts, keep sshd tests disabled on Windows and macOS. Also keep Docker tests disabled on these platforms, they do not work: GHA Windows: ``` no matching manifest for windows/amd64 in the manifest list entries ``` GHA macOS: ``` sh: docker: command not found ``` It's not possible to run UWP and ARM64 binaries: UWP: ``` Test #2: test_simple ......................Exit code 0xc0000135 ``` Needs but doesn't find: `VCRUNTIME140_APP.dll`. ARM64 ``` D:/a/libssh2/libssh2/bld/tests/Release/test_ssh2.exe: cannot execute binary file: Exec format error ``` Cherry-picked from #1017 - tests: disable sshd tests on Windows via new options Instead of using hacks inside the build systems. `SSHD` variable added to GitHub Actions is not currently used. Added there to make it easy to experiment with these tests and the path is non-trivial to discover. Using the Windows built-in sshd server is another option (haven't discovered its path yet). Cherry-picked from #1017 - tests: add cmake/autotools options to disable running tests autotools: - `--disable-docker-tests` - `--disable-sshd-tests` cmake: - `RUN_DOCKER_TESTS` - `RUN_SSHD_TESTS` Update automake and ci to use this new flag and delete former logic of relying on Windows detection and `HOST_WINDOWS`. Also fix honoring this when running `test_read_algos.test`. This allows to disable these individually and on per-CI/local-job basis. To run as much tests as the env allows. Cherry-picked from #1017 - ci: add `make distcheck` job Cherry-picked from #1017 - ci: switch to out-of-tree autotools builds Cherry-picked from #1017 - ci: restore parallel builds with cmake Also add missing -j3 for macOS builds. Partial revert of 0d08974633cfc02641e6593db8d569ddb3644255 Cherry-picked from #1017 - ci: sync names, steps, syntax, build dirname between jobs Also: - delete an unused 64-bit option for Linux (all jobs are 64-bit). - fix to not install libgcrypt and openssl when doing mbedTLS builds. [ Empty lines after multiline run commands are solely to unbreak my editor's syntax highlighting. They can be deleted in the future ] Cherry-picked from #1017 - ci: add `Makefile.mk` test, with `LIBSSH2_NO_*` options Cherry-picked from #1017 - Makefile.mk: use Makefile.inc from example and tests Instead of assembling the list using `$(wildcard ...)`. Also split off a `tests/Makefile.inc` from `tests/Makefile.am`. With its simpler syntax, this also allows to delete some complexity from the CMake loader. Cherry-picked from #1017 - example, tests: fix ssh2 to correctly return failure Before this patch ssh2 and test_ssh2 returned success even if the session failed at `libssh2_session_handshake()` or after. This patch depends on cda41f7cb87c3af5258ba48ccef19d3efdbd3d3b, that fixed running test_ssh2 on Windows via sshd_fixture. Cherry-picked from #1017 - tests: set -e -u in shell scripts Cherry-picked from #1017 - cmake: use shared libs again in example and tests Re-sync with autotools and v1.10.0 behavior. This improves build times. It also allows to stop building our special shared test target to test shared builds. Follow-up to 4e2580628dd1f8dc51ac65ac747ebcf0e93fa3d1 Cherry-picked from #1017 Closes #1022 - tests: retry KEX failures when using the WinCNG backend Twice. This tests are flaky and we haven't figured out why. In the meantime use this workaround to test and log these issues, but also ensure that CI run aren't flagged red because of it. Also: - kex: add debug message when hostkey `sig_verify` fails, to help tracking WinCNG KEX failures. - test_ssh2: also add retry logic. I'm not quite sure this is correct. Please let me know. - session_fixture: bump up `src_path` slots to fit retries and show message when hitting the limit. - session_fixture: clear `kbd_password` static variable after use. - session_fixture: close and deinit socket after use. - session_fixture: deinit libssh2 after use. Ref: #804 #846 #979 #1012 #1015 Cherry-picked from #1017 Closes #1023 - example, test_ssh2: shutdown socket before close Syncing them with `tests/session_fixture.c`. Cherry-picked from #1017 - ci.yml: fix indentation [ci skip] Cherry-picked from #1017 - Makefile.mk: make tests depend on runner lib Cherry-picked from #1017 - build: compile agent_win.c via agent.c Silences these warnings on non-Windows: ``` ranlib: file: libssh2.a(agent_win.c.o) has no symbols ``` Cherry-picked from #1017 - cmake: delete obsolete comment Follow-up to 80175921638fa0a345237d23206a2ad1644cdd9b Cherry-picked from #1017 - checksrc.sh: fix it to run from any current directory Also silence a shellcheck warning. Cherry-picked from #1017 - ISSUE_TEMPLATE: ask for crypto backend version Also fix casing in backend names. Cherry-picked from #1017 - tests: fix newlines in test keys for sshd on Windows Make sure these files get LF newlines on checkout. Before this patch a checked out libssh2 Git repository may have used CRLF newlines in text files, include test keys. Private keys with CRLF newlines could confuse sshd on Windows: ``` # sshd version: 'OpenSSH_9.2, OpenSSL 1.1.1t 7 Feb 2023' Unable to load host key "/d/a/libssh2/libssh2/tests/openssh_server/ssh_host_ed25519_key": invalid format Unable to load host key: /d/a/libssh2/libssh2/tests/openssh_server/ssh_host_ed25519_key ``` Ref: https://github.com/libssh2/libssh2/actions/runs/4846188677/jobs/8635575847#step:6:39 Cherry-picked from #1017 - cmake: move option descriptions next to definition Cherry-picked from #1017 - checksrc: sync with curl There were no new issues detected. Cherry-picked from #1017 - openssl: enable AES-GCM with wolfSSL Follow-up to 3c953c05d67eb1ebcfd3316f279f12c4b1d600b4 #797 There is pending issue with wolfSSL, where encryption/decryption is not working (both with and without this patch). Ref: #1020 Cherry-picked from #1017 - appveyor: add a UWP OpenSSL 3 build Cherry-picked from #1017 - appveyor: skip `before_test` when not doing tests Also merge `before_test` section into `test_script`. Cherry-picked from #1017 - docs: delete two stray characters Cherry-picked from #1017 - tidy-up: avoid expression 'of course' Cherry-picked from #1017 - tidy-up: avoid word 'just' Cherry-picked from #1017 - tidy-up: avoid word 'simply' Cherry-picked from #1017 - tests: teach to use the `USERNAME` envvar on Windows Necessary to pick the correct local username when run on Windows. Cherry-picked from #1017 - test_ssh2: support `FIXTURE_TRACE_ALL*` envvars Cherry-picked from #1017 - tidy-up: add missing newline to error msg, formatting Also: - fix indent - lowercase variables names - fix formatting in `src/global.c` Cherry-picked from #1017 - appveyor: wait more for SSH connection from GHA Cherry-picked from #1017 - ci: restrict permissions in GitHub Actions Cherry-picked from #1017 - build: fix autoreconf warnings - update `AC_HELP_STRING' to 'AS_HELP_STRING`: ``` configure.ac:[...]: warning: The macro `AC_HELP_STRING' is obsolete. ``` "AC_HELP_STRING is deprecated in 2.70+ and I believe AS_HELP_STRING works already since 2.59 so bump the minimum required version to that." Ref: https://github.com/curl/curl/commit/a59f04611629f0db9ad8e768b9def73b9b4d9423 - simplify to avoid: ``` src/Makefile.inc:48: warning: variable 'EXTRA_DIST_SOURCES' is defined but no program or src/Makefile.inc:48: library has 'DIST' as canonical name (possible typo) ``` Regression from 2c18b6fc8df060c770fa7e5da704c32cf40a5757 - `AC_TRY_LINK`/`AC_TRY_COMPILE`: ``` configure.ac:335: warning: The macro `AC_TRY_COMPILE' is obsolete. configure.ac:335: warning: The macro `AC_TRY_LINK' is obsolete. ``` - `libtool`-related ones: ``` configure.ac:70: warning: The macro `AC_LIBTOOL_WIN32_DLL' is obsolete. configure.ac:70: warning: AC_LIBTOOL_WIN32_DLL: Remove this warning and the call to _LT_SET_OPTION when you configure.ac:70: put the 'win32-dll' option into LT_INIT's first parameter. configure.ac:71: warning: The macro `AC_PROG_LIBTOOL' is obsolete. ``` Using code copied from curl: https://github.com/curl/curl/blob/9ce7eee07042605045dcfd02a6f5b38ad5c8a05d/m4/xc-lt-iface.m4#L157-L163 - delete commented and obsolete `AC_HEADER_STDC`. - formatting. Most cherry-picked from `autoupdate` updates. Cherry-picked from #1017 Closes #1021 - docker-bridge.ps1: use native newlines Also add a shebang and exec flag to ease testing/handling on *nix. PowerShell accepts both LF and CRLF. Cherry-picked from #1017 GitHub (1 May 2023) - [Zenju brought this change] sftp: remove packet limit for directory reading (#791) Currently libssh2 cannot read huge directory listings when the package size of `LIBSSH2_SFTP_PACKET_MAXLEN` (256KB) is hit. For example AWS always sends a single package with all files of a directory, no matter how big it is: https://freefilesync.org/forum/viewtopic.php?t=10020 Package size is probably around 7MB in this case! `LIBSSH2_SFTP_PACKET_MAXLEN` is a good idea in general, but there doesn't seem to be a one size fits all. While almost all(?) SFTP responses come in very small packages, I believe the `SSH_FXP_READDIR` request should be exempted. The proposed patch, enhances the package size reading to include parsing the full SFTP packet header. And in case a package is of type `SSH_FXP_NAME` and matches an expected `readdir_request_id`, it does not fail if `LIBSSH2_SFTP_PACKET_MAXLEN` is hit. The chances of accidentally hiding data-corruption are pretty non-existent, because both SFTP `request_id` and packet type must match. No change in behavior otherwise. Best, Zenju Previous discussion: #268 #269 With the above changes, the `LIBSSH2_SFTP_PACKET_MAXLEN` value could (and should?) probably be set back to a small number again. Integration-patches-by: Viktor Szakats Viktor Szakats (28 Apr 2023) - checksrc: update and apply fixes Update to latest revision and fix new issues detected. Closes #1014 - ci: add macOS CI jobs + fix issues revealed Add macOS CI jobs, both cmake and autotools for all supported crypto backends (except BoringSSL), with debug, zlib enabled. Without running tests. It also introduces OpenSSL 1.1 into the CI with a non-MSVC compiler. Credits to curl's `macos.yml`, that I used as a base. Fix these issues uncovered by the new tests: - openssl: fix warning when built with wolfSSL, or OpenSSL 1.1 and earlier. CI missed it because apparently the only OpenSSL 1.1 test we had used MSVC, which did not complain. ``` ../src/openssl.c:3852:19: error: variable 'sslError' set but not used [-Werror,-Wunused-but-set-variable] unsigned long sslError; ^ ``` Regression from 097c8f0dae558643d43051947a1c35b65e1c5761 - pem: add hack to build without MD5 crypto-backend support. The Homebrew wolfSSL build comes with MD5 support disabled. We can expect this becoming the norm. FIPS also requires MD5 disabled. We deleted the same hack from `hostkey.c` a month ago: ad6aae302aaec84afbfacf0c1dfdc446d46eaf21 A better fix would be to guard the MD5 logic with our `LIBSSH2_MD5` macro. ``` pem.c:214:32: error: use of undeclared identifier 'MD5_DIGEST_LENGTH'; did you mean 'SHA_DIGEST_LENGTH'? unsigned char secret[2*MD5_DIGEST_LENGTH]; ^~~~~~~~~~~~~~~~~ SHA_DIGEST_LENGTH ``` Regression from 386e012292a96fcf0dc6861588397845df0aba2c - `configure.ac`: add crypto libs late. Fix it by adding crypto libs to `LIBS` at the end of the configuration process. Otherwise `configure` links crypto libs while doing feature tests, which can cause unwanted detections. For example LibreSSL publishes the function `explicit_bzero()`, which masks the system alternative, e.g. `memset_s()` on macOS. Then when trying to compile libssh2, its declaration is missing: ``` bcrypt_pbkdf.c:93:5: error: implicit declaration of function 'explicit_bzero' is invalid in C99 [-Werror,-Wimplicit-function-declaration] _libssh2_explicit_zero(ciphertext, sizeof(ciphertext)); ^ ../src/misc.h:50:43: note: expanded from macro '_libssh2_explicit_zero' ^ ``` Regression from 4f0f4bff5a92dce6a6cd7a5600a8ee5660402c3f - cmake: fix to list our own include directory before the crypto libs', when building tests. Otherwise a global crypto header path, such as `/usr/local/include`, containing an external `libssh2.h` of a different version, could cause weird errors: ``` cc -DHAVE_CONFIG_H -DLIBSSH2_LIBGCRYPT \ -I../src -I../../src -I/usr/local/include -I[...]/libssh2/include \ -g -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk \ -mmacosx-version-min=12.6 -MD -MT \ tests/CMakeFiles/test_aa_warmup.dir/test_aa_warmup.c.o \ -MF CMakeFiles/test_aa_warmup.dir/test_aa_warmup.c.o.d \ -o CMakeFiles/test_aa_warmup.dir/test_aa_warmup.c.o -c \ [...]/libssh2/tests/test_aa_warmup.c ``` ``` [ 62%] Building C object tests/CMakeFiles/test_aa_warmup.dir/test_aa_warmup.c.o In file included from /Users/runner/work/libssh2/libssh2/tests/test_aa_warmup.c:4: In file included from /Users/runner/work/libssh2/libssh2/tests/runner.h:42: In file included from /Users/runner/work/libssh2/libssh2/tests/session_fixture.h:43: /Users/runner/work/libssh2/libssh2/tests/../src/libssh2_priv.h:649:5: error: type name requires a specifier or qualifier LIBSSH2_AUTHAGENT_FUNC((*authagent)); ^ /Users/runner/work/libssh2/libssh2/tests/../src/libssh2_priv.h:649:30: error: type specifier missing, defaults to 'int' [-Werror,-Wimplicit-int] LIBSSH2_AUTHAGENT_FUNC((*authagent)); ^ /Users/runner/work/libssh2/libssh2/tests/../src/libssh2_priv.h:650:5: error: type name requires a specifier or qualifier LIBSSH2_ADD_IDENTITIES_FUNC((*addLocalIdentities)); ^ /Users/runner/work/libssh2/libssh2/tests/../src/libssh2_priv.h:650:35: error: type specifier missing, defaults to 'int' [-Werror,-Wimplicit-int] LIBSSH2_ADD_IDENTITIES_FUNC((*addLocalIdentities)); ^ /Users/runner/work/libssh2/libssh2/tests/../src/libssh2_priv.h:651:5: error: type name requires a specifier or qualifier LIBSSH2_AUTHAGENT_SIGN_FUNC((*agentSignCallback)); ^ /Users/runner/work/libssh2/libssh2/tests/../src/libssh2_priv.h:651:35: error: type specifier missing, defaults to 'int' [-Werror,-Wimplicit-int] LIBSSH2_AUTHAGENT_SIGN_FUNC((*agentSignCallback)); ^ 6 errors generated. ``` - `tests/session_fixture.h`: delete duplicate `libssh2.h`, `libssh2_priv.h` already includes it. Follow-up to a683133dfe96de126194f58f183131a84c7d36a2 CI logs with these errors: https://github.com/libssh2/libssh2/actions/runs/4824079094 https://github.com/libssh2/libssh2/actions/runs/4824270819 curl's `macos.yml`: https://github.com/curl/curl/blob/da2470de96e94e1c8d276b9ae6e4c97c2cf54239/.github/workflows/macos.yml Tidying-up while here: - tests/session_fixture.h: delete duplicate `libssh2.h`. `libssh2_priv.h` includes it already. Follow-up to a683133dfe96de126194f58f183131a84c7d36a2 - ci.yml: yamllint warnings and formatting. - ci.yml: msvc section formatting and step-naming sync with macOS. Follow-up to f4a4c05dc3bcd62ecaa1b0cac5997faefe16c83f - ci.yml: enable `--enable-werror` for msys2 jobs. Follow-up to 71cae949d577fdd632a271da0bec89f977dc5dd2 - appveyor.yml: show OpenSSL versions, link to image content. Closes #1013 - ci: convert `docker-bridge.bat` to shell script Convert `ci/appveyor/docker-bridge.bat` to a POSIX shell script. Also bump the tunnel to use ed25519 (was RSA-2048). Closes #997 - kex: use distinctive error strings Use unique error strings to help localize errors. Closes #1011 - tidy-up: C header use - drop unused or duplicate C headers. - add missing ones (that worked by chance). (`string.h`, `stdlib.h`) - mention the functions that need certain headers. - move some headers from crypto header to crypto C source. - reorder headers in some places. - simplify the #if tree for `sys/select.h` in `libssh2_priv.h`. - move scp-specific macros next to their header to `scp.c` Follow-up to 5db836b2a829c6fff1e8c7acaa4b21b246ae1757 Closes #999 - tidy-up: text nits, English contractions [ci skip] In input/output text and docs mostly. - ci: add MSVC and UWP builds to GitHub Actions - add MSVC jobs to GitHub Actions. They are similar to the 'Build-only' jobs we have on AppVeyor CI, though only the ARM64 Windows one is identical. Major disadvantage is that we don't run tests here. Major advantage is they only take a few minutes to complete, compared to an hour on AppVeyor, so WinCNG build results now appear quicker. Docker tests might be possible, but my light attempts failed. Finding ZLIB also failed, so we still miss an MSVC test with it. Tool versions as of now: Server 2022, VS2022, OpenSSL 1.1.1 - add UWP builds for both ARM64 and x64. This hasn't been CI tested before. (We could probably enable UWP on AppVeyor CI as well. I haven't tried.) - fix two uncovered UWP issues in tests. - rename internal macro `LIBSSH2_WINDOWS_APP` to `LIBSSH2_WINDOWS_UWP`. Follow-up to 2addafb77b662e64248d156c71c69b91ba7b926e - fold long lines and quote truthy values in `.github/workflows/ci.yml`. Closes #1010 - session_fixture: avoid no-op `chdir(getcwd())` If no `FIXTURE_WORKDIR` macro or envvar is present to set the cwd, avoid querying the cwd and then calling chdir with the result. Ref: 54bef4c5dad868a9d45fdbfca9729b191c0abab5 (patch) Ref: 10a5cbf945abcc60153ee3d59284d09fc64ea152 (individual commit) Closes #1009 - tests/sshd_fixture.sh: convert back to POSIX There was no strong reason to require bash. Let's use POSIX shell like before the recent overhaul. Follow-up to a459a25302a31f6e2aba3c4e15b1472b83b596fc Closes #1008 GitHub (26 Apr 2023) - [Miguel de Icaza brought this change] If SFTP fails to initialize, do not busy loop waiting for IO to happen (#720) Currently SFTP's init will busy loop waiting for the channel to close, even if the underlying transport returns EAGAIN. While this works for sockets, it might not work out if you have a different transport that needs to do some additional processing on the side. Integration-patches-by: Viktor Szakats Viktor Szakats (26 Apr 2023) - docs: simplify `.TH` header & other cleanups [ci skip] - simplify `.TH` headers. - delete empty lines before sections. - update template with an `AVAILABILITY` section. Left libssh2 version number in the `.TH` header for entries without an `AVAILABILITY` section, or where there was a different version number there. - tidy-up: formatting nits [ci skip] - vms: fix to include `sys/socket.h` Due to a typo in the `HAVE_*` macro, this header was never included. A comment suggests that `socklen_t` is not defined on VMS and defines it manually. This symbol is usually in `sys/socket.h`, so the typo may have been the reason for it to be missing. Closes #1007 - build: fix `make distcheck` regressions - add #included C files to `EXTRA_DIST`. Regression from 4f0f4bff5a92dce6a6cd7a5600a8ee5660402c3f - fix `tests/sshd_fixture.sh` to not write into the test dir, by using a pre-assembled `TrustedUserCAKeys` file. Update `Dockerfile` too to use this. Regression from a459a25302a31f6e2aba3c4e15b1472b83b596fc Also update `tests/sshd_fixture.sh` to use `openssh_server/authorized_keys` like `Dockerfile` does. And a few more cosmetic updates. Closes #1006 - libssh2_priv.h: assume `HAVE_LONGLONG` Unless I'm missing something, it looks like `libssh2.h` has been using `libssh2_int64_t` unconditionally since at least 2010-04-17 when `libssh2_scp_send64()` landed via commit be9ee7095e2d5021985f57d88f5f889d3c2b9d8f. This makes it redundant to detect `HAVE_LONGLONG` to fallback to a 32-bit `scpRecv_size` in `libssh2_priv.h`. Then deal with possible combinations of this flag and `strtoll()` options, which was error-prone. Instead, assume in `libssh2_priv.h` that we have `libssh2_int64_t`, and use it always. For MSVC, this means `_MSC_VER` `1310` (from year 2003) is now required. Based on the above, this was already so before this patch. If there happens to be no 64-bit `strtoll()` detected, fall back to the 32-bit `strtol()` (this should never happen with MSVC, and probably neither with any other reasonably modern toolchain.) Also make sure to set `HAVE_STRTOI64` for older, non-CMake, MSVC builds (e.g. `Makefile.mk` or `NMakefile` ones). Closes #1002 GitHub (26 Apr 2023) - [Miguel de Icaza brought this change] fix a couple of small regressions (#1004) - openssl: fix potentially missing `ERR_*` constants by including `openssl/err.h`. This could happen with recent version of Xcode or when building against OpenSSL built with the `OPENSSL_NO_ENGINE` option. Regression from 097c8f0dae558643d43051947a1c35b65e1c5761 (#789) - channel: fix an issue that would corrupt the data stream when attempting to initialize the agent in non-blocking mode, as it is necessary to propagate the `EAGAIN` signal upstream when the transport returns `EAGAIN`. Regression from bc4e619e76071393e466c29220fc4ef5764c2820 (#752) - packet: the current code does not set the state machine upon reaching this point which means that if the code is suspended due to the transport returning an `EAGAIN`, this will re-initialize the structure every time. The issue is that this keeps assigning a new channel-id downstream, which does not match the initial channel-id that is initially generated, causing a lookup later to fail as there is no matching channel. Regression from bc4e619e76071393e466c29220fc4ef5764c2820 (#752) Viktor Szakats (26 Apr 2023) - tidy-up: `gettimeofday()` fallback and use Simplify the way we handle `gettimeofday()` fallback for platforms without native support or without any support. Make it similar to how we handle `snprintf()`. In case of no native `gettimeofday()` support and a non-Windows platform, our local fallback returns zero in `tv_usec` and `tv_sec`, ending up with a zero `timeout_remaining` in `session.c`, same as before this patch. Also: - drop unused `sys/time.h` headers. - fix our fallback code to compile with any Windows compilers (not just MSVC) - delete unnecessary casts. Closes #1001 - libssh2_priv.h: fix checksrc warning [ci skip] Regression from 9ef75298fae0728305d9d38ba1e3c838ad0513f7 - libssh2_priv.h: whitespace fixes cont. [ci skip] - libssh2_priv.h: whitespace fixes [ci skip] - cmake: use portable mkdir for tests/coverage target [ci skip] Makes `make coverage` work without a POSIX mkdir. Tested locally. Ref: https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-E-arg-make_directory - kex: fix overlapping memcpy() to memmove() Noticed this when libasan started kicking out errors when sending in MACs preferences that were not supported yet. Reported-by: fourierules on github Fixes #611 Closes #1000 - test/CMakeLists.txt: reuse `Makefile.am` librunner source list Follow-up to a459a25302a31f6e2aba3c4e15b1472b83b596fc Closes #998 GitHub (25 Apr 2023) - [Zenju brought this change] openssl: fix misleading error message if wrong passphrase (#789) Fixes #608 Viktor Szakats (25 Apr 2023) - tidy-up: tiny nits [ci skip] - tests: improve running tests TL;DR: Sync test builds between autotools and CMake. Sync sshd configuration between Docker and non-Docker fixtures. Bump up sshd_config for recent OpenSSH releases. This also opens up the path to have non-Docker tests that use a local sshd process. Though sshd is practically unusable on Windows CI machines out of the box, so this will need further efforts. Details: - cmake: run sshd fixture test just like autotool did already. - sync tests and their order between autotools and CMake. It makes `test_aa_warmup` the first test with both. - cmake: load test lists from `Makefile.am`. Needed to update the loader to throw away certain lines to keep the converted output conform CMake syntax. Using regexp might be an alternative way of doing this, but couldn't make it work. - cmake: use the official way to configure test environment variables. Switch to syntax that's extendable. - cmake: allow to run the same test both under Docker and sshd fixture. Useful for testing the sshd fixture runner, or how the same test behaves in each fixture. - update test fixture to read the username from `USER` envvar instead of using the Dockfile-specific hardwired one, when running outside Docker. - rework `ssh2.sh` into `sshd_fixture.sh`, to: - allow running any tests (not just `test_ssh2`). - configure Docker tests for running outside Docker. - fixup `SSHD` path when running on Windows (e.g. in AppVeyor CI). Fixes: `sshd re-exec requires execution with an absolute path` - allow overriding `PUBKEY` and `PRIVKEY` envvars. - allow overriding `ssh_config` via `SSHD_FIXTURE_CONFIG`. - prepare support for running multiple tests via sshd_fixture. Add a TAP runner for autotools and extend CMake logic. The TAP runner loads the test list from `Makefile.am`. Notice however that on Windows, `sshd_fixture.sh` is very flaky with GitHub Actions. And consistently broken for subsequent tests in AppVeyor CI: 'libssh2_session_handshake failed (-43): Failed getting banner' Another way to try is a single sshd instance serving all tests. For CMake this would probably mean using an external script. - ed25519 test keys were identical for auth and host. Regenerate the auth keypair to make them distinct. - sync the sshd environment between Docker and sshd_fixture. - use common via `openssh_server/sshd_config`. - accept same auth keys. - offer the same host keys. - sync TrustedUserCAKeys. - delete now unused keypairs: `etc/host*`, `etc/user*`. - bump up startup delay for Windows (randomly, to 5 secs, from 3). - delete `UsePrivilegeSeparation no` to avoid deprecation warnings. `command-line line 0: Deprecated option UsePrivilegeSeparation` - delete `Protocol 2` to avoid deprecation warnings. It has been the default since OpenSSH 3.0 (2001-11-06). - delete `StrictModes no` (CI tests work without it, Docker tests never used it). - bump `Dockerfile` base image to `testing-slim` (from `bullseye-slim`). It needed `sshd_config` updates to keep things working with OpenSSH 9.2 (compared to bullseye's 8.4). - replace `ChallengeResponseAuthentication` alias with `KbdInteractiveAuthentication`. The former is no longer present in default `sshd_config` since OpenSSH 8.7 (2021-08-20). This broke the `Dockerfile` script. The new name is documented since OpenSSH 4.9 (2008-03-31) - add `PubkeyAcceptedKeyTypes +ssh-rsa,ssh-dss,ssh-rsa-cert-v01@openssh.com` and `HostKeyAlgorithms +ssh-rsa`. Original-patch-by: Eric van Gyzen (@vangyzen on github) Fixes #691 There is a new name for `PubkeyAcceptedKeyTypes`: `PubkeyAcceptedAlgorithms`. It requires OpenSSH 8.5 (2021-03-03) and breaks some envs so we're not using it just yet. - drop `rijndael-cbc@lysator.liu.se` tests and references from config. This is a draft alias for `aes256-cbc`. No need to test it twice. Also this alias is no longer recognized by OpenSSH 8.5 (2021-03-03). - update `mansyntax.sh` and `sshd_fixture.sh` to not rely on `srcdir`. Hopefully this works with out-of-tree builds. - fix `test_read_algos.test` to honor CRLF EOLs in their inputs (necessary when running on Windows.) - fix `test_read_algos.test` to honor `EXEEXT`. Might be useful when running tests under cross-builds? - `test_ssh2.c`: - use libssh2 API to set blocking mode. This makes it support all platforms. - adapt socket open timeout logic from `openssh_fixture.c`. Sadly this did not help fix flakiness on GHA Windows. - tests: delete unused C headers and variable initialization. - delete unused test files: `sshd_fixture.sh.in`, `sshdwrap`, `etc/sshd_config`. Ref: cf80f2f4b5255cc85a04ee43b27a29c678c1edb1 - autotools: delete stray `.c` test sources from `EXTRA_DIST` in tests. - `tests/.gitignore`: drop two stray tests. - autotools: fix passing `SSHD` containing space (Windows needs this). - autotools: sort `EXTRA_DIST` in tests. - cmake: fix to add `test_ssh2` to `TEST_TARGETS`. - fix `authorized_key` order in `tests/gen_keys.sh`. - silence shellcheck warning in `ci/checksrc.sh`. - set `SSHD` for autotools on GitHub Actions Windows. [skipped] Auto-detection doesn't work (maybe because sshd is installed via Git for Windows and we're using MSYS2's shell.) It enables running sshd fixture (non-Docker) tests in these jobs. I did not include this in the final patch due to flakiness: ``` Connection to 127.0.0.1:4711 attempt #0 failed: retrying... Connection to 127.0.0.1:4711 attempt #1 failed: retrying... Connection to 127.0.0.1:4711 attempt #2 failed: retrying... Failure establishing SSH session: -43 ``` Can be enabled with: `export SSHD='C:/Program Files/Git/usr/bin/sshd.exe'` Closes #996 - ci: reduce algo test runtime on AppVeyor Make the block count customizable in `test_read` via environment `FIXTURE_XFER_COUNT`. Set the custom count lower than the default when running on AppVeyor. The goal is to reduce CI roundtrip times. Closes #995 GitHub (22 Apr 2023) - [Michael Buckley brought this change] Agent forwarding implementation (#752) This PR contains a series of patches that date back many years and I believe were discussed on the mailing list, but never merged. We have been using these in our local copy of libssh2 without issue since 2015, if not earlier. I believe this is the full set of changes, as we tried to use comments to mark where our copy of libssh2 differs from the canonical version. This also contains changes I made earlier this year, but which were not discussed on the mailing list, to support certificates and FIDO2 keys with agent forwarding. Note that this is not a complete implementation of agent forwarding, as that is outside the scope of libssh2. Clients still need to provide their own implementation that parses ssh-agent methods after calling libssh2_channel_read() and calls the appropriate callback messages in libssh2. See the man page changes in this PR for more details. Integration-patches-by: Viktor Szakats * prefer size_t * prefer unsigned int over u_int in public function * add const * docs, indent, checksrc, debug call, compiler warning fixes Viktor Szakats (21 Apr 2023) - ci: add Windows Server 2016 into the test mix We had Windows Server 2012 R2 (8.1) and Windows Server 2019 (10) before this patch. After, we also have Windows Server 2016 (10). The WinCNG flakey tests should have a better chance when running on the newer OS. This update does not change the compiler mix. Also change the test fixture to not use the `--quiet` option with the `docker pull` commant. This option requires docker v19.03, and AppVeyor's Visual Studio 2017 image doesn't support it. Log output did not change without `--quiet`, so it seems safe to delete it. In case we'd need it, another solution is to retry without `--quiet` if the command fails. docker's exit status is 125 in that case. Ref: https://github.com/libssh2/libssh2/issues/804#issuecomment-1515232799 Ref: https://www.appveyor.com/docs/windows-images-software/ Closes #994 - build: add autotools test_read support and more Keep a single list for mac and crypt algos that we use in both CMake and autotools. Use the same test names across build tools. Use the TAP protocol to track individual tests run from a single shell script. Also: - enable the rest of our tests with autotools. - set `make check` verbose to see errors in case they happen. - silence stray 'command not found' error when running `mansyntax.sh` on Windows. GitHub Actions Windows docker tests disabled due to: ``` Command: docker build --quiet -t libssh2/openssh_server ../tests/openssh_server Error running command 'docker build --quiet -t libssh2/openssh_server ../tests/openssh_server' (exit 1): Sending build context to Docker daemon 22.02kB Step 1/42 : FROM debian:bullseye-slim bullseye-slim: Pulling from library/debian no matching manifest for windows/amd64 10.0.20348 in the manifest list entries Failed to build docker image ``` Closes #993 - cmake: restore a dash char in comment [ci skip] It's a CMake comment header convention. GitHub (21 Apr 2023) - [Dan Fandrich brought this change] tests: add AES-GCM protocol read tests (#992) Closes #992 - [Viktor Szakats brought this change] support encrypt-then-mac (etm) MACs (#987) Support for calculating MAC (message authentication code) on encrypted data instead of plain text data. This adds support for the following MACs: - `hmac-sha1-etm@openssh.com` - `hmac-sha2-256-etm@openssh.com` - `hmac-sha2-512-etm@openssh.com` Integration-patches-by: Viktor Szakats * rebase on master * fix checksec warnings * fix compiler warning * fix indent/whitespace/eol * rebase/manual merge onto AES-GCM patch #797 * more manual merge of `libssh2_transport_send()` based on dfandrich/shellfish Fixes #582 Closes #655 Closes #987 Viktor Szakats (20 Apr 2023) - docs: fix typo in argument name [ci skip] - [Keith Dart brought this change] channel: add support for "signal" message Can send specific signals to remote process. Allows for slightly improved remote process management, if the server supports it. Integration-patches-by: Viktor Szakats * doc updates * change `signame_len` to `size_t` * variable scopes * fix checksrc warnings Closes #672 Closes #991 - crypto: add `LIBSSH2_NO_AES_CBC` option Also rename internal `LIBSSH2_AES` to `LIBSSH2_AES_CBC`. Follow-up to 857e431648df6edcb3e17138d877f2e65d2d769d Closes #990 - tidy-up: indentation fixes [ci skip] GitHub (20 Apr 2023) - [Dan Fandrich brought this change] Add support for AES-GCM crypto protocols (#797) Add support for aes256-gcm@openssh.com and aes128-gcm@openssh.com ciphers, which are the OpenSSH implementations of AES-GCM cryptography. It is similar to RFC5647 but has changes to the MAC protocol negotiation. These are implemented for recent versions of OpenSSL only. The ciphers work differently than most previous ones in two big areas: the cipher includes its own integrated MAC, and the packet length field in the SSH frame is left unencrypted. The code changes necessary are gated by flags in the LIBSSH2_CRYPT_METHOD configuration structure. These differences mean that both the first and last parts of a block require special handling during encryption. The first part is where the packet length field is, which must be kept out of the encryption path but in the authenticated part (as AAD). The last part is where the Authentication Tag is found, which is calculated and appended during encryption or removed and validated on decryption. As encryption/ decryption is performed on each packet in a loop, one block at a time, flags indicating when the first and last blocks are being processed are passed down to the encryption layers. The strict block-by-block encryption that occurs with other protocols is inappropriate for AES-GCM, since the packet length shifts the first encrypted byte 4 bytes into the block. Additionally, the final part of the block must contain the AES-GCM's Authentication Tag, so it must be presented to the lower encryption layer whole. These requirements mean added code to consolidate blocks as they are passed down. When AES-GCM is negotiated as the cipher, its built-in MAC is automatically used as the SSH MAC so further MAC negotiation is not necessary. The SSH negotiation is skipped when _libssh2_mac_override() indicates that such a cipher is in use. The virtual MAC configuration block mac_method_hmac_aesgcm is then used as the MAC placeholder. This work was sponsored by Anders Borum. Integration-patches-by: Viktor Szakats * fix checksrc errors * fix openssl.c warning * fix transport.c warnings * switch to `LIBSSH2_MIN/MAX()` from `MIN()`/`MAX()` * fix indent * fix libgcrypt unused warning * fix mbedtls unused warning * fix wincng unused warning * fix old openssl unused variable warnings * delete blank lines * updates to help merging with the ETM patch Viktor Szakats (20 Apr 2023) - tidy-up: align comments [ci skip] - tidy-up: whitespace nits [ci skip] - crypto: add/fix algo guards and extend `NO` options Add new guard `LIBSSH2_RSA_SHA1`. Add missing guards for `LIBSSH2_RSA`, `LIBSSH2_DSA`. Fix warnings when all options are disabled. This is still not complete and it's possible to break a build with certain crypto backends (e.g. mbedTLS) and/or combination of options. It's not guaranteed that all bits everywhere get disabled by these settings. Consider this a "best effort". Add these new options to disable certain crypto elements: - `LIBSSH2_NO_3DES` - `LIBSSH2_NO_AES_CTR` - `LIBSSH2_NO_BLOWFISH` - `LIBSSH2_NO_CAST` - `LIBSSH2_NO_ECDSA` - `LIBSSH2_NO_RC4` - `LIBSSH2_NO_RSA_SHA1` - `LIBSSH2_NO_RSA` The goal is to offer a way to disable legacy/obsolete/insecure ones. See also: 146a25a06dd2365a4330dad34fefcdcee1a206aa `LIBSSH2_NO_HMAC_RIPEMD` See also: 38015f4e46d8dbeea522dc7ee664522d4f47fc75 `LIBSSH2_NO_DSA` See also: be31457f3071686b555a0f0b19e5dcf63d67fc27 `LIBSSH2_NO_MD5` Closes #986 - scp: fix typo in comments [ci skip] Follow-up to 0a500b3554c29451708353279eefce750f4bca6c - base64: do not use `snprintf()` on encoding This also significantly (by 7-8x in my limited tests with a short string) speeds up this function. The impact is still minor as this function is only used in `knownhost.c` in release builds. Closes #985 - wincng: constify data arg of `libssh2_wincng_hash()` Tested in #979 - wincng: fix unused variables with `LIBSSH2_RSA_SHA2` disabled Tested in #979 - ci: delete config elements for unused 32-bit Linux builds They have been disabled since d9b4222ef1c5ab9b9e499fe6234556e5cca7c4fe Tested in #979 - ci: enable FIXTURE_TRACE_ALL_CONNECT for WinCNG tests To hopefully help finding the WinCNG hostkey verification intermittent failure #804. Tested in #979 - tests: add `FIXTURE_TRACE_ALL_CONNECT` option Works like the `FIXTURE_TRACE_ALL` envvar, but enables full trace for the connection phase only. Also fix a possible NULL deref with `FIXTURE_TRACE_ALL` and a failed `libssh2_session_init_ex()`. Tested in #979 - ci: really enable logging in AppVeyor CMake builds `CONFIGURATION` was never passed to the cmake command, so it had never enabled logging when set to `Debug`. Also `CONFIGURATION` is ambiguous depending on the "generator" used by CMake. In case of Visual Studio, this is a build/ctest-time setting, not a cmake-config parameter. So set this permanently to `Release` and enable logging via our dedicated CMake option `ENABLE_DEBUG_LOGGING`. Tested in #979 - HACKING-CRYPTO: fix stray whitespace - tidy-up: fix more nits - fix indentation errors. - reformat `cmake/FindmbedTLS.cmake` - replace a macro with a variable in `example/sftp_RW_nonblock.c`. - delete macOS macro `_DARWIN_USE_64_BIT_INODE` from the OS/400 config header, `os400/libssh2_config.h`. - fix other minor nits. Closes #983 - mansyntax: make it work on macOS, check reqs locally - use `gman` alias if present. This makes it work when the correct `man` command is provided via `brew` on macOS. - move CMake attempts to detect tools necessary to run `mansyntax.sh` into the script itself. - delete CMake TODO to move more test logic into CMake. This would make it CMake-specific and require maintaining it separately for each build tool. Just use our external script when a POSIX shell is available. Closes #982 - cmake: dedupe setting `-DHAVE_CONFIG_H` Move `libssh2_config.h` generation and setting `-DHAVE_CONFIG_H` to the root `CMakeFile.txt`. Also move symbol hiding setup there. It needs to be done before generating the config file for `LIBSSH2_API` value to be set in it. After this change the `HIDE_SYMBOLS` setting is accepted without an annoying CMake warning when not actually building a shared libssh2 lib. Closes #981 - build: assume non-blocking I/O on Windows Drop checks from Windows builds and enable it based on `WIN32`. This saves detection time and also makes 3rd party builds simpler. Also: - delete `HAVE_DISABLED_NONBLOCKING`, that we used in build tools to explicitly disable an explicit `#error` in `session.c`. - replace existing `WSAEWOULDBLOCK` check for Windows support with `WIN32`. Cleaner with the same result. Follow-up to f1e80d8d8ce9570d81836da96ba02f4d4552a7b3 Follow-up to 5644eea2161b17f7c16e18f3a10465ebb217ca1f Closes #980 - ci: rename Logging to Debug in AppVeyor - switch to internal base64 decode that uses size_t Make the public `libssh2_base64_decode()` a wrapper for that. Bump up length sizes in callers. Also fix output size calculation to first divide then multiply. Closes #978 - tests: switch to debian:bullseye-slim in Dockerfile 'slim' provides all we need, with less bloat. Tested in #976 Follow-up to 78cb64a85955f2cd9700c4fbad3f02d589dd7169 - tests: build improvements and more - rename tests to have more succint names and a more useful natural order. - rename `simple` and `ssh2` in tests to have the `test_` prefix. This avoids a name collisions with `ssh2` in examples. - cmake: drop the `example-` prefix for generated examples. Bringing their names in sync with other build tools, like autotools. - move common auth test code into the fixture and simplify tests by using that. - move feature guards from CMake to preprocessor for auth tests. Now it works with all build tools and it's easier to keep it in sync with the lib itself. For this we need to include `libssh2_priv.h` in tests, which in turn needs tweaking on the trick we use to suppress extra MSVS warnings when building tests and examples. - move mbedTLS blocklist for crypto tests from CMake to the test fixture. - add ed25519 hostkey tests to `test_hostkey` and `test_hostkey_hash`. - add shell script to regenerate all test keys used for our tests. - alpha-sort tests. - rename `signed_*` keys to begin with `key` like the rest of the keys do. - whitespace fixes. Closes #969 - autotools: rename a variable To match its counterpart we use for clang and to better match the original code in curl. Follow-up to ec0feae7920d695ce234a5aba13014bf29824c09 Closes #977 - ssh2.sh: revert likely wrong quoting [ci skip] Follow-up to 50124428509ffc2f5d08d8d3c152fa36546c9a75 - build: add `-Wbad-function-cast` picky warning Also adjust minimum gcc versions in comment. Closes #975 - tests: restore debian:bullseye in Dockerfile Follow-up to 78cb64a85955f2cd9700c4fbad3f02d589dd7169 - session: simplify preprocessor logic - by using #elif - by merging two blocks Closes #972 - tests: try debian:testing for Dockerfile Follow-up to 78cb64a85955f2cd9700c4fbad3f02d589dd7169 - src: add and use `LIBSSH2_MIN/MAX` macros Also for #797 Closes #974 - tests: switch Dockerfile to debian:testing-slim From debian:bullseye - doesn't need manual bumps. - is ahead of stable and should be stable enough for our purpose. - slim is saving resources. Closes #971 - cmake: optimize non-blocking tests on WIN32/non-WIN32 Skip testing unixy methods on Windows and vice versa. I continue to assume that CMake doesn't define `WIN32` with Cygwin (as Cygwin doesn't define `_WIN32`/`WIN32` for C), though I haven't tested this. Closes #970 GitHub (15 Apr 2023) - [Jörgen Sigvardsson brought this change] scp: option to not quote paths (#803) A new flag named `LIBSSH2_FLAG_QUOTE_PATHS` has been added, to make libssh2 not quote file paths sent to the remote's scp subsystem. Some custom ssh daemons cannot handle quoted paths, and this makes this flag useful. Authored-by: Jörgen Sigvardsson Viktor Szakats (15 Apr 2023) - cmake: make Windows builds initialize faster By skipping unixy header checks that always fail with the MSVC toolchain or all Windows toolchains. Closes #968 - cmake: use a single build rule for all tests - use the complete filename of test sources in the input list. - build all tests with the ability to access libssh2 internals. This is necessary for `test_keyboard_interactive_auth_info_request` now and might be necessary for others in the future, e.g. to avoid the depreacted public base64 decoding API. - move `test_keyboard_interactive_auth_info_request` into the main test build loop. - move `simple` into the main test build loop too. - build `ssh2` also in static mode. - cleanup the way we detect and enable gcov. - fix indentation. Closes #967 - tidy-up: more whitespace in src Closes #966 - checksrc: fix `EQUALSNULL` warnings `s/([a-z0-9._>*-]+) == NULL/!\1/g` Closes #964 - Makefile.am: add new OS400 header [ci skip] Follow-up to 6dc42e9d625deb816a051d312d09e68926959e78 - checksrc: fix `NOTEQUALSZERO` warnings Closes #963 - checksrc: fix `SIZEOFNOPAREN` warnings `s/sizeof ([a-z0-9._>*-]+)/sizeof(\1)/g` Closes #962 - crypto: add `LIBSSH2_NO_HMAC_RIPEMD` option See also: 38015f4e46d8dbeea522dc7ee664522d4f47fc75 See also: be31457f3071686b555a0f0b19e5dcf63d67fc27 Ref: https://github.com/stribika/stribika.github.io/issues/46 Closes #965 - tidy-up: example, tests continued - fix skip auth if `userauthlist` is NULL. Closes #836 (Reported-by: @sudipm-mukherjee on github) - fix most silenced `checksrc` warnings. - sync examples/tests code between each other. (output messages, error handling, declaration order, comments) - stop including unnecessary headers. - always deinitialize in case of error. - drop some redundant variables. - add error handling where missing. - show more error codes. - switch `perror()` to `fprintf()`. - fix some `printf()`s to be `fprintf()`. - formatting. Closes #960 - src: fix indentation of macro definitions (follow-up) Follow-up to d5438f4ba9036e8028f35258dd1ab97cc2edb37c - src: fix indentation of macro definitions And some comment cleanup. Closes #958 - example/ssh2_exec: drop conditional code for deprecated API GitHub (13 Apr 2023) - [monnerat brought this change] Make OS/400 implementation work again (#953) * os400: support QADRT development files in a non-standard directory This enables the possibility to compile libssh2 even if the ascii runtime development files are not installed system-wide. * userauth_kbd_packet: fix a pointer target type mismatch. A temporary variable matching the parameter type is used before copying to the real target and checking for overflow (that should not occur!). * os400qc3: move and fix big number procedures A bug added by a previous code style cleaning is fixed. _libssh2_random() now checks and return the success status. * os400qc3: fix cipher definition block lengths They were wrongly set to the key size. * Diffie-Hellman min/max modulus sizes are dependent of crypto-backend In particular, os400qc3 limits the maximum group size to 2048-bits. Move definitions of these parameters to crypto backend header files. * kex: return an error if Diffie-Hellman key pair generation fails * os400: add an ascii assert.h header file * os400qc3: implement RSA SHA2 256/512 Viktor Szakats (13 Apr 2023) - sftp: add open functions with custom attribute support Before this patch, libssh2 sent hardcoded `LIBSSH2_SFTP_ATTRIBUTES` struct on handle open. This can be problematic on some special OS, where the file size should be known on new file creation. I added two new functions to resolve this issue. Patch-by: @vajdaakos on github via #506 Changes compared to #506: - drop attr size fixup in favour of #946. - move `memcpy()` under the state where we need it. - bump filename length type to `size_t`. - fix filenames in documentation and other nits. Closes #506 Closes #947 - build: speed up and extend picky compiler options Implement picky warnings with clang in autotools. Extend picky gcc warnings, sync them between build tools and compilers and greatly speed up detection in CMake. - autotools: enable clang compiler warnings with `--enable-debug`. - autotools: enable more gcc compiler warnings with `--enable-debug`. - autotools/cmake: sync compiler warning options between gcc and clang. - sync compiler warning options between autotools and cmake. - cmake: reduce option-checks to speed up the detection phase. Bring them down to 3 (from 35). Leaving some checks to keep the CMake logic alive and for an easy way to add new options. clang 3.0 (2011-11-29) and gcc 2.95 (1999-07-31) now required. - autotools logic copied from curl, with these differences: - delete `-Wimplicit-fallthrough=4` due to a false positive. - reduce `-Wformat-truncation=2` to `1` due to a false positive. - simplify MinGW detection for `-Wno-pedantic-ms-format`. - cmake: show enabled picky compiler options (like autotools). - cmake: do compile `tests/simple.c` and `tests/ssh2.c`. - fix new compiler warnings. - `tests/CMakeLists.txt`: fix indentation. Original source of autotools logic: - https://github.com/curl/curl/blob/a8fbdb461cecbfe1ac6ecc5d8f6cf181e1507da8/acinclude.m4 - https://github.com/curl/curl/blob/a8fbdb461cecbfe1ac6ecc5d8f6cf181e1507da8/m4/curl-compilers.m4 Notice that the autotools implementation considers Apple clang as legacy clang 3.7. CMake detection works more accurately, at the same time more error-prone and difficult to update due to the sparsely documented nature of Apple clang option evolution. Closes #952 - include: delete leading underscore from macro name It can cause compiler warnings in 3rd-party code. Follow-up to 59666e03f04927e5fe3e8d8772d40729f63c570e Closes #957 - ci: use OpenSSL 3 on AppVeyor VS2022 images Closes #954 - build: be friendly with 3rd-party build tools After recent build changes, 3rd party build that took the list of C source to compile them as-is, stopped working as expected, due to `blowfish.c` and crypto-backend C sources no longer expected to compile separately but via `bcrypt_pbkdf.c` and `crypto.c`, respectively. This patch ensures that compiling these files directly result in an empty object instead of redundant code and duplicated symbols. Also: - add a compile-time error if none of the supported crypto backends are enabled. - fix `libssh2_crypto_engine()` for wolfSSL and os400qc3. Rearrange code to avoid a hard-to-find copy of crypto-backend selection guards. Follow-up to 4f0f4bff5a92dce6a6cd7a5600a8ee5660402c3f Follow-up to ff3c774e03585252b70a9ee0fcf254de7b14a767 Closes #951 - sftp: calculate attr size based on attr content in `sftp_open()` Improve robustness by replacing constant argument of `sftp_attrsize()` in `sftp_open()` with the actual `flag` value read from the `attr` we plan to transfer. Restores state of this before 37624b61e3ec4aa65a608800613d00b55ced56d7. Prerequisite for #947, #506. Also improve readability a bit and link to SFTP specs. Delete comment about version 6: The latest spec no longer features the mentioned "DO NOT IMPLEMENT" notice. Closes #946 - man: fixups - add missing `.fi` tags. - fix misplaced `.nf` tags. - add `.nf`/`.fi` tags `SYNOPSIS` where missing. - fix missing/wrong function name from `SH NAME`. - fix wrong function name in `TH`. - keep return values in a separate line. - indent. - fold long lines. - deleted `libssh2_channel_direct_streamlocal()`, there is no such function. - add missing types. - add missing headers. Closes #949 - include: indentation fixes - tidy-up: misc & minor cmake MSVS fix - `libssh2.rc`: document language/codepage codes. Ref: https://learn.microsoft.com/windows/win32/intl/code-page-identifiers - convert to Markdown: `docs/BINDINGS`, `docs/HACKING` Blind update for `vms/libssh2_make_help.dcl`. Please double-check. - cmake: fix to recognize dash-style warning options (`-Wn`) with MSVC. - `NMakefile`: sync `rd` command with `Makefile.mk`. - delete a CVS header. - cmake: simplify a `LIBSSH2_HAVE_ZLIB` macro. - few other nits and whitespace mods. Closes #943 GitHub (10 Apr 2023) - [Viktor Szakats brought this change] Support for direct-streamlocal@openssh.com UNIX socket connection (#945) This patch allow to use direct-streamlocal service from OpenSSH 6.7, that allows UNIX socket connections. Mods: - delete unrelated condition: Ref: https://github.com/libssh2/libssh2/pull/216#discussion_r374748111 - rebase on master, whitespace updates. Patch-by: @gjalves Gustavo Junior Alves Closes #216 Closes #632 Closes #945 Viktor Szakats (10 Apr 2023) - build: support `libssh2.rc` with autotools Caveat: When building `--enable-static` and `--enable-shared` at the same time, the compiled Windows resource is also included in the static library. This appears to be an autotools limitation, with no way to have different input lists (or different custom options) for shared and static libraries, even though it builds them separately. The workaround is to build static libraries in a separate `./configure` + `make` pass. Closes #944 - crypto: add `LIBSSH2_NO_DSA` to disable DSA support See also: be31457f3071686b555a0f0b19e5dcf63d67fc27 Closes #942 - build: unify source lists - introduce `src/crypto.c` as an umbrella source that does nothing else than include the selected crypto backend source. Moving this job from the built-tool to the C preprocessor. - this allows dropping the various techniques to pick the correct crypto backend sources in autotools, CMake and other build method. Including the per-backend `Makefile..inc` makefiles. - copy a trick from curl and instead of maintaining duplicate source lists for CMake, convert the GNU Makefile kept for autotools automatically. Do this in `docs`, `examples` and `src`. Ref: https://github.com/curl/curl/blob/dfabe8bca218d2524af052bd551aa87e13b8a10b/CMakeLists.txt#L1399-L1413 Also fixes missing `libssh2_setup.h` from `src/CMakeFiles.txt` after 59666e03f04927e5fe3e8d8772d40729f63c570e. - move `Makefile.inc` from root to `src`. - reformat `src/Makefile.inc` to list each source in separate lines, re-align the continuation character and sort the lists alphabetically. - update `docs/HACKING-CRYPTO` accordingly. - autotools: update the way we add crypto-backends to `LIBS`. - delete old CSV headers, indent, and merge two lines in `docs/Makefile.am` and `src/Makefile.am`. - add `libssh2.pc` to `.gitignore`, while there. Closes #941 GitHub (9 Apr 2023) - [Zenju brought this change] sftp: always clear protocol error (#787) Viktor Szakats (9 Apr 2023) - cmake: add `HIDE_SYMBOLS` option & do symbol hiding on *nix - implement symbol hiding on non-Windows platforms. The essence of the detection logic was copied from: https://github.com/curl/curl/blob/dfabe8bca218d2524af052bd551aa87e13b8a10b/CMake/CurlSymbolHiding.cmake Then simplified and shortened. This method doesn't require a recent CMake version, nor an external, auto-generated C header. Move `configure_file()` after `set(LIBSSH2_API ...)`, for the config file to pick up `LIBSSH2_API`s value. Closes #602 - add CMake option `HIDE_SYMBOLS`. This setting means to hide non-public functions from the libssh2 dynamic library when set to `ON`. The default. When set to `OFF`, make all non-static/internal functions visible in the dynamic library. This setting requires `BUILD_SHARED_LIBS=ON`. - honor this setting on Windows. By setting the `LIBSSH2_EXPORTS` manual macro again, and stop recognizing the automatic CMake macro for this purpose: `libssh2_shared_EXPORT`. Closes #939 - build: make `windows.h` even leaner Disable GDI and NLS features in `windows.h`. libssh2 doesn't use these. Closes #940 - blowfish: build improvements - include `blowfish.c` into `bcrypt_pbkdf.c`, instead of compiling it as a distinct object. - make low-level blowfish functions static. This prevents this symbols to pollute the public namespace of libssh2. It also allows the compiler to inline these functions. - integrate `blf.h` header into `bcrypt_pbkdf.c` as well. - use `_DEBUG_BLOWFISH` instead of `#if 0`. - fix `_DEBUG_BLOWFISH` compiler warnings and other nits. - `#undef` `inline` before redefining it in `libssh2_priv.h`. (copied from `blowfish.c`) - delete unused `inline` redefinitions from `blowfish.c`. - disable unused low-level blowfish functions. - formatting, header order. Closes #938 - libssh2.rc: fix debug flag, other cleanups - fix to use `LIBSSH2DEBUG` macro to set the debug flag. (was `DEBUGBUILD`, a curl-specific macro) - use manifest constants instead of literals - change language to neutral Closes #937 - tidy-up: example, tests - drop unnecessary `WIN32`-specific branches. - add `static`. - sync header inclusion order. - sync some common code between examples/tests. - fix formatting/indentation. - fix some `checksrc` errors not caught by `checksrc`. Closes #936 - tests/mansyntax.sh: avoid `if !` for portability Ref: https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Limitations-of-Builtins.html#Limitations-of-Builtins Fixes #704 Closes #935 - tidy-up: indentation in guarded #includes [ci skip] - Makefile.mk: drop `PROOT` variable [ci skip] - build: hand-crafted config rework & header tidy-up - introduce the concept of a project level setup header `src/libssh2_setup.h`, that is used by `src`, `example` and `tests` alike. Move there all common platform/compiler configuration from `src/libssh2_priv.h`, individual sources and `CMakeFiles.txt` files. Also move there our hand-crafted (= not auto-generated by CMake or autotools) configuration `win32/libssh2-config.h`. - `win32` directory is empty now, delete it. - `Makefile.mk`: adapt to the above. Build-directory is the target triplet, or any custom name set via `BLD_DIR`. - sync header path order between build systems: build/src -> source/src -> source/include - delete redundant references to `windows.h`, `winsock2.h`, `ws2tcpip.h`. - delete unnecessary #includes, update order (`libssh2_setup.h` first, `winsock2.h` first), simplify where possible. This makes the code warning-free without `WIN32_LEAN_AND_MEAN`. At the same time this patch applies this macro globally, to avoid header bloat. - example: add missing *nix header guards. - example: fix misindented `HAVE_UNISTD_H` `#ifdef`s. - set `WIN32` with all build-tools. - set `HAVE_SYS_PARAM_H` in the hand-crafted config for MinGW. To match auto-detection. - move a source-specific macro to `misc.c` from `libssh2_priv.h`. See the PR's individual commits for step-by-step updates. Closes #932 - Makefile.mk: build tests and other improvements [ci skip] - use `example` target for building examples (was: `test`). - add support for building tests via the `test` target. - accept lib-only options in a new `LIBSSH2_CPPFLAGS_LIB` variable. Useful to pass `-DLIBSSH2_EXPORTS` for correct `dllexport` in `libssh2.dll`. - fix to put dynamic library in lib directory for non-Windows builds - fix to not delete lib objects on `testclean` - test_warmup: re-implement as `test()` Instead of overriding `main()`. To align with the other tests. Overriding `main()` can cause duplicate symbols without using a lib for the `runner` code. Follow-up to 40ac6b230a309d35c57aa65a8f6d7ab6654aa3d8 Closes #934 - NMakefile: drop `/DEBUG` linker option in release mode [ci skip] - NMakefile: simplify [ci skip] - Makefile.mk: merge two rules [ci skip] - TODO: update item about compiler warnings [ci skip] Follow-up to 08354e0abbe86d4cc5088d210d53531be6d8981a Follow-up to 29347905721d2e7fbb97dabfb0071bee51db3013 Follow-up to 5a96f494ee0b00282afb2db2e091246fc5e1774a Follow-up to 463449fb9ee7dbe5fbe71a28494579a9a6890d6d Follow-up to 02f2700a61157ce5a264319bdb80754c92a40a24 GitHub (5 Apr 2023) - [ihsinme brought this change] example/x11: Add null-termination (#749) Viktor Szakats (5 Apr 2023) - crypto: fix `LIBSSH2_NO_MD5` compiler warnings Follow-up to be31457f3071686b555a0f0b19e5dcf63d67fc27 Closes #933 - build: add new man pages Follow-up to c20c81ab105cdf27f5a4e2604bd13085f46e21de GitHub (5 Apr 2023) - [Daniel Silverstone brought this change] Configurable session read timeout (#892) This set of changes provides a mechanism to runtime-configure the previously #define'd timeout for reading packets from a session. The intention here is to also extend libcurl to be able to use this interface so that when fetching from sftp servers which are very slow to return directory listings, connections do not time-out so much. * Add new field to session to hold configurable read timeout * Updated `_libssh2_packet_require()`, `_libssh2_packet_requirev()`, and `sftp_packet_requirev()` to use new field in session structure * Updated docs for API functions to set/get read timeout field in session structure * Updated `libssh2.h` to declare the get/set read timeout functions Co-authored-by: Jon Axtell Credit: Daniel Silverstone Viktor Szakats (4 Apr 2023) - cmake: whitespace fixes [ci skip] - libssh2.h: bump LIBSSH2_COPYRIGHT year [ci skip] - Makefile.mk: move portable GNU Make file to the root Move the GNU Make file formerly known as `win32/GNUmakefile` to the root directory from `win32`. It now supports any platform with a GCC-like toolchain, while also keeping support for win32. For non-Windows platforms it's necessary to provide a hand-crafted `libssh2_config.h` header for now. Usage: `make -f Makefile.mk` - src: include `limits.h` for `*_MAX` macros Follow-up to 5a96f494ee0b00282afb2db2e091246fc5e1774a Reported-by: OldWorldOrdr on github Fixes #928 Closes #930 - build: MSVS warning suppression option tidy-up - in `win32/libssh2_config.h` replace `_CRT_SECURE_NO_DEPRECATE` with `_CRT_SECURE_NO_WARNINGS`, to use the official macro for this, like in CMake. Also, it's now safe to move it back under `_MSC_VER`. Suppressing: `warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.` `warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead.` - move `_CRT_NONSTDC_NO_DEPRECATE` to `example` and `tests`. Not needed for `src`. Suppressing: `warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _strdup.` `warning C4996: 'write': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _write.` - move `_WINSOCK_DEPRECATED_NO_WARNINGS` from source files to CMake files, in `example` and `tests`. Also limit this to MSVC. Suppressing: `warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead` TODO: try fixing these instead of suppressing. Closes #929 - win32/GNUmakefile: make it movable [ci skip] - add `BLD_DIR` to customize the output directory (where libs, .zip, obj subdir will go). This directory must exist. It remains `./win32` for Windows builds. - add `CONFIG_H_DIR` option to customize `libssh2_config.h` location. It remains `./win32` for Windows builds. - include `.def` in distro zip for Windows. - ready to move to the root directory. - win32/GNUmakefile: drop an unnecessary variable [ci skip] - windows: re-add `libssh2.rc` Lost while moving it from the win32 directory Follow-up to 194cfc0f84192809c87f846140e5bf06b7a864af - crypto: add `LIBSSH2_NO_MD5` to disable MD5 support Closes #927 - hostkey: fix `hash_len` field constants Replace incorrect `MD5_DIGEST_LENGTH` with `SHA_DIGEST_LENGTH` for these hostkey algos: - `ssh-rsa` and `ssh-dss` Ref: 7a5ffc8cee259bbde82ab92515cd8fea2166854b (2004-12-07 Initial) - `ssh-rsa-cert-v01@openssh.com` Ref: 4b21e49d9d2db74579b18804ed1f5eeb16578b2f (2022-07-28) Ref: #710 Also delete local fall-back definition of `MD5_DIGEST_LENGTH` (added in 9af7eb48dc3854ce8ee0589f7e2beb944e064847). Macro is no longer used. Reported-by: Markus-Schmidt on github Fixes #919 Closes #926 - ci: add MSVS 2008/2010 build tests and fix warnings Also: - fix newly surfaced (bogus) warnings in examples with MSVS 2010: ``` ..\..\example\direct_tcpip.c(262): warning C4127: conditional expression is constant ``` Happens for every `FD_SET()` macro reference. Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46677835/job/ni4hs97bh18c14ap - silence MSVS 2010 predefined Windows macro warnings: ``` ..\..\src\wincng.c(867): warning C4306: 'type cast' : conversion from 'int' to 'LPCSTR' of greater size ..\..\src\wincng.c(897): warning C4306: 'type cast' : conversion from 'int' to 'LPCSTR' of greater size ..\..\src\wincng.c(1132): warning C4306: 'type cast' : conversion from 'int' to 'LPCSTR' of greater size ``` Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46678071/job/08t5ktvkcgdghp7r Closes #925 - transport: rename local `RANDOM_PADDING` macro Rename `RANDOM_PADDING` macro used internally to enable some code. Committed in the initial version of `transport.c` in 9d55db6501aa4e21f0858cf36cdc2ddc11b96e83 (2007-02-02). libssh2 code never defined it. The name happens to collide with a Windows macro in `wincrypt.h`. `transport.c` doesn't include this header, but it includes `winsock2.h`, and it turns out it can also define this macro in some cases, e.g. when `WIN32_LEAN_AND_MEAN` is not set. To be on the safe side, prefix the name with `LIBSSH2_` to avoid enabling it by accident. Q: Maybe it'd be best to delete it with the guarded code? Reported-by: Markus-Schmidt on github Fixes #921 Closes #924 - windows: move `libssh2.rc` to the `src` directory Closes #918 - autotools: delete unused conditional `HAVE_SYS_UN_H` No longer necessary after moving the disabling/enabling logic from build tool to `example/x11.c`. Reverts 4774d500e724bc4e548f743a0cb644ab05599474 Follow-up to d245c66cc0029e480674394c23e8be1c9410f7ad - win32/GNUmakefile: update help & exit without crypto backend [ci skip] Follow-up to: 5bcd25c4c980e9765c00a2f20ac5348635063aad Follow-up to: 68fd02fba002c8c6af3ba51a2780de46b47b3787 - build: respect autotools `DLL_EXPORT` in `libssh2.h` The `DLL_EXPORT` macro is automatically set by autotools when building the libssh2 DLL. Certain toolchains might require this to correctly export symbols, so make sure to respect it in `libssh2.h` to enable `declspec(dllexport)`. With this patch we have a manual macro for that (`LIBSSH2_EXPORT`), this autotools one, the CMake one, and `_WINDLL` (added in c355d31ff94a1622526c4988b9d09074f7f7605d), possibly defined by Visual Studio. Closes #917 - build: make `HAVE_LIBCRYPT32` local to `wincng.c` libssh2 uses `wincrypt.h` aka the `crypt32` Windows system library for the function `CryptDecodeObjectEx()` [1]. This function has been available for Win32 (and UWP/WinRT apps) for a long while. Even old MinGW supports it, and also Watcom 1.9, of the rare/old compilers I checked. CMake had it permanently enabled, while it also did an extra check for the header to add the lib to the lib list. Autotools did the detection proper. Other builds had it permanently enabled. It seems safe to assume this function/header/lib is available in all environments we support. In this patch we simplify by deleting these detections and feature flags from all build tools. Keep the feature flag internal to `wincng.h`, and for extra safety add the new macro `LIBSSH2_WINCNG_DISABLE_WINCRYPT` do disable it via custom `CPPFLAGS`. WinCNG's other requirement is `bcrypt`. That also has been universally available for a long time. Here the only known outlier is old/legacy MinGW, which is missing support. [1] https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptdecodeobjectex Closes #916 - autotools: delete `src/libssh2.pc.in` reference [ci skip] Follow-up to 06f281921907fa077884c7020917661ca805b9d3 - tidy-up: null-mac/cipher documentation Move documentation for these deleted build-level options from autotools/cmake docs to the source code itself. Follow-up to 50c9bf868e833258d23c5f55ed546d1fcd5687d0 Closes #915 - cmake: re-use existing `libssh2.pc` template Instead of maintaining a second copy of `libssh2.pc.in` in `src` just for CMake, teach CMake to use the existing template in the root dir, that we already use with autotools. Closes #914 - delete redundant `HAVE_STDLIB_H` libssh2 used this standard C89 header unconditionally before this patch. Delete the feature checks and all unnecessary header guards. Closes #913 - NMakefile: drop redundant variable and assignments [ci skip] - delete redundant `HAVE_WINSOCK2_H` `libssh2.h` required `winsock2.h` for `_WIN32` since 81d53de4dc5ee39bd6215958c7dce3b12731195e (2011-06-04). Apply that to the whole codebase. This makes it unnecessary to detect `HAVE_WINSOCK2_H` and allows to drop all its uses. Completes TODO from b66d7317ca6c882afbe52fe426f68c119c40d348 TODO: Straighten out the use a mixture of `HAVE_WINDOWS_H`, `WIN32`, `_WIN32` to detect Windows. - cmake: detect WinCNG last This gives a chance to auto-detect mbedTLS on Windows with CMake. - NMakefile: rename config variables, default to WinCNG [ci skip] - replace `OPENSSLINC` and `OPENSSLLIB` with `OPENSSL_PATH`. Assume `include` and `lib` subdirs for headers and libs. - replace `WITH_ZLIB`, `ZLIBINC` and `ZLIBLIB` with `ZLIB_PATH`. Assume `include` and `lib` subdirs for header and lib. - make WinCNG the default if `WITH_OPENSSL` is not set. - win32/GNUmakefile: rename object dir and update .gitignore [ci skip] From `-{release|debug}` to `{release|debug}-`. Follow-up to 68fd02fba002c8c6af3ba51a2780de46b47b3787 - win32/GNUmakefile: add libgcrypt support [ci skip] In the previous commit 969487113aae856e43d3d905c3f2260246d44f9b, the commit message should read `win32/GNUmakefile: ` instead of `libssh2-gnumake.sh: `. Sorry for the mixup. - libssh2-gnumake.sh: make variable names platform-agnostic [ci skip] Also more consistent. Refer to DLL/SO/shared as 'dyn'. Also add comment on how to find customizable environment variables. - win32/GNUmakefile: make it support non-Windows builds [ci skip] With 20-ish extra lines, make this Makefile support all GCC-like toolchains. The temporary directory becomes `-{release|debug}` from the former `{release|debug}`. Also change the lib directory name in the `dist` package from `win32` to `lib`, to match other packages and build tools. - win32/GNUmakefile: default to WinCNG [ci skip] Also check for wolfSSL before mbedTLS to match CMake. - win32/GNUmakefile: fixups to previous commit [ci skip] - `-lws2_32` is necessary when building examples. - drop a temporary variable. Follow-up to d245c66cc0029e480674394c23e8be1c9410f7ad - delete redundant `HAVE_WS2TCPIP_H` It was used once in `src/libssh2_priv.h`, but without any effect. The header included `ws2tcpip.h` twice, once guarded by `HAVE_WS2TCPIP_H` and another time by `HAVE_WINSOCK2_H`. Dedupe these to not use `HAVE_WS2TCPIP_H`. Then delete detection of this feature from all build methods. TODO: Replace `HAVE_WINSOCK2_H` with `_WIN32`/`WIN32`. - win32/libssh2_config.h: set `HAVE_LONGLONG` & `HAVE_STDLIB_H` [ci skip] - enable `HAVE_LONGLONG` for MinGW and MSVC versions supporting it. Necessary for `GNUmakefile`/`NMakefile` builds to create the same binaries as CMake/autotools ones do. - enable `HAVE_STDLIB_H`. It has been universally available on Windows for a long time. Fixes these clang-cl warnings: ``` src\wincng.c(444,5) : warning: implicit declaration of function 'free' is invalid in C99 [-Wimplicit-function-declaration] free(buf); ^ src\wincng.c(491,20) : warning: implicitly declaring library function 'malloc' with type 'void *(unsigned long long)' [-Wimplicit-function-declaration] pbHashObject = malloc(dwHashObject); ^ src\wincng.c(491,20) : note: include the header or explicitly provide a declaration for 'malloc' src\wincng.c(2106,14) : warning: implicitly declaring library function 'realloc' with type 'void *(void *, unsigned long long)' [-Wimplicit-function-declaration] bignum = realloc(bn->bignum, length); ^ src\wincng.c(2106,14) : note: include the header or explicitly provide a declaration for 'realloc' 3 warnings generated. ``` - example: make `x11` exclusion build-tool-agnostic Whether to build the `x11` example or not was decided by each build tool. CMake didn't build it even on supported platforms. GNUMakefile used a specific blocklist for it, while autotools enabled it based on feature-detection. Migrate the enabler logic to an #ifdef in source and build `x11` unconditionally with all build tools. On unsupported platforms (=Windows) this program now displays a short message stating that fact. Also: - fix `x11.c` warnings uncovered after CMake started building it. - use `libssh2_socket_t` type for portability in `x11.c` too. - use detected header guards in `x11.c`. - delete a duplicate reference to `-lws2_32` from `win32/GNUmakefile` while there. Closes #909 - .gitignore updates [ci skip] - tidy-up: whitespace, sorting, comment and naming fixups - cmake: add missing man pages - cmake: dedupe and merge config detection Before this patch CMake did feature detections in three files: `src/CMakefiles.txt`, `examples/CMakefiles.txt` and `tests/CMakefiles.txt`. Merge and move them to the root `CMakefiles.txt`. After this patch we end up with a single `src/libssh2_config.h`. This brings CMake in sync with autotools builds, which already worked with a single config header. This also prevents mistakes where feature detection went out of sync between `src` & `tests` (see ae90a35d15d97154ac0c8554bce99ebfb18ee825). `tests` do compile sources from `src` directly, so these should always be in sync. It also allows to better integrate hand-crafted, platform-specific config headers into the builds, like the one currently residing in the `win32` directory (and also in `vms` and `os400`). Subject to an upcoming PR. Also fix a warning revealed after this patch made CMake correctly enable `HAVE_GETTIMEOFDAY` for `example` programs. Closes #906 - cmake: dedupe crypto-backend detection Before this patch CMake did crypto-backend detection in both `src/CMakefiles.txt` and `tests/CMakefiles.txt`. Merge them and move it to the root `CMakefiles.txt`. While here, also add zlib for OpenSSL. Necessary when using OpenSSL builds with zlib enabled. Closes #905 - cmake: add missing #cmakedefines to src - `HAVE_MEMSET_S` missing since 03092292597ac601c3f9f0c267ecb145dda75e4e (2018-08-02) - `HAVE_EXPLICIT_BZERO` and `HAVE_EXPLICIT_MEMSET` missing since 00005682f7b9a1aa42be50e269056ea873637047 (2023-03-28) GitHub (31 Mar 2023) - [Viktor Szakats brought this change] tidy-up: NMakefile (#903) Viktor Szakats (30 Mar 2023) - GNUmakefile: adjust win32/.gitignore [ci skip] - build: delete references to deleted NMake files [ci skip] Follow-up to 057522bb0f15c10c33159e12899ecc60e40aa6ef GitHub (30 Mar 2023) - [Viktor Szakats brought this change] NMakefile: merge them into a single file [ci skip] (#902) Also: - allow to override `AR` and `ARFLAGS`. - The extra `src` subdir in the target directory is no longer, to simplify things. - gone the dynamically generated `objects.mk`. Now replaced with some tricky logic to do that inline. - add necessary `LIBS` for WinCNG. (untested) Lightly tested via clang-cl. - [Viktor Szakats brought this change] maketgz: tidy-up [ci skip] (#901) - fix shellcheck warnings: - use quotes - use `$()` - use `printf` (instead of calling perl). - indent. - copy/adapt header comment from curl to `maketgz`. - [Viktor Szakats brought this change] ci: flatten AppVeyor jobs, add debug builds (#900) This results in better job names (now including CPU), avoiding the complex exception rules, and fine-tuning the order and variation of these tests. Enable `LIBSSH2DEBUG` for two of the existing jobs. - [Viktor Szakats brought this change] ci: add VS2022 builds (incl. ARM64) to AppVeyor (#899) - add MSVS 2022 WinCNG builds for x64 and ARM64, replacing MSVS 2013 WinCNG builds for x64 and x86. - add MSVS 2022 OpenSSL builds for x64. - fix a compiler warning uncovered by the new ARM64 build: ``` tests\openssh_fixture.c(393,17): warning C4477: 'fprintf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'libssh2_socket_t' tests\openssh_fixture.c(393,17): message : consider using '%lld' in the format string tests\openssh_fixture.c(393,17): message : consider using '%Id' in the format string tests\openssh_fixture.c(393,17): message : consider using '%I64d' in the format string ``` - echo the actual CMake command-line. - cmake: echo the DLL filenames found by the OpenSSL DLL-finder heuristics. - cmake: delete `libcrypto.dll` and `libssl.dll` names from the above logic. I've added these in 19884e5055b6c65f0df93d7cc776a01c518a2f06. That resulted in CMake picking up a rogue `libcrypto.dll` (with no `libssl.dll` pair) from `C:\Windows\System32\` on the `Visual Studio 2022` image, breaking tests. Turns out, OpenSSL v1.0.2 uses the "EAY" names, but let's not re-add those either, because CMake mis-picks those up from `C:/OpenSSL-Win64/bin/`, even while pointing `OPENSSL_ROOT_DIR` to a v1.1.1 installation. - cmake: set `NO_DEFAULT_PATH` for OpenSSL DLL lookup to avoid picking up all kinds of wrong DLLs. CMake considers not the first, but the _last_ hit the valid one. This happened to be `C:/Program Files/Meson/lib*-1_1.dll` when using the `Visual Studio 2022` image. Ref: https://cmake.org/cmake/help/latest/command/find_file.html - cmake: leave two commented debug lines that will be useful next time the DLL detection lookup goes wrong. Ref: https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_DEBUG_MODE.html - on error, also dump `CMakeFiles/CMakeConfigureLog.yaml` if it exists (requires CMake 3.26 and newer) - [Viktor Szakats brought this change] src: fix compiler warning on Darwin (#898) ``` src/session.c:675:52: warning: implicit conversion loses integer precision: 'long' to '__darwin_suseconds_t' (aka 'int') [-Wshorten-64-to-32] tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000; ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ ``` Viktor Szakats (29 Mar 2023) - tidy-up: tabs to spaces in Makefile.am [ci skip] Follow-up to 2f16d8105c9491beb2a02b3081f4f1c2a224fa62 GitHub (29 Mar 2023) - [Viktor Szakats brought this change] netware: delete support (#888) Last related commit happened 15 years ago. NetWare had it last release in 2009. All links referenced from the make file are inaccessible. - [Viktor Szakats brought this change] wolfssl: add workaround for HMAC_Update() len arg difference (#897) It's `int` in wolfSSL. `size_t` in OpenSSL/quictls/LibreSSL/BoringSSL. Ref: https://github.com/wolfSSL/wolfssl/blob/ba47562d182e10e59813da012e0ab8ef20892231/wolfssl/openssl/hmac.h#L60-L61 /cc @wolfSSL - [Viktor Szakats brought this change] cmake: introduce variables for lib target names (#896) Make our CMake config more self-documenting by introducing variables for the shared and static lib target names. Without this, it might be non-trivial to find out which line is referring to a target name vs libname, export name or other occurrences of `libssh2`. This allows to rename back the shared lib target name to the value used before 4e2580628dd1f8dc51ac65ac747ebcf0e93fa3d1: `libssh2_shared` -> `libssh2`, if necessary for compatibility. Notice: before that patch, `libssh2` name referred to either the static or shared lib, depending on build settings. - [Viktor Szakats brought this change] detect and use explicit_bzero() and explicit_memset() (#895) Also skip detecting these and `memset_s()` for Windows targets in CMake, to save detection time. On Windows we always use `SecureZeroMemory()`. - [Viktor Szakats brought this change] ci: bump mbedtls (#894) - [Viktor Szakats brought this change] GNUmakefile: minor fix for DYN mode [ci skip] (#893) Follow-up to b8762c1003d97e109efa587bdc760ff9873949eb - [Viktor Szakats brought this change] build: delete MS Dev Studio build files (#891) Last updated in 2007. Also delete `VCPROJ` target remains (necessary files seem to have been missing from the repo all along) for Visual Studio 2008. Viktor Szakats (28 Mar 2023) - checksrc: fix reference in Makefile.am, update options [ci skip] GitHub (28 Mar 2023) - [Viktor Szakats brought this change] build: delete native Watcom wmake support with Win32 (#889) CMake supports generating Watcom wmake files: https://cmake.org/cmake/help/v3.1/generator/Watcom%20WMake.html - [Viktor Szakats brought this change] checksrc: update and fix warnings (#890) Update from: https://github.com/curl/curl/blob/5fec927374e4d9553205d861f2dcb39ec78002cc/scripts/checksrc.pl - suppress these new checks: - EQUALSNULL: 320 warnings - NOTEQUALSZERO: 142 warnings - TYPEDEFSTRUCT: 16 warnings We can enabled them in the future. - fix all other new ones. - also fix whitespace in two `NMakefile` files. - [Viktor Szakats brought this change] tidy-up: fix/update URLs (#887) - [Viktor Szakats brought this change] tidy-up: fix typos (#886) detected by codespell 2.2.4. - [Viktor Szakats brought this change] tidy-up: replace tabs and other whitespace (#885) There are a few non-whitespace changes, see them here: https://github.com/libssh2/libssh2/pull/885/files?w=1 - [Viktor Szakats brought this change] ci: drop cmake --parallel (#884) `--parallel 2` did not seem to make builds faster. Neither did 4 or 6. Delete this option from both GHA and AppVeyor jobs. On AppVeyor, with VS, it uses MSBuild under the hood where apparently `--parallel` doesn't do much [1]. The suggested MSBuild-specific option `/p:CL_MPcount=2` did not improve build times either. CMake spends significant time (comparable to building the project itself) on feature detection, it'd be nice to execute those in parallel, but I found not such CMake option. [1] https://discourse.cmake.org/t/parallel-does-not-really-enable-parallel-compiles-with-msbuild/964 Partial revert of 7a039d9a7a2945c10b4622f38eeed21ba6b4ec55 - [Viktor Szakats brought this change] rework how to enable insecure null-cipher/null-MAC (#873) Null-cipher and null-MAC are security footguns we want to avoid. Existing option names to toggle these were ambiguous and gave room for misinterpretation. Some projects may have had these options enabled by accident. This patch aims to make it more difficult to enable them, and making sure that existing methods require an update to stay enabled. - delete CMake/autotools settings to enable the "none" cipher and MAC. - rename existing C macros that can enable them. To use them, pass them as custom `CPPFLAGS` to the build. - enable them only if `LIBSSH2DEBUG` is also enabled. Best would be to delete them, though they may have some use while developing libssh2 itself, or debugging. - [Viktor Szakats brought this change] delete old gex (SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) build option (#872) libssh2 supports an "old" style KEX message `SSH2_MSG_KEX_DH_GEX_REQUEST_OLD`, as an off-by-default build option. OpenSSH deprecated/disabled this feature in v6.9 (2015-07-01): https://www.openssh.com/releasenotes.html#6.9 This patch deletes this obsolete feature from libssh2, with no option to enable it. Added to libssh2 in: cf8ca63ea0c9388c8ae9079961d7e6a91b72b5c8 (2004-12-31) RFC: https://datatracker.ietf.org/doc/html/rfc4419 (2006-03) - [Viktor Szakats brought this change] src: more tolerant snprintf() local override (#881) `#undef snprintf` before redefining it, when `HAVE_SNPRINTF` is not defined, even though `snprintf` is available and it should have been. Possibly with 3rd party builds. Downside is that cases of missing `HAVE_SNPRINTF` are less trivially detected at compile-time. - [Viktor Szakats brought this change] ci: fix cmake warning with AppVeyor WinCNG builds (#883) ``` CMake Warning: Manually-specified variables were not used by the project: OPENSSL_ROOT_DIR ``` Follow-up to 0834b9bcc85b90c78afff103f909b5a909b95e45 - [Viktor Szakats brought this change] ci: cmake `ENABLE_WERROR` -> `ON` (#877) Consider warnings as errors for CMake jobs in CI. Viktor Szakats (26 Mar 2023) - src: silence compiler warnings 4 (alignment in WinCNG) Silence alignment warnings in WinCNG, by reworking the code. Also add two unrelated casts to avoid gcc compiler warnings in surrounding code. `increases required alignment from 1 to 4 [-Wcast-align]` `increases required alignment from 1 to 8 [-Wcast-align]` See warning details in the PR's individual commits. Reviewed-by: Marc Hörsken in Cherry-picked from #846 Closes #880 - src: silence compiler warnings 3 (change types) Apply type changes to avoid casts and warnings. In most cases this means changing to a larger type, usually `size_t` or `ssize_t`. Change signedness in a few places. Also introduce new variables to avoid reusing them for multiple purposes, to avoid casts and warnings. - add FIXME for public `libssh2_sftp_readdir_ex()` return type. - fix `_libssh2_mbedtls_rsa_sha2_verify()` to verify if `sig_len` is large enough. - fix `_libssh2_dh_key_pair()` in `wincng.c` to return error if `group_order` input is negative. Maybe we should also reject zero? - bump `_libssh2_random()` size type `int` -> `size_t`. Add checks for WinCNG and OpenSSL to return error if requested more than they support (`ULONG_MAX`, `INT_MAX` respectively). - change `_libssh2_ntohu32()` return value `unsigned int` -> `uint32_t`. - fix `_libssh2_mbedtls_bignum_random()` to check for a negative `top` input. - size down `_libssh2_wincng_key_sha_verify()` `hashlen` to match Windows'. - fix `session_disconnect()` to limit length of `lang_len` (to 256 bytes). - fix bad syntax in an `assert()`. - add a few `const` to casts. - `while(1)` -> `for(;;)`. - add casts that didn't fit into #876. - update `docs/HACKING-CRYPTO` with new sizes. May need review for OS400QC3: /cc @monnerat @jonrumsey See warning details in the PR's individual commits. Cherry-picked from #846 Closes #879 - src: silence compiler warnings 2 (ZLIB interface) Silence warnings in the ZLIB interface by adding casts and changing types. See PR for individual commits. Cherry-picked from #846 Closes #878 - src: silence compiler warnings 1 Most of the changes aim to silence warnings by adding casts. An assortment of other issues, mainly compiler warnings, resolved: - unreachable code fixed by using `goto` in `publickey_response_success()` in `publickey.c`. - potentially uninitialized variable in `sftp_open()`. - MSVS-specific bogus warnings with `nid_type` in `kex.c`. - check result of `kex_session_ecdh_curve_type()`. - add missing function declarations. - type changes to fit values without casts: - `cmd_len` in `scp_recv()` and `scp_send()`: `int` -> `size_t` - `Blowfish_expandstate()`, `Blowfish_expand0state()` loop counters: `uint16_t` -> `int` - `RECV_SEND_ALL()`: `int` -> `ssize_t` - `shell_quotearg()` -> `unsigned` -> `size_t` - `sig_len` in `_libssh2_mbedtls_rsa_sha2_sign()`: `unsigned` -> `size_t` - `prefs_len` in `libssh2_session_method_pref()`: `int` -> `size_t` - `firstsec` in `_libssh2_debug_low()`: `int` -> `long` - `method_len` in `libssh2_session_method_pref()`: `int` -> `size_t` - simplify `_libssh2_ntohu64()`. - fix `LIBSSH2_INT64_T_FORMAT` for MinGW. - fix gcc warning by not using a bit field for `burn_optimistic_kexinit`. - fix unused variable warning in `_libssh2_cipher_crypt()` in `libgcrypt.c`. - fix unused variables with `HAVE_DISABLED_NONBLOCKING`. - avoid const stripping with `BIO_new_mem_buf()` and OpenSSL 1.0.2 and newer. - add a missing const in `wincng.h`. - FIXME added for public: - `libssh2_channel_window_read_ex()` `read_avail` argument type. - `libssh2_base64_decode()` `datalen` argument type. - fix possible overflow in `sftp_read()`. Ref: 4552c73cd58fccb1fc49cb0f25f86619133e560f - formatting in `wincng.h`. See warning details in the PR's individual commits. Cherry-picked from #846 Closes #876 GitHub (24 Mar 2023) - [Viktor Szakats brought this change] cmake: automatic exports macro tidy-up (#875) In a recent CMake update I left the original CMake EXPORTS macro unchanged (`libssh2_EXPORTS`) for compatibility. However, that macro was also recently added [1] and not present in an official release yet, so we might as well just use the new native one instead (`libssh2_shared_EXPORTS`), defined by CMake automatically. This way we don't need to define the old macro manually. CMake forms this macro from the lib's internal name as defined in `add_library()` by appending `_EXPORTS`. That target name changed from `libssh2` to `libssh2_shared` after introducing dual shared + static builds in the recent update. If we're here, add a new, stable, build-tool agnostic macro with the same effect, for non-CMake use: `LIBSSH2_EXPORTS` [1] 1f0fe7443a1ecddd320f2c693607b2afee9bbe2f (2021-10-26) Follow-up to 4e2580628dd1f8dc51ac65ac747ebcf0e93fa3d1 - [Viktor Szakats brought this change] maketgz: add .xz, .bz2, .zip source archive formats (#874) Copied from curl: https://github.com/curl/curl/blob/4528690cd51e5445df74aef8f83470a602683797/maketgz#L174-L222 [ci skip] Viktor Szakats (23 Mar 2023) - dist: delete reference to recently deleted file [ci skip] Follow-up to b8762c1003d97e109efa587bdc760ff9873949eb GitHub (23 Mar 2023) - [Viktor Szakats brought this change] cmake: separate compilation passes for shared/static (#871) Before this patch, cmake did a single compilation pass when we enabled both shared and static lib targets. This saves build time (esp. with MinGW targets and cross-compiling), but has the disadvantage that static libs built this way must have PIC enabled (offering slightly less performance) and `dllexport` enabled also, which means that executables linking the static libssh2 lib export its public symbols. To avoid these downsides, this patch separates the two passes and creates a non-PIC, non-`dllexport` static lib, even when also building the shared lib. - [Viktor Szakats brought this change] ci: test with OpenSSL v1.1.1 on AppVeyor (#870) Was: v1.0.2. Keep using v1.0.2 with the static-only test. To make sure we don't break support. - [Viktor Szakats brought this change] ci: speed up static-only build tests on AppVeyor (#868) - limit static-only build to a single platform (x64). - skip running ctest for the static-only build. - use MSVS 2013 for static-only builds. It's faster. - run static-only test before WinCNG ones. Otherwise it's often skipped due to WinCNG failures (#804). - [Viktor Szakats brought this change] cmake: fix error with static lib off and example/tests on (#869) Regression from 4e2580628dd1f8dc51ac65ac747ebcf0e93fa3d1 - [Viktor Szakats brought this change] ci: parallelize more (#867) - [Viktor Szakats brought this change] cmake/src: move build options before target definitions (#864) To allow more flexibility when defining targets. - [Viktor Szakats brought this change] ci: use static+shared builds to cut number of cmake jobs (#865) With CMake builds supporting static-shared libssh2 builds in a single pass, we no longer need to run static and shared jobs separately. For the same effect it's enough to run builds with both shared and static builds enabled. Halving CI jobs. We add an extra run to test the CMake config-path without shared builds enabled. This allows to add useful jobs, e.g. MSVS 2022 or ZLIB-enabled builds for Windows, valgrind builds or other useful stuff, without stretching CI run times further. Ref: #863 Viktor Szakats (22 Mar 2023) - cmake: allow building static + shared libs in a single pass - `BUILD_SHARED_LIBS=ON` no longer disables building static lib. When set, we build the static lib with PIC enabled. For shared lib only, set `BUILD_STATIC_LIBS=OFF`. For static lib without PIC, leave this option disabled. - new setting: `BUILD_STATIC_LIBS`. `ON` by default. Force-enabled when building examples or tests (we build those in static mode always.) - fix to exclude Windows Resource from the static lib. - fix to not overwrite static lib with shared implib on Windows platforms using identical suffix for them (MSVS). By using `libssh2_imp<.ext>` implib filename. - add support for `STATIC_LIB_SUFFIX` setting to set an optional suffix (e.g. `_static`) for the static lib. (experimental, not documented). Overrides the above when set. - fix to set `dllexport` when building shared lib. - set `TrackFileAccess=false` for MSVS. For faster builds, shorter verbose logs. - tests: new test linking against shared libssh2: `test_warmup_shared` - tests: simplify 'runner' lib by merging 3 libs into a single one. - tests: drop hack from `test_keyboard_interactive_auth_info_request` build. We no longer need to compile `src/misc.c` because we always link libssh2 statically. - tests: limit `FIXTURE_WORKDIR=` to the `runner` target. TL;DR: Default behavior unchanged: static (no-PIC), no shared. Enabling shared unchanged, but now also builds a static (PIC) lib by default. Based-on: b60dca8b6450a9729670986d2899cca54ccdbb6d #547 by berney on github Fixes: #547 Fixes: #675 Closes: #863 - include: silence warnings with casts in public `libssh2_sftp.h` Avoid triggering warnings in macros coming from public libssh2 headers. Cherry-picked from: #846 Closes #862 - example, tests: address compiler warnings Fix or silence all C compiler warnings discovered with (or without) `PICKY_COMPILER=ON` (in CMake). This means all warnings showing up in CI (gcc, clang, MSVS 2013/2015), in local tests on macOS (clang 14) and Windows cross-builds using gcc (12) and llvm/clang (14/15). Also fix the expression `nread -= nread` in `sftp_RW_nonblock.c`. Cherry-picked from: #846 Closes #861 - openssl: require `EVP_aes_128_ctr()` support libssh2 built with OpenSSL and without its `EVP_aes_128_ctr()`, aka `HAVE_EVP_AES_128_CTR`, option are working incorrectly. This option wasn't always auto-detected by autotools up until recently (#811). Non-cmake, non-autotools build methods never enabled it automatically. OpenSSL supports this options since at least v1.0.2, which is already EOLed and considered obsolete. OpenSSL forks (LibreSSL, BoringSSL) supported it all along. In this patch we enable this option unconditionally, now requiring OpenSSL supporting this function, or one of its forks. Also modernize OpenSSL lib references to what 1.0.2 and newer versions have been using. Fixes #739 - wincng: fix memory leak in `_libssh2_dh_secret()` Patch-by: iruis on github Assisted-by: Marc Hörsken Bug #846, commit e3487092ef9553af67633c6747cb9ab2f86465e0. Fixes #856 Closes #858 GitHub (19 Mar 2023) - [Viktor Szakats brought this change] nw, os400, watcom: stop setting unused macros [ci skip] (#859) Viktor Szakats (19 Mar 2023) - cmake: fix `ENABLE_WERROR=ON` breaking auto-detections - cmake: fix compiler warnings in `CheckNonblockingSocketSupport`. detection functions. Without this, these detections fail when `ENABLE_WERROR=ON`. - cmake: disable ENABLE_WERROR for MSVC during symbol checks in `src`. CMake's built-in symbol check function `check_symbol_exists()` generate warnings with MSVC. With warnings considered errors, these detections fail permanently. Our workaround is to disable warnings-as-errors while running these checks. ``` CheckSymbolExists.c(8): warning C4054: 'type cast': from function pointer '__int64 (__cdecl *)(const char *,char **,int)' to data pointer 'int *' in `return ((int*)(&strtoll))[argc];` ``` Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46537222/job/4vg4yg333mu2lg9b - example: replace `strcasecmp()` with C89 `strcmp()`. To avoid using CMake symbol checks in `example`. Another option is to duplicate the `check_symbol_exists()` workaround from `src`, but I figure it's not worth the complexity. We use `strcasecmp()` solely to check optional command-line options for example programs, and those are fine as lower-case. Without this, these detections fail when `ENABLE_WERROR=ON`. - also delete `__function__` detection/use in `example`. To avoid the complexity for the sake of using it at a single place in of the example's error branch. Replace that use with a literal name of the function. - cmake: also use `CMakePushCheckState` functions instead of manual save/restore. Closes #857 - build: improve a test build workaround with bcrypt - cmake: extend workaround for linking a test with shared libssh2. One of the tests uses internal libssh2 functions, and with CMake it compiles `src/misc.c` directly for this. `misc.c` references bcrypt / blowfish code. This needs a workaround for build configs where libssh2 doesn't export these. Before this patch, we enabled this workaround for MSVC. In the patch we extend this to all Windows. There is no CI test for this, but gcc and llvm/clang + mingw64 builds also need it. This may well apply to other configurations (it should, as shared libs are not supposed to export internal functions), so also make it easy to enable it at a single point. [ autotools builds force-link this one test against static libssh2. ] - make `misc.c` not depend on bcrypt. By moving out our `bcrypt_pbkdf()` wrapper into `bcrypt_pbkdf.c` itself. This allows to compile `misc.c` into tests without pulling in bcrypt / blowfish functions, and simplify the above workaround. Source code uses `HAVE_BCRYPT_PBKDF`, a leftover from original bcrypt source. We never define this inside libssh2. Defining it breaks the build, and this patch doesn't change that. - make `bcrypt_pbkdf()` static. While here, make the low-level `bcrypt_pbkdf()` function static to avoid namespace pollution. Closes #855 GitHub (17 Mar 2023) - [Viktor Szakats brought this change] ci: more timeout adjustments (#853) - add timeout to SSH connection wait loop in AppVeyor test prep. (2 minutes) - switch to per-step timeout for GitHub CI cmake/ctest runs. (10 minutes) ctest timeout (of 450 seconds) didn't seem to make any difference. Viktor Szakats (17 Mar 2023) - ci: set timeout to ctest and GitHub CI jobs - `ctest` shows a the default timeout '10000000' (turns out to be in seconds), cause infinite waits e.g. in case the necessary server worker is not available. CMake CI tests take approx: - GitHub / Linux : 125 seconds - AppVeyor / Windows: 300 seconds New timeouts are: 450 and 900 seconds respectively. - set timeouts for style-check, fuzz, Linux and Windows GitHub CI jobs to avoid hanging forever. Also: - move `choco install` to before_test to make builds start faster in `appveyor.yml`. - fix some yamllint `ON`/`OFF`-confusion issue by quoting these values in `appveyor.yml`. - fix indentation in `appveyor.yml`. - convert to GitHub workflows to LF line-ending. Ref: https://github.com/libssh2/libssh2/pull/655#issuecomment-1472853493 Closes #851 GitHub (17 Mar 2023) - [Viktor Szakats brought this change] ci: update mbedTLS repo URL, delete Travis CI (#850) Last Travis CI session run on 2021-11-18. Ref: https://app.travis-ci.com/github/libssh2/libssh2 Ref: https://travis-ci.org/github/libssh2/libssh2/builds - [Viktor Szakats brought this change] appveyor.yml: reorder tests to return relevant feedback earlier (#849) - build x64 first x64 is the more interesting target. Most type conversion issues are revealed here. Also more commonly used by now. - test VS 2013 earlier - test WinCNG earlier - delete reference to no longer used VS 2008 After this patch we end up starting with all Shared builds (2015, 2013, OpenSSL, WinCNG), then continue with Static ones. Shared/Static makes a minor if any difference in builds/tests compared to different VS versions of TLS backends. -- CI run times: Preparation + build takes: 8 x VS2015 4.5 mins -> total: 36 8 x VS2013 2 mins -> total: 16 Total: 52 mins with our 30 tests, it increases to: 8 x VS2015 8-10 mins -> total: 72 8 x VS2013 6- 9 mins -> total: 60 Total: 132 mins Without tests: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46475315 With tests: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46480549 Dan Fandrich (14 Mar 2023) - src: check for NULL pointer passed to _libssh2_get_string Callers should be protecting against this, but it's prudent to check here anyway. Fixes #802 Closes #848 Viktor Szakats (14 Mar 2023) - appveyor.yml: choco install improvements [ci skip] - avoid outputting 4000 log lines by hiding the progress bar. Reduces log size by 5x. - decrease timeout (from the default 2700 seconds). - omit unnecessary output. Tested as part of #846 GitHub (14 Mar 2023) - [Jakob Egger brought this change] build: update instructions for autoreconf (#847) The "convenience script" talks about the "buildconf" file, which is no longer recommended. - [Viktor Szakats brought this change] win32: set HAVE_STRTOLL with MSVS 2013 and newer (#845) As in curl: https://github.com/curl/curl/blob/7fa6e36583b52dd8f1e639b370c9a2849be81b54/lib/config-win32.h#L221 - [Viktor Szakats brought this change] GNUmakefile: move HAVE_STRTOLL to libssh2_config.h [ci skip] (#844) - [Viktor Szakats brought this change] src: silence unused variable warnings (#843) Viktor Szakats (13 Mar 2023) - GNUmakefile: add wolfSSL support + major rework - add wolfSSL support. - reduce size and redundant logic. - fix a bunch of small issues. - rework configuration, now with: `CC`, `AR`, `RC`, `TRIPLET`, `CFLAGS`, `CPPFLAGS`, `LDFLAGS`, `RCFLAGS`, `LIBS`, `LIBSSH2_DLL_SUFFIX`, `LIBSSH2_LDFLAGS_LIB`, `LIBSSH2_LDFLAGS_BIN` (and more). - merge examples build into the main Makefile. - relative dependency paths are now the same for building libssh2 or examples. - drop detection for obsolete OpenSSL versions (can be configure via new `OPENSSL_LIBS`). - merge dev/dist distribution zip options. - build libssh2 with `-DHAVE_STRTOLL`. - tidy-up. - build examples in static mode by default (use `DYN` to build them in shared mode). - drop forced (in non-debug mode) `-O2`. - drop Win9x support. - deprecate `ARCH` in favour of custom options and `TRIPLET`. - drop Windows resources from examples for simplicity - drop `WITH_ZLIB`. Default `ZLIB_PATH` to enable zlib support. - drop `LIBSSH2_DLL_A_SUFFIX`, use standard value `.dll` (as in `libssh2.dll.a`). - always link `bcrypt` (for LibreSSL and OpenSSL) and `crypt32` (for wolfSSL). - unhide executed build commands. - fix mbedTLS `lib` path - drop specific options to force static linking. Custom options seems a better way for this. - based on similar work made for curl: https://github.com/curl/curl/commit/a8861b6ccdd7ca35b6115588a578e36d765c9e38 Closes #842 GitHub (13 Mar 2023) - [Viktor Szakats brought this change] wincng: fix memory leak in libssh2_dh_key_pair() (#829) Fixes #722 - [Viktor Szakats brought this change] src: C89-compliant _libssh2_debug() macro (#831) Before this patch, with debug logging disabled, libssh2 code used a variadic macro to catch `_libssh2_debug()` calls, and convert them to no-ops. In certain conditions, it used an empty inline function instead. Variadic macro is a C99 feature. It means that depending on compiler, and build settings, it littered the build log with warnings about this. The new solution uses the trick of passing the variable arg list as a single argument and pass that down to the debug function with a regular macro. When disabled, another regular C89-compatible macro converts it to a no-op. This makes inlining, C99 variadic macros and maintaining the conditions for each unnecessary and also makes the codebase compile more consistently, e.g. with forced C standards and/or picky warnings. TL;DR: It makes this feature C89-compliant. - [Viktor Szakats brought this change] openssl: fix possible compiler warning in macro condition (#839) Building with wolfSSL or pre-OpenSSL v1.1.1 triggered it. ``` ../src/openssl.h:130:5: warning: 'LIBRESSL_VERSION_NUMBER' is not defined, evaluates to 0 [-Wundef] LIBRESSL_VERSION_NUMBER >= 0x3070000fL ^ ``` Regression from 2e2812dde8c1fc9b48eca592823770ab2e601f7a - [Viktor Szakats brought this change] GNUmakefile: cleanups [ci skip] (#840) - indent - sync `test/GNUmakefile` with main - delete `RANLIB` - use `else if` - use more `?=` - use ASCII-7 copyright symbol (in test) - [Viktor Szakats brought this change] win32: convert tabs to spaces [ci skip] (#838) Also strip stray newlines from `win32/rules.mk`. - [Viktor Szakats brought this change] ci: retry choco install on appveyor (#837) Trying to mitigate occasional intermittent failures while installing docker. Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46460704/job/g3t7bro6ta6n3pk6#L52 - [Viktor Szakats brought this change] cmake: drop unnecessary exception for warmup build (#835) - [Viktor Szakats brought this change] cmake: reflect minimum version in docs (#834) Follow-up to 505ea626b6e125b7ce15caf453b522192008a884 - [Viktor Szakats brought this change] cmake: add wolfSSL support to tests (#833) wolfSSL supports building with zlib as a dependency, that's the reason for the ZLIB logic in the patch. Also add it to `docs/INSTALL_CMAKE.md` and to the help text in `src/CMakeLists.txt`. Running tests not actually tested. Follow-up to 9f217a17f6f3c2047c4a1668a5c037a75a02abfd Ref: #817 - [Viktor Szakats brought this change] tests: workaround for intermittent first test failures (#832) Flakiness got continously worse these last days. It didn't seem related to recent commits. Flakiness also picked up in GitHub CI runs, something rarely seen before. Manual restart consistently fixed them. The repeating pattern was the _first_ test (`test_hostkey`) failing, with `libssh2_session_handshake failed (-13): Failed getting banner`. Failures came after a lengthy wait, suggesting a timeout. I then reversed the order of the first two tests, and it turned out that the _first_ test failed again (`test_hostkey_hash`). Also pointing to a timeout issue. Then I added a dummy test to "warm up" whatever needs warming up in the layers of CI + Docker + ssh server and their interconnects. This helped, and GitHub CI tests run without failure right for the first time. AppVeyor CI also improved a little. This patch adds a new first test called `test_warmup`, that creates a new libssh2 session, and exits with success even if that attempt failed. A stop-gap solution at best, and there is no guarantee it will continue to fix this or similar future issues, but it's also untenable to have almost every CI run fail for intermittent reasons. In some [1] cases [2] it's not the first test failing intermittently. That's a different issue, and this patch doesn't fix it. [1] #804 [2] https://ci.appveyor.com/project/libssh2org/libssh2/builds/46440828/job/8rej6cq6itg7vc4w#L500 - [Viktor Szakats brought this change] cmake: detect HAVE_SNPRINTF for tests (#830) Turns out `test_keyboard_interactive_auth_info_request.c` requires `src/libssh2_priv.h`, which in turn requires a correctly set `HAVE_SNPRINTF`. Follow-up to 4cdf785cd313c3272d04c2ef7458a35d44533d8b. - [Viktor Szakats brought this change] cmake: unset forced CMAKE_C_STANDARD 90 (#822) Added in cf80f2f4b5255cc85a04ee43b27a29c678c1edb1 (on 2016-08-14), with the title "Basic dockerised test suite". It's not clear why a C standard was explicitly set, but a side-effect of this is that CMake-built binaries diverged from ones built with autotools or GNU Make (using the same compiler and configuration). Another issue is that this may introduce ABI incompatibility with binaries built with a different C standard flag, e.g. the C compiler default or one used for other components of a final app. Seems unlikely, but if our tests require this option, we should set it for the CI builds only? - [Viktor Szakats brought this change] example: silence MSVS 2013 C4127 warnings (#828) - [Viktor Szakats brought this change] cmake: reposition ws2_32 to make binutils ld work again (#827) This restores socket libs to their pre-regression positions. Without this, `ld` doesn't find `ws2_32` symbols when referenced from TLS libs. Regression from 31fb8860dbaae3e0b7d38f2a647ee527b4b2a95f - [Viktor Szakats brought this change] fix compiling with LIBSSH2_NO_CLEAR_MEMORY and OpenSSL (#825) Regression from a0e424a51c27cc27af611ba20d134f9a9ae35273 Fixes #824 - [Viktor Szakats brought this change] snprintf: add missing prototype for local replacement (#820) Should fix these warnings with MSVS 2013 and older: `agent.c(294): warning C4013: '_libssh2_snprintf' undefined; assuming extern returning int` Follow-up to 4cdf785cd313c3272d04c2ef7458a35d44533d8b. - [Viktor Szakats brought this change] build: set _FILE_OFFSET_BITS=64 for mingw-w64 (#821) autotools builds already did auto-detect and set this mingw-specific macro, but CMake and GNU Make builds did not. This patch fixes that. Necessary for `src/scp.c`. - [Viktor Szakats brought this change] cmake: add os400qc3.c to SOURCES (#826) This re-syncs the list of compiled objects in cmake builds with non-cmake builds. Follow-up to 16619a8eddec35bb8582d1c334db0fc13b0817c4. - [Viktor Szakats brought this change] build: silence bogus C4127 warnings with MSVS 2013 and earlier (#819) E.g.: `channel.c(370): warning C4127: conditional expression is constant` Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46437333/job/5rak1vcl9hue31ei#L190 - [Viktor Szakats brought this change] cmake: use only needed socket libs when checking non-blocking sockets (#816) Based on patch by Christian Beier. Fixes #694 Closes #712 - [Viktor Szakats brought this change] cmake: update openssl dll list (#818) Add OpenSSL 3 and versionless DLL names. Also modernize warning messages and variable names. Do we need the OpenSSL-Windows-specific check and the related `RUNTIME_DEPENDENCIES` feature? The list of OpenSSL DLLs was out of date for 1.5 years without anybody noticing. Keeping it fresh is a chore and copying around DLL dependencies rarely helps as much as expected. This check also results in unuseful warnings in certain build scenarios, e.g. when linking to OpenSSL statically. - [Viktor Szakats brought this change] cmake: add wolfSSL support (#817) Implement wolfSSL support for libssh2 when building with CMake. Configuration example from curl-for-win: ``` -DCRYPTO_BACKEND=wolfSSL -DWOLFSSL_LIBRARY=/path-to/wolfssl/lib/libwolfssl.a -DWOLFSSL_INCLUDE_DIR=/path-to/wolfssl/include ``` Module `cmake/Findwolfssl.cmake` copied from: https://github.com/ngtcp2/ngtcp2/blob/e4d920c4b7a350d63b6978c68b216b76faa12635/cmake/Findwolfssl.cmake via commit: https://github.com/ngtcp2/ngtcp2/commit/296396d3730b721ad97f9de22f525400f8524c0e by Stefan Eissing - [Viktor Szakats brought this change] cmake: restore non-Windows socket lib detection (#815) I mistakenly pruned some non-Windows logic, also missing the fact that our local `check_function_exists_may_need_library()` set the `NEED_*` variables. Oddly, only `src` imported this function, yet also `examples` and `tests` called it indirectly. The referenced `HAVE_SOCKET` / `HAVE_INET_ADDR` variables might be coming from an upstream CMake project? Leaving those there also, just in case. Regression from 31fb8860dbaae3e0b7d38f2a647ee527b4b2a95f Viktor Szakats (7 Mar 2023) - build: more fixes and tidy-up (mostly for Windows) - cmake: always link `ws2_32` on Windows. Also add it to `libssh2.pc`. Fixes #745 - agent: fix gcc compiler warning: `src/agent.c:296:35: warning: 'snprintf' output truncated before the last format character [-Wformat-truncation=]` - autotools: fix `EVP_aes_128_ctr` detection with binutils `ld` The prerequisite for a successful detection is setting `LIBS=-lbcrypt` if the chosen openssl-compatible library requires it, e.g. libressl, or quictls/openssl built with `-DUSE_BCRYPTGENRANDOM`. With llvm `lld`, detection works out of the box. With binutils `ld`, it does not. The reason is `ld`s world-famous pickiness with lib order. To fix it, we pass all custom libs before and after the TLS libs. This ugly hack makes `ld` happy and detection succeed. - agent: fix Windows-specific warning: `src/agent.c:318:10: warning: implicit conversion loses integer precision: 'LRESULT' (aka 'long long') to 'int' [-Wshorten-64-to-32]` - src: fix llvm/clang compiler warning: `src/libssh2_priv.h:987:28: warning: variadic macros are a C99 feature [-Wvariadic-macros]` - src: support `inline` with `__GNUC__` (llvm/clang and gcc), fixing: ``` src/libssh2_priv.h:990:8: warning: extension used [-Wlanguage-extension-token] static inline void ^ ``` - blowfish: support `inline` keyword with MSVC. Also switch to `__inline__` (from `__inline`) for `__GNUC__`: https://gcc.gnu.org/onlinedocs/gcc/Inline.html https://clang.llvm.org/docs/UsersManual.html#differences-between-various-standard-modes - example/test: fix MSVC compiler warnings: - `example\direct_tcpip.c(209): warning C4244: 'function': conversion from 'unsigned int' to 'u_short', possible loss of data` - `tests\session_fixture.c(96): warning C4013: 'getcwd' undefined; assuming extern returning int` - `tests\session_fixture.c(100): warning C4013: 'chdir' undefined; assuming extern returning int` - delete unused macros: - `HAVE_SOCKET` - `HAVE_INET_ADDR` - `NEED_LIB_NSL` - `NEED_LIB_SOCKET` - `HAVE_NTSTATUS_H` - `HAVE_NTDEF_H` - build: delete stale zlib/openssl version numbers from path defaults. - cmake: convert tabs to spaces, add newline at EOFs. Closes #811 - cmake: make `test_read` runs cross-build-friendly Improve tests added in 7487dcf4b4ddae54b2a850737789b57b4251b0ae by running `test_read` commands directly. This makes external shell/batch files unnecessary, and is friendlier with cross-builds and when run from non-default shells, like MSYS2. Also extend CRYPT/MAC test error messages with the CRYPT/MAC name. External runner shell scripts kept for future use. Closes #814 - src: enable clear memory on all platforms - convert `_libssh2_explicit_zero()` to macro. This allows inlining where supported (e.g. `SecureZeroMemory()`). - replace `SecureZeroMemory()` (in `wincng.c`) and `LIBSSH2_CLEAR_MEMORY`-guarded `memset()` (in `os400qc3.c`) with `_libssh2_explicit_zero()` macro. - delete `LIBSSH2_CLEAR_MEMORY` guards, which enables secure-zeroing universally. - add `LIBSSH2_NO_CLEAR_MEMORY` option to disable secure-zeroing. - while here, delete double/triple inclusion of `misc.h`. `libssh2_priv.h` included it already. Closes #810 - cmake: bump minimum version to 3.1 (from 2.8.12) This allows to delete some fallback code. CMake release dates: - 2014-12-15: 3.1 - 2013-10-07: 2.8.12 Closes #813 - snprintf: unify fallback logic Before this patch, the `snprintf()` fallback logic for envs not supporting this function (i.e. Visual Studio 2013 and older) varied depending on build tool, and used different techniques in examples, tests and libssh2 itself. This patch aims to apply a common logic to libssh2 and examples/tests. - libssh2: use local `snprintf()` fallback with all build tools. We already had a local implementation, but only with CMake. Move that to the library as `_libssh2_snprintf()`, and map `snprintf()` to it when `HAVE_SNPRINTF` is not set. Also change the length type from `int` to `size_t`, and fix formatting. - set or detect `HAVE_SNPRINTF` in non-CMake builds. Detect in autotools. Keep existing logic in `win32/libssh2_config.h`. Always set for OS/400, NetWare and VMS, keeping existing behaviour. (OS/400 builds use a different local implementation) - examples/tests: drop the CMake-specific fallback logic and map `snprintf()` to `_snprintf()` for old MSVC versions, like we did before with other build tools. This is unsafe, but should be fine for these uses. - `win32/libssh2_config.h`: make it easier to read. Closes #812 - cmake: build fixes with OpenSSL/LibreSSL on Windows - Link `bcrypt` for newer (non-fork) OpenSSL. - Link `bcrypt` and `ws2_32` when using (non-fork) OpenSSL or LibreSSL, to allow `Looking for EVP_aes_128_ctr` detecting this feature. With the feature available, but not found by CMake, build failed with: `openssl.c:636:21: error: incompatible integer to pointer conversion assigning to 'EVP_CIPHER *' (aka 'struct evp_cipher_st *') from 'int' [-Wint-conversion]` Closes #809 - build fixes and improvements (mostly for Windows) - in `hostkey.c` check the result of `libssh2_sha256_init()` and `libssh2_sha512_init()` calls. This avoid the warning that we're ignoring the return values. - fix code using `int` (or `SOCKET`) for sockets. Use libssh2's dedicated `libssh2_socket_t` and `LIBSSH2_INVALID_SOCKET` instead. - fix compiler warnings due to `STATUS_*` macro redefinitions between `ntstatus.h` / `winnt.h`. Solve it by manually defining the single `STATUS` value we need from `ntstatus.h` and stop including the whole header. Fixes #733 - improve Windows UWP/WinRT builds by detecting it with code copied from the curl project. Then excluding problematic libssh2 parts according to PR by Dmitry Kostjučenko. Fixes #734 - always use `SecureZeroMemory()` on Windows. We can tweak this if not found or not inlined by a C compiler which we otherwise support. Same if it causes issues with UWP apps. Ref: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa366877(v=vs.85) Ref: https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlsecurezeromemory - always enable `LIBSSH2_CLEAR_MEMORY` on Windows. CMake and curl-for-win builds already did that. Delete `SecureZeroMemory()` detection from autotools' WinCNG backend logic, that this setting used to depend on. TODO: Enable it for all platforms in a separate PR. TODO: For clearing buffers in WinCNG, call `_libssh2_explicit_zero()`, insead of a local function or explicit `SecureZeroMemory()`. - Makefile.inc: move `os400qc3.h` to `HEADERS`. This fixes compilation on non-unixy platforms. Recent regression. - `libssh2.rc`: replace copyright with plain ASCII, as in curl. Ref: curl/curl@1ca62bb Ref: curl/curl#7765 Ref: curl/curl#7776 - CMake fixes and improvements: - enable warnings with llvm/clang. - enable more comprehensive warnings with gcc and llvm/clang. Logic copied from curl: https://github.com/curl/curl/blob/233810bb5f6c5e7bedfc10bdd36607b958c0cfe4/CMakeLists.txt#L131-L148 - fix `Policy CMP0080` CMake warning by deleting that reference. - add `ENABLE_WERROR` (default: `OFF`) option. Ported from curl. - add `PICKY_COMPILER` (default: `ON`) option, as known from curl. It controls both the newly added picky warnings for llvm/clang and gcc, and also the pre-existing ones for MSVC. - `win32/GNUmakefile` fixes and improvements: - delete `_AMD64_` and add missing `-m64` for x64 builds under test. - add support for `ARCH=custom`. It disables hardcoded Intel 64-bit and Intel 32-bit options, allowing ARM64 builds. - add support for `LIBSSH2_RCFLAG_EXTRAS`. To pass custom options to windres, e.g. in ARM64 builds. - add support for `LIBSSH2_RC`. To override `windres`. - delete support for Metrowerks C. Last released in 2004. - `win32/libssh2_config.h`: delete unnecessary socket #includes `src/libssh2_priv.h` includes `winsock2.h` and `ws2tcpip.h` further down the line, triggered by `HAVE_WINSOCK2_H`. `mswsock.h` does not seem to be necessary anymore. Double-including these (before `windows.h`) caused compiler failures when building against BoringSSL and warnings with LibreSSL. We could work this around by passing `-DNOCRYPT`. Deleting the duplicates fixes these issues. Timeline: 2013: c910cd382dfa07fed2adaabf688af9e4a084fa1d deleted `mswsock.h` from `src/libssh2_priv.h` 2008: 8c43bc52b1e3de2c8fc7899a80aec0e98de4e2d8 added `winsock2.h` and `ws2tcpip.h` to `src/libssh2_priv.h` 2005: dc4bb1af967d2c53e90349f2f37324c622e714f5 added the now deleted #includes - delete or replace `LIBSSH2_WIN32` with `WIN32`. - replace hand-rolled `HAVE_WINDOWS_H` macro with `WIN32`. Also delete its detections/definitions. - delete unused `LIBSSH2_DARWIN` macro. - delete unused `writev()` Windows implementation There is no reference to `writev()` since 2007-02-02, commit 9d55db6501aa4e21f0858cf36cdc2ddc11b96e83. - fix a bunch of MSVC / llvm/clang / gcc compiler warnings: - `warning C4100: '...': unreferenced formal parameter` - using value of undefined PP macro `LIBSSH2DEBUG` - missing void from function definition - `if()` block missing in non-debug builds - unreferenced variable in non-debug builds - `warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]` in `_libssh2_debug()` - `warning C4295: 'ciphertext' : array is too small to include a terminating null character` - `warning C4706: assignment within conditional expression` - `warning C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings` By suppressning it. Would be best to use inet_pton() as suggested. On Windows this needs Vista though. - `warning C4152: nonstandard extension, function/data pointer conversion in expression` (silenced locally) - `warning C4068: unknown pragma` Ref: https://ci.appveyor.com/project/libssh2org/libssh2/builds/46354480/job/j7d0m34qgq8rag5w Closes #808 Dan Fandrich (1 Mar 2023) - Add tests to check individual crypt & HMAC methods One specific crypt or hmac method is requested to be negotiated, then several MB of data is transferred. - Add test to read lots of data over a channel Connects to the ssh server then downloads several MB of data. This tests the data transfer path as well as boundary cases in packet handling as data is split into smaller SSH blocks. GitHub (27 Feb 2023) - [Will Cosgrove brought this change] Disable deprecated warnings for OpenSSL 3 #805 (#806) Disable deprecated warnings (for now) when building against OpenSSL 3 for a clean build. Reported: Daniel Stenberg Dan Fandrich (24 Feb 2023) - Fix a couple of warnings of errors in MSVC builds Two warnings (in tests & examples) in particular would cause problems: bad format causing invalid data output or a bad chdir due to out of scope buffer use. - tests: Support running tests in out-of-tree builds Various files are found by referencing the srcdir environment variable in that case. Closes #801 - Improve the ssh2 example program to run a command This performs better as an example since it shows more working code, and in the simplest possible way. It also turns the program into an actually useful tool out of the box, able to run an arbitrary command (with one restriction) on a remote machine and return the response, without needing to touch the source. Closes #800 GitHub (14 Feb 2023) - [Will Cosgrove brought this change] Add NULL session check to _libssh2_error_flags() (#796) Don't dereference null if a null session happens to make it into _libssh2_error_flags() Dan Fandrich (7 Feb 2023) - Reorder AES crypt methods so stronger ones are first This make it more likely that a stronger one will be negotiated rather than a weaker variant. - CI: update uses: dependencies to the latest versions We were seeing some deprecation warning messages on some of the older ones. - transport.c: Add some comments - Add missing files to automake makefiles & build tests Many files have been added to the cmake build files but not the automake ones in recent years. Missing ones have been added so automake "make dist" will now create a usable tar ball. The integration tests using Docker are now built with automake as well (with "make check"). They are not run yet since they aren't working yet on Linux. - tests: Fix gcc compile warnings These were mostly due to missing and non-ANSI prototypes. - Enable trace debugging in example/ssh2 This is intended to be a test program, so debugging is likely to be useful by default. - Improve example/ssh2 to allow unmodified use of public key auth The previous hard-coded key file paths were not valid for normal users. Make the paths relative to the user's home directory instead so they can work out of the box. Add a banner showing what connection will be attempted to make it easier for the user to see what is being attempted. Enable trace debugging since this is designed as a test program. GitHub (13 Dec 2022) - [Viktor Szakats brought this change] openssl.h: enable ed25519 for LibreSSL 3.7.0 (#778) This brings LibreSSL libssh2 builds on par with OpenSSL. Dan Fandrich (5 Dec 2022) - configure.ac: check for sys/param.h This file is required by glibc for the test suite. GitHub (12 Nov 2022) - [Viktor Szakats brought this change] tests: add option to run tests without docker (#762) via `export OPENSSH_NO_DOCKER=1`. SSH server host can be set via: `export OPENSSH_SERVER_HOST=127.0.0.1` SSH server port via existing: `export OPENSSH_SERVER_PORT=4711` This requires more work to be usable out of the box. The necessery sshd config is (partly) embedded into `tests/openssh_server/Dockerfile`. After this patch, it is possible to run tests in envs where docker is not installed or not available, by running a preconfigured, non-containerized sshd. - [Michael Buckley brought this change] Skip leading \r and \n characters in banner_receive() (#769) Fixes #768 Credit: Michael Buckley - [Zenju brought this change] Fixed error handling of _libssh2_packet_requirev callers (#767) Notes: some callers of _libssh2_packet_requirev() fail to set _libssh2_error(). This creates the situation where e.g. libssh2_session_handshake() fails, but libssh2_session_last_error() confusingly returns LIBSSH2_ERROR_NONE. Credit: Zenju - [Will Cosgrove brought this change] Revert usage of EVP_CipherUpdate #764 #739 (#765) Revert usage of EVP_CipherUpdate from wolfSSL PR to fix #764 #739. - [Will Cosgrove brought this change] Fix regression with rsa_sha2_verify #758 (#763) Fixes comparison with the result value coming from `mbedtls_rsa_pkcs1_verify`. Success is 0, not 1. Marc Hoersken (24 Oct 2022) - CI: fix AppVeyor status failing for starting jobs Viktor Szakats (24 Oct 2022) - delete cast5 - null-cipher mapping - more feature guard cleanup - indent - formatting - fold long lines - cleanup - temporarily silence checksrc - add mbedTLS 3.x support Make libssh2 compile cleanly with mbedTLS 3.x and later. This patch makes use of `MBEDTLS_PRIVATE()`, which is not the recommended, future-proof way to access mbedTLS data structures. This method may break with a minor upgrade, according to the authors. This is also the method used by libcurl. Also: - Fix a potentially uninitialized variable in `libssh2_mbedtls_rsa_sha2_sign()`. This happened in an error path, resulting in an unnecessary mbedTLS API call, with an uninitialized `md_type`. - Bump mbedTLS version used in CI tests to 3.2.1. Fixes #751 - tests: add option to enable all trace messages in fixture via `export FIXTURE_TRACE_ALL=1`. - win32/GNUmakefile: add mbedTLS support via `export MBEDTLS_PATH=`. Marc Hoersken (21 Oct 2022) - CI: fix AppVeyor job links only working for most recent build Ref: https://github.com/curl/curl/pull/9768#issuecomment-1286675916 Reported-by: Daniel Stenberg Follow up to #754 - CI: add missing permission section to AppVeyor status workflow Follow up to #754 - Remove OSSFuzz integration which was replaced with CIFuzz (#756) Confirmed-by: Max Dymond - Rename workflow file appveyor.yml to appveyor_docker.yml - Streamline names of CI workflow jobs - [Jeroen Ooms brought this change] Add CI for mingw-w64 via msys2 (#742) Credit: Jeroen Ooms - CI: report AppVeyor build status for each job (#754) Also give each job on AppVeyor CI a human-readable name. This aims to make job and therefore build failures more visible. GitHub (29 Sep 2022) - [Michael Buckley brought this change] Support for sk-ecdsa-sha2-nistp256 and sk-ssh-ed25519 keys, FIDO (#698) Notes: Add support for sk-ecdsa-sha2-nistp256@openssh.com and sk-ssh-ed25519@openssh.com key exchange for FIDO auth using the OpenSSL backend. Stub API for other backends. Credit: Michael Buckley - [Y. Yang brought this change] Fix DLL import library name (#711) Notes: Fix DLL import library name https://aur.archlinux.org/packages/mingw-w64-libssh2 https://cmake.org/cmake/help/latest/prop_tgt/IMPORT_PREFIX.html Credit: metab0t Y. Yang - [skundu07 brought this change] Add RSA-SHA2 support for the WinCNG backend (#736) Notes: Added code to support RSA-SHA2 for WinCNG backend. Credit: skundu07 - [Gabriel Smith brought this change] sftp: Prevent files from being skipped if the output buffer is too small (#746) Notes: LIBSSH2_ERROR_BUFFER_TOO_SMALL is returned if the buffer is too small to contain a returned directory entry. On this condition we jump to the label `end`. At this point the number of names left is decremented despite no name being returned. As suggested in #714, this commit moves the error label after the decrement of `names_left`. Fixes #714 Credit: Co-authored-by: Gabriel Smith - [bgermann brought this change] Drop advertisement clause on Blowfish (#747) Originally driven by https://github.com/pyca/bcrypt/issues/169, OpenBSD removed Niels Provos's BSD advertisement clause in version 7.1: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/lib/libsa/blowfish.c.diff?r1=1.1&r2=1.2 https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/lib/libsa/blowfish.h.diff?r1=1.1&r2=1.2 This enables using libssh2 in GPL software. - [zhaochongliu brought this change] Support building with gcc < version 8 Files: CMakeLists.txt Notes: don't use gcc arguments that don't exist in gcc versions lower than 8 if building with older gcc. Credit: zhaochongliu - [Miguel de Icaza brought this change] Document the obscure LIBSSH2_ERROR_BAD_USE when writing to a channel (#713) Document the obscure LIBSSH2_ERROR_BAD_USE when writing to a channel Credit: Miguel de Icaza - [Michael Buckley brought this change] Don't erroneously log SSH_MSG_REQUEST_FAILURE packets from keepalive (#727) Notes: When setting a ServerAliveInterval using libssh2_keepalive_config() with want_reply set to true, some servers will reply to the keep-alive requests with a single SSH_MSG_REQUEST_FAILURE packet. This is an allowed behavior in RFC 4254, section 4. Credit: Michael Buckley - [Ryan Kelley brought this change] Updating docs for libssh2_channel_flush_ex (#728) Notes: In #614 it was identified the docs do not accurately show how libssh2_channel_flush_ex() return value is set. I have updated the doc's to correctly show what the function is returning. Credit: Ryan Kelley - [Sandeep Bansal brought this change] Support RSA certificate authentication (#710) * Adding support for signed RSA keys and unit test Credit: Sandeep Bansal Viktor Szakats (2 Jul 2022) - configure: add --disable-tests option - cmake: do not add libssh2.rc to the static library GitHub (23 May 2022) - [AyushiN brought this change] Fixed typo #697 (#701) Credit: AyushiN - [Viktor Szakats brought this change] Openssl: add support for LibreSSL 3.5.x (#700) LibreSSL 3.5.0 made more structures opaque, so let's enable existing support for that when building against these LibreSSL versions. Ref: https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.5.0-relnotes.txt Credit: Viktor Szakats - [Michael Buckley brought this change] Ensure KEX replies don't include extra bytes (#696) Addresses #695 Credit: Michael Buckley, reported by Harry Sintonen - [Zenju brought this change] Fix buffer overflow during SSH_MSG_USERAUTH_BANNER (#693) File: userauth.c Notes: This patch fixes application crashes due to heap corruption. Turns out the null terminator is written one byte outside of the allocated area. Credit: Zenju - [Will Cosgrove brought this change] Changed NULL check to avoid logic change - [Will Cosgrove brought this change] NULL check before calling session_handshake - [Harry Sintonen brought this change] Fix build since openssl 1.1.0 when ECDSA and/or RIPEMD are disabled (#666) File: openssl.h Notes: In openssl 1.1.0 and later openssl decided to change some of the defines used to check if certain features are not compiled in the libraries. This updates the define checks. Credit: Harry Sintonen Co-authored-by: Harry Sintonen - [gbaraldi brought this change] Add RSA-SHA2 support for the mbedtls backend (#688) File: mbedtls.c Notes: * Add sha2 support for RSA key upgrading to mbedTLS backend Credit: gbaraldi Daniel Stenberg (21 Mar 2022) - misc/libssh2_copy_string: avoid malloc zero bytes Avoids the inconsistent malloc return code for malloc(0) Closes #686 Marc Hoersken (17 Mar 2022) - wincng: rename struct field referring to the DH private big number Closes #684 - tests/openssh_fixture.c: print command after variable expansion - CI: store and reuse OpenSSH Server docker image used for tests Supersedes #588 Fixes #665 Closes #685 GitHub (26 Feb 2022) - [Will Cosgrove brought this change] Added LibreSSL to crypto backend list - [Will Cosgrove brought this change] Added crypto backend list to template Added OS version as well - [Will Cosgrove brought this change] Revert "Option to build both static and shared libraries (#547)" (#675) This reverts commit b60dca8b6450a9729670986d2899cca54ccdbb6d. #547 doesn't build clean anymore with the keyboard interactive changes. - [berney brought this change] Option to build both static and shared libraries (#547) files: cmakelists.txt Notes: * Option to build both static and shared libraries when using CMake Credit: berney - [xalopp brought this change] Use modern API in userauth_keyboard_interactive() (#663) Files: userauth_kbd_packet.c, userauth_kbd_packet.h, test_keyboard_interactive_auth_info_request.c, userauth.c Notes: This refactors `SSH_MSG_USERAUTH_INFO_REQUEST` processing in `userauth_keyboard_interactive()` in order to improve robustness, correctness and readability or the code. * Refactor userauth_keyboard_interactive to use new api for packet parsing * add unit test for userauth_keyboard_interactive_parse_response() * add _libssh2_get_boolean() and _libssh2_get_byte() utility functions Credit: xalopp - [xalopp brought this change] Fix formatting in manual page (#667) Fixed formatting of `LIBSSH2_ERROR_AUTHENTICATION_FAILED` in the errors section. credit: xalopp - [tihmstar brought this change] NULL terminate server_sign_algorithms string (#669) files: packet.c, libssh2_priv.h notes: * Fix heap buffer overflow in _libssh2_key_sign_algorithm When allocating `session->server_sign_algorithms` which is a `char*` is is important to also allocate space for the string-terminating null byte at the end and make sure the string is actually null terminated. Without this fix, the `strchr()` call inside the `_libssh2_key_sign_algorithm` (line 1219) function will try to parse the string and go out of buffer on the last invocation. Credit: tihmstar Co-authored-by: Will Cosgrove - [Will Cosgrove brought this change] free RSA2 related memory (#664) Free `server_sign_algorithms` and `sign_algo_prefs`. - [Will Cosgrove brought this change] Legacy Agent support for rsa2 key upgrading/downgrading #659 (#662) Files: libssh2.h, agent.c, userauth.c Notes: Part 2 of the fix for #659. This adds rsa key downgrading for agents that don't support sha2 upgrading. It also adds better trace output for debugging/logging around key upgrading. Credit: Will Cosgrove (signed off by Michael Buckley) - [Ian Hattendorf brought this change] Support rsa-sha2 agent flags (#661) File: agent.c Notes: implements rsa-sha2 flags used to tell the agent which signing algo to use. https://tools.ietf.org/id/draft-miller-ssh-agent-01.html#rfc.section.4.5.1 Credit: Ian Hattendorf Daniel Stenberg (13 Jan 2022) - [Sunil Nimmagadda brought this change] ssh: Add support for userauth banner. The new libssh2_userauth_banner API allows to get an optional userauth banner sent with SSH_MSG_USERAUTH_BANNER packet by the server. Closes #610 GitHub (6 Jan 2022) - [Michael Buckley brought this change] Fix a memcmp errors in code that was changed from memmem to memcmp (#656) Notes: Fixed supported algo prefs list check when upgrading rsa keys Credit: Michael Buckley - [Hayden Roche brought this change] Add support for a wolfSSL crypto backend. (#629) It uses wolfSSL's OpenSSL compatibility layer, so rather than introduce new wolfssl.h/c files, the new backend just reuses openssl.h/c. Additionally, replace EVP_Cipher() calls with EVP_CipherUpdate(), since EVP_Cipher() is not recommended. Credit: Hayden Roche - [Bastien Durel brought this change] Runtime engine detection with libssh2_crypto_engine() (#643) File: version.c, HACKING-CRYPTO, libssh2.h, libssh2_crypto_engine.3, makefile. Notes: libssh2_crypto_engine() API to get crypto engine at runtime. Credit: Bastien Durel - [Will Cosgrove brought this change] RSA SHA2 256/512 key upgrade support RFC 8332 #536 (#626) Notes: * Host Key RSA 256/512 support #536 * Client side key hash upgrading for RFC 8332 * Support for server-sig-algs, ext-info-c server messages * Customizing preferred server-sig-algs via the preference LIBSSH2_METHOD_SIGN_ALGO Credit: Anders Borum, Will Cosgrove - [xalopp brought this change] fix: use userauth name length to check memory boundaries for userauth name, fixes #653 (#654) File: userauth.c Notes: Fixes `userauth_kybd_auth_name_len` length check Co-authored-by: Xaver Lopenstedt - [Daniel Stenberg brought this change] agent: handle overly large comment lengths (#651) Reported-by: Harry Sintonen - [Daniel Stenberg brought this change] userauth: check for too large userauth_kybd_auth_name_len (#650) ... before using it. Reported-by: MarcoPoloPie Fixes #649 Daniel Stenberg (17 Dec 2021) - .github/SECURITY.md: fix the URL - .github/SECURITY.md: add security policy GitHub (30 Nov 2021) - [Will Cosgrove brought this change] hostkey_method_ssh_ed25519_init() check key bounds (#645) * hostkey_method_ssh_ed25519_init() check key bounds File: hostkey.c Notes: Additional key length checking before calling _libssh2_ed25519_new_public() Credit: Will Cosgrove - [Will Cosgrove brought this change] Fix error message in memory_read_privatekey #636 file: userauth.c note: fix error message credit: volund - [cntrump brought this change] Update maketgz for macOS (#543) File: maketgz Notes: Fix error on macOS: sed: -e: No such file or directory Credit: cntrump - [Jun Tseng brought this change] CMake update minimum version to 2.8.12 (#639) File: CMakeLists.txt Notes: Following CMake's advice, Update the minimum required version. Credit: Jun Tseng Daniel Stenberg (8 Nov 2021) - [David Korczynski brought this change] ci: Add CIFuzz integration Notes: Add CIFuzz integration to run fuzzer using the OSS-Fuzz infrastructure at each PR. Signed-off-by: David Korczynski Closes #635 GitHub (26 Oct 2021) - [Uwe L. Korn brought this change] Use libssh2_EXPORTS as an alternative to _WINDLL (#470) Files: libssh2.h Notes: `_WINDLL` is only defined when a Visual Studio CMake generator is used, `libssh2_EXPORTS` is used though for all CMake generator if a shared libssh2 library is being built. Credit: Uwe L. Korn Viktor Szakats (1 Oct 2021) - windows: fix clang and WinCNG warnings Fix these categories of warning: - in `wincng.c` disagreement in signed/unsigned char when passing around the passphrase string: `warning: pointer targets in passing argument [...] differ in signedness [-Wpointer-sign]` Fixed by using `const unsigned char *` in all static functions and applying/updating casts as necessary. - in each use of `libssh2_*_init()` macros where the result is not used: `warning: value computed is not used [-Wunused-value]` Fixed by using `(void)` casts. - `channel.c:1171:7: warning: 'rc' may be used uninitialized in this function [-Wmaybe-uninitialized]` Fixed by initializing this variable with `LIBSSH2_ERROR_CHANNEL_UNKNOWN`. While there I replaced a few 0 literals with `LIBSSH2_ERROR_NONE`. - in `sftp.c`, several of these two warnings: `warning: 'data' may be used uninitialized in this function [-Wmaybe-uninitialized]` `warning: 'data_len' may be used uninitialized in this function [-Wmaybe-uninitialized]` Fixed by initializing these variables with NULL and 0 respectively. - Also removed the exec attribute from `wincng.h`. Notes: - There are many pre-existing checksrc issues. - The `sftp.c` and `channel.c` warnings may apply to other platforms as well. Closes #628 Daniel Stenberg (25 Sep 2021) - README: use www.libssh2.org for the license link - libssh2.h: bump it to 1.10.1-dev - mailing list: moved to lists.haxx.se GitHub (2 Sep 2021) - [Laurent Stacul brought this change] openssh_fixture.c: Fix openssh_server build not working (#616) (#620) File: openssh_fixture.c Notes: fixes too long of output lines building docker image Credit: Laurent Stacul - [Will Cosgrove brought this change] openssh_fixture.c: fix warning (#621) File: openssh_fixture.c Notes: Fix `portable_sleep` return type warning Credit: Will Cosgrove - [Will Cosgrove brought this change] Update CI to use latest Ubuntu #624 (#625) File: ci.yml Notes: Update CI to use latest Ubuntu #624 Also removed 32 bit building in the matrix. Credit: Will Cosgrove - [Will Cosgrove brought this change] Update .gitignore Add .DS_Store files for macOS - [Laurent Stacul brought this change] Makefile.am: Add missing key in case openssl > 1.1.0 (#617) File: Makefile.am Notes: fix missing test keys Credit: Laurent Stacul Version 1.10.0 (29 Aug 2021) Daniel Stenberg (29 Aug 2021) - [Will Cosgrove brought this change] updated docs for 1.10.0 release Marc Hörsken (30 May 2021) - [Laurent Stacul brought this change] [tests] Try several times to connect the ssh server Sometimes, as the OCI container is run in detached mode, it is possible the actual server is not ready yet to handle SSH traffic. The goal of this PR is to try several times (max 3). The mechanism is the same as for the connection to the docker machine. - [Laurent Stacul brought this change] Remove openssh_server container on test exit - [Laurent Stacul brought this change] Allow the tests to run inside a container The current tests suite starts SSH server as OCI container. This commit add the possibility to run the tests in a container provided that: * the docker client is installed builder container * the host docker daemon unix socket has been mounted in the builder container (with, if needed, the DOCKER_HOST environment variable accordingly set, and the permission to write on this socket) * the builder container is run on the default bridge network, or the host network. This PR does not handle the case where the builder container is on another network. Marc Hoersken (28 May 2021) - CI/appveyor: run SSH server for tests on GitHub Actions (#607) No longer rely on DigitalOcean to host the Docker container. Unfortunately we require a small dispatcher script that has access to a GitHub access token with scope repo in order to trigger the daemon workflow on GitHub Actions also for PRs. This script is hosted by myself for the time being until GitHub provides a tighter scope to trigger the workflow_dispatch event. GitHub (26 May 2021) - [Will Cosgrove brought this change] openssl.c: guards around calling FIPS_mode() #596 (#603) Notes: FIPS_mode() is not implemented in LibreSSL and this API is removed in OpenSSL 3.0 and was introduced in 0.9.7. Added guards around making this call. Credit: Will Cosgrove - [Will Cosgrove brought this change] configure.ac: don't undefine scoped variable (#594) * configure.ac: don't undefine scoped variable To get this script to run with Autoconf 2.71 on macOS I had to remove the undefine of the backend for loop variable. It seems scoped to the for loop and also isn't referenced later in the script so it seems OK to remove it. * configure.ac: remove cygwin specific CFLAGS #598 Notes: Remove cygwin specific Win32 CFLAGS and treat the build like a posix build Credit: Will Cosgrove, Brian Inglis - [Laurent Stacul brought this change] tests: Makefile.am: Add missing tests client keys in distribution tarball (#604) Notes: Added missing test keys. Credit: Laurent Stacul - [Laurent Stacul brought this change] Makefile.am: Add missing test keys in the distribution tarball (#601) Notes: Fix tests missing key to build the OCI image Credit: Laurent Stacul Daniel Stenberg (16 May 2021) - dist: add src/agent.h Fixes #597 Closes #599 GitHub (12 May 2021) - [Will Cosgrove brought this change] packet.c: Reset read timeout after received a packet (#576) (#586) File: packet.c Notes: Attempt keyboard interactive login (Azure AD 2FA login) and use more than 60 seconds to complete the login, the connection fails. The _libssh2_packet_require function does almost the same as _libssh2_packet_requirev but this function sets state->start = 0 before returning. Credit: teottin, Co-authored-by: Tor Erik Ottinsen - [kkoenig brought this change] Support ECDSA certificate authentication (#570) Files: hostkey.c, userauth.c, test_public_key_auth_succeeds_with_correct_ecdsa_key.c Notes: Support ECDSA certificate authentication Add a test for: - Existing ecdsa basic public key authentication - ecdsa public key authentication with a signed public key Credit: kkoenig - [Gabriel Smith brought this change] agent.c: Add support for Windows OpenSSH agent (#517) Files: agent.c, agent.h, agent_win.c Notes: * agent: Add support for Windows OpenSSH agent The implementation was partially taken and modified from that found in the Portable OpenSSH port to Win32 by the PowerShell team, but mostly based on the existing Unix OpenSSH agent support. https://github.com/PowerShell/openssh-portable Regarding the partial transfer support implementation: partial transfers are easy to deal with, but you need to track additional state when non-blocking IO enters the picture. A tracker of how many bytes have been transfered has been placed in the transfer context struct as that's where it makes most sense. This tracker isn't placed behind a WIN32 #ifdef as it will probably be useful for other agent implementations. * agent: win32 openssh: Disable overlapped IO Non-blocking IO is not currently supported by the surrounding agent code, despite a lot of the code having everything set up to handle it. Credit: Co-authored-by: Gabriel Smith - [Zenju brought this change] Fix detailed _libssh2_error being overwritten (#473) Files: openssl.c, pem.c, userauth.c Notes: * Fix detailed _libssh2_error being overwritten by generic errors * Unified error handling Credit: Zenju - [Paul Capron brought this change] Fix _libssh2_random() silently discarding errors (#520) Notes: * Make _libssh2_random return code consistent Previously, _libssh2_random was advertized in HACKING.CRYPTO as returning `void` (and was implemented that way in os400qc3.c), but that was in other crypto backends a lie; _libssh2_random is (a macro expanding) to an int-value expression or function. Moreover, that returned code was: — 0 or success, -1 on error for the MbedTLS & WinCNG crypto backends But also: — 1 on success, -1 or 0 on error for the OpenSSL backend! – 1 on success, error cannot happen for libgcrypt! This commit makes explicit that _libssh2_random can fail (because most of the underlying crypto functions can indeed fail!), and it makes its result code consistent: 0 on success, -1 on error. This is related to issue #519 https://github.com/libssh2/libssh2/issues/519 It fixes the first half of it. * Don't silent errors of _libssh2_random Make sure to check the returned code of _libssh2_random(), and propagates any failure. A new LIBSSH_ERROR_RANDGEN constant is added to libssh2.h None of the existing error constants seemed fit. This commit is related to d74285b68450c0e9ea6d5f8070450837fb1e74a7 and to https://github.com/libssh2/libssh2/issues/519 (see the issue for more info.) It closes #519. Credit: Paul Capron - [Gabriel Smith brought this change] ci: Remove caching of docker image layers (#589) Notes: continued ci reliability work. Credit: Gabriel Smith - [Gabriel Smith brought this change] ci: Speed up docker builds for tests (#587) Notes: The OpenSSH server docker image used for tests is pre-built to prevent wasting time building it during a test, and unneeded rebuilds are prevented by caching the image layers. Credit: Gabriel Smith - [Will Cosgrove brought this change] userauth.c: don't error if using keys without RSA (#555) file: userauth.c notes: libssh2 now supports many other key types besides RSA, if the library is built without RSA support and a user attempts RSA auth it shouldn't be an automatic error credit: Will Cosgrove - [Marc brought this change] openssl.c: Avoid OpenSSL latent error in FIPS mode (#528) File: openssl.c Notes: Avoid initing MD5 digest, which is not permitted in OpenSSL FIPS certified cryptography mode. Credit: Marc - [Laurent Stacul brought this change] openssl.c: Fix EVP_Cipher interface change in openssl 3 #463 File: openssl.c Notes: Fixes building with OpenSSL 3, #463. The change is described there: https://github.com/openssl/openssl/commit/f7397f0d58ce7ddf4c5366cd1846f16b341fbe43 Credit: Laurent Stacul, reported by Sergei - [Gabriel Smith brought this change] openssh_fixture.c: Fix potential overwrite of buffer when reading stdout of command (#580) File: openssh_fixture.c Notes: If reading the full output from the executed command took multiple passes (such as when reading multiple lines) the old code would read into the buffer starting at the some position (the start) every time. The old code only works if fgets updated p or had an offset parameter, both of which are not true. Credit: Gabriel Smith - [Gabriel Smith brought this change] ci: explicitly state the default branch (#585) Notes: It looks like the $default-branch macro only works in templates, not workflows. This is not explicitly stated anywhere except the linked PR comment. https://github.com/actions/starter-workflows/pull/590#issuecomment-672360634 credit: Gabriel Smith - [Gabriel Smith brought this change] ci: Swap from Travis to Github Actions (#581) Files: ci files Notes: Move Linux CI using Github Actions Credit: Gabriel Smith, Marc Hörsken - [Mary brought this change] libssh2_priv.h: add iovec on 3ds (#575) file: libssh2_priv.h note: include iovec for 3DS credit: Mary Mstrodl - [Laurent Stacul brought this change] Tests: Fix unused variables warning (#561) file: test_public_key_auth_succeeds_with_correct_ed25519_key_from_mem.c notes: fixed unused vars credit: Laurent Stacul - [Viktor Szakats brought this change] bcrypt_pbkdf.c: fix clang10 false positive warning (#563) File: bcrypt_pbkdf.c Notes: blf_enc() takes a number of 64-bit blocks to encrypt, but using sizeof(uint64_t) in the calculation triggers a warning with clang 10 because the actual data type is uint32_t. Pass BCRYPT_BLOCKS / 2 for the number of blocks like libc bcrypt(3) does. Ref: https://github.com/openbsd/src/commit/04a2240bd8f465bcae6b595d912af3e2965856de Fixes #562 Credit: Viktor Szakats - [Will Cosgrove brought this change] transport.c: release payload on error (#554) file: transport.c notes: If the payload is invalid and there is an early return, we could leak the payload credit: Will Cosgrove - [Will Cosgrove brought this change] ssh2_client_fuzzer.cc: fixed building The GitHub web editor did some funky things - [Will Cosgrove brought this change] ssh_client_fuzzer.cc: set blocking mode on (#553) file: ssh_client_fuzzer.cc notes: the session needs blocking mode turned on to avoid EAGAIN being returned from libssh2_session_handshake() credit: Will Cosgrove, reviewed by Michael Buckley - [Etienne Samson brought this change] Add a LINT option to CMake (#372) * ci: make style-checking available locally * cmake: add a linting target * tests: check test suite syntax with checksrc.pl - [Will Cosgrove brought this change] kex.c: kex_agree_instr() improve string reading (#552) * kex.c: kex_agree_instr() improve string reading file: kex.c notes: if haystack isn't null terminated we should use memchr() not strchar(). We should also make sure we don't walk off the end of the buffer. credit: Will Cosgrove, reviewed by Michael Buckley - [Will Cosgrove brought this change] kex.c: use string_buf in ecdh_sha2_nistp (#551) * kex.c: use string_buf in ecdh_sha2_nistp file: kex.c notes: use string_buf in ecdh_sha2_nistp() to avoid attempting to parse malformed data - [Will Cosgrove brought this change] kex.c: move EC macro outside of if check #549 (#550) File: kex.c Notes: Moved the macro LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY outside of the LIBSSH2_ECDSA since it's also now used by the ED25519 code. Sha 256, 384 and 512 need to be defined for all backends now even if they aren't used directly. I believe this is already the case, but just a heads up. Credit: Stefan-Ghinea - [Tim Gates brought this change] kex.c: fix simple typo, niumber -> number (#545) File: kex.c Notes: There is a small typo in src/kex.c. Should read `number` rather than `niumber`. Credit: Tim Gates - [Tseng Jun brought this change] session.c: Correct a typo which may lead to stack overflow (#533) File: session.c Notes: Seems the author intend to terminate banner_dup buffer, later, print it to the debug console. Author: Tseng Jun Marc Hoersken (10 Oct 2020) - wincng: fix random big number generation to match openssl The old function would set the least significant bits in the most significant byte instead of the most significant bits. The old function would also zero pad too much bits in the most significant byte. This lead to a reduction of key space in the most significant byte according to the following listing: - 8 bits reduced to 0 bits => eg. 2048 bits to 2040 bits DH key - 7 bits reduced to 1 bits => eg. 2047 bits to 2041 bits DH key - 6 bits reduced to 2 bits => eg. 2046 bits to 2042 bits DH key - 5 bits reduced to 3 bits => eg. 2045 bits to 2043 bits DH key No change would occur for the case of 4 significant bits. For 1 to 3 significant bits in the most significant byte the DH key would actually be expanded instead of reduced: - 3 bits expanded to 5 bits => eg. 2043 bits to 2045 bits DH key - 2 bits expanded to 6 bits => eg. 2042 bits to 2046 bits DH key - 1 bits expanded to 7 bits => eg. 2041 bits to 2047 bits DH key There is no case of 0 significant bits in the most significant byte since this would be a case of 8 significant bits in the next byte. At the moment only the following case applies due to a fixed DH key size value currently being used in libssh2: The DH group_order is fixed to 256 (bytes) which leads to a 2047 bits DH key size by calculating (256 * 8) - 1. This means the DH keyspace was previously reduced from 2047 bits to 2041 bits (while the top and bottom bits are always set), so the keyspace is actually always reduced from 2045 bits to 2039 bits. All of this is only relevant for Windows versions supporting the WinCNG backend (Vista or newer) before Windows 10 version 1903. Closes #521 Daniel Stenberg (28 Sep 2020) - libssh2_session_callback_set.3: explain the recv/send callbacks Describe how to actually use these callbacks. Closes #518 GitHub (23 Sep 2020) - [Will Cosgrove brought this change] agent.c: formatting Improved formatting of RECV_SEND_ALL macro. - [Will Cosgrove brought this change] CMakeLists.txt: respect install lib dir #405 (#515) Files: CMakeLists.txt Notes: Use CMAKE_INSTALL_LIBDIR directory Credit: Arfrever - [Will Cosgrove brought this change] kex.c: group16-sha512 and group18-sha512 support #457 (#468) Files: kex.c Notes: Added key exchange group16-sha512 and group18-sha512. As a result did the following: Abstracted diffie_hellman_sha256() to diffie_hellman_sha_algo() which is now algorithm agnostic and takes the algorithm as a parameter since we needed sha512 support. Unfortunately it required some helper functions but they are simple. Deleted diffie_hellman_sha1() Deleted diffie_hellman_sha1 specific macro Cleaned up some formatting Defined sha384 in os400 and wincng backends Defined LIBSSH2_DH_MAX_MODULUS_BITS to abort the connection if we receive too large of p from the server doing sha1 key exchange. Reorder the default key exchange list to match OpenSSH and improve security Credit: Will Cosgrove - [Igor Klevanets brought this change] agent.c: Recv and send all bytes via network in agent_transact_unix() (#510) Files: agent.c Notes: Handle sending/receiving partial packet replies in agent.c API. Credit: Klevanets Igor - [Daniel Stenberg brought this change] Makefile.am: include all test files in the dist #379 File: Makefile.am Notes: No longer conditionally include OpenSSL specific test files, they aren't run if we're not building against OpenSSL 1.1.x anyway. Credit: Daniel Stenberg - [Max Dymond brought this change] Add support for an OSS Fuzzer fuzzing target (#392) Files: .travis.yml, configure.ac, ossfuzz Notes: This adds support for an OSS-Fuzz fuzzing target in ssh2_client_fuzzer, which is a cut down example of ssh2.c. Future enhancements can improve coverage. Credit: Max Dymond - [Sebastián Katzer brought this change] mbedtls.c: ECDSA support for mbed TLS (#385) Files: mbedtls.c, mbedtls.h, .travis.yml Notes: This PR adds support for ECDSA for both key exchange and host key algorithms. The following elliptic curves are supported: 256-bit curve defined by FIPS 186-4 and SEC1 384-bit curve defined by FIPS 186-4 and SEC1 521-bit curve defined by FIPS 186-4 and SEC1 Credit: Sebastián Katzer Marc Hoersken (1 Sep 2020) - buildconf: exec autoreconf to avoid additional process (#512) Also make buildconf exit with the return code of autoreconf. Follow up to #224 - scp.c: fix indentation in shell_quotearg documentation - wincng: make more use of new helper functions (#496) - wincng: make sure algorithm providers are closed once (#496) GitHub (10 Jul 2020) - [David Benjamin brought this change] openssl.c: clean up curve25519 code (#499) File: openssl.c, openssl.h, crypto.h, kex.c Notes: This cleans up a few things in the curve25519 implementation: - There is no need to create X509_PUBKEYs or PKCS8_PRIV_KEY_INFOs to extract key material. EVP_PKEY_get_raw_private_key and EVP_PKEY_get_raw_public_key work fine. - libssh2_x25519_ctx was never used (and occasionally mis-typedefed to libssh2_ed25519_ctx). Remove it. The _libssh2_curve25519_new and _libssh2_curve25519_gen_k interfaces use the bytes. Note, if it needs to be added back, there is no need to roundtrip through EVP_PKEY_new_raw_private_key. EVP_PKEY_keygen already generated an EVP_PKEY. - Add some missing error checks. Credit: David Benjamin - [Will Cosgrove brought this change] transport.c: socket is disconnected, return error (#500) File: transport.c Notes: This is to fix #102, instead of continuing to attempt to read a disconnected socket, it will now error out. Credit: TDi-jonesds - [Will Cosgrove brought this change] stale.yml Increasing stale values. Marc Hoersken (6 Jul 2020) - wincng: try newer DH API first, fallback to legacy RSA API Avoid the use of RtlGetVersion or similar Win32 functions, since these depend on version information from manifests. This commit makes the WinCNG backend first try to use the new DH algorithm API with the raw secret derivation feature. In case this feature is not available the WinCNG backend will fallback to the classic approach of using RSA-encrypt to perform the required modular exponentiation of BigNums. The feature availability test is done during the first handshake and the result is stored in the crypto backends global state. Follow up to #397 Closes #484 - wincng: fix indentation of function arguments and comments Follow up to #397 - [Wez Furlong brought this change] wincng: use newer DH API for Windows 8.1+ Since Windows 1903 the approach used to perform DH kex with the CNG API has been failing. This commit switches to using the `DH` algorithm provider to perform generation of the key pair and derivation of the shared secret. It uses a feature of CNG that is not yet documented. The sources of information that I've found on this are: * https://stackoverflow.com/a/56378698/149111 * https://github.com/wbenny/mini-tor/blob/5d39011e632be8e2b6b1819ee7295e8bd9b7a769/mini/crypto/cng/dh.inl#L355 With this change I am able to successfully connect from Windows 10 to my ubuntu system. Refs: https://github.com/alexcrichton/ssh2-rs/issues/122 Fixes: https://github.com/libssh2/libssh2/issues/388 Closes: https://github.com/libssh2/libssh2/pull/397 GitHub (1 Jul 2020) - [Zenju brought this change] comp.c: Fix name clash with ZLIB macro "compress" (#418) File: comp.c Notes: * Fix name clash with ZLIB macro "compress". Credit: Zenju - [yann-morin-1998 brought this change] buildsystem: drop custom buildconf script, rely on autoreconf (#224) Notes: The buildconf script is currently required, because we need to copy a header around, because it is used both from the library and the examples sources. However, having a custom 'buildconf'-like script is not needed if we can ensure that the header exists by the time it is needed. For that, we can just append the src/ directory to the headers search path for the examples. And then it means we no longer need to generate the same header twice, so we remove the second one from configure.ac. Now, we can just call "autoreconf -fi" to generate the autotools files, instead of relying on the canned sequence in "buildconf", since autoreconf has now long known what to do at the correct moment (future versions of autotools, automake, autopoint, autoheader etc... may require an other ordering, or other intermediate steps, etc...). Eventually, get rid of buildconf now it is no longer needed. In fact, we really keep it for legacy, but have it just call autoreconf (and print a nice user-friendly warning). Don't include it in the release tarballs, though. Update doc, gitignore, and travis-CI jobs accordingly. Credit: Signed-off-by: "Yann E. MORIN" Cc: Sam Voss - [Will Cosgrove brought this change] libssh2.h: Update Diffie Hellman group values (#493) File: libssh2.h Notes: Update the min, preferred and max DH group values based on RFC 8270. Credit: Will Cosgrove, noted from email list by Mitchell Holland Marc Hoersken (22 Jun 2020) - travis: use existing Makefile target to run checksrc - Makefile: also run checksrc on test source files - tests: avoid use of deprecated function _sleep (#490) - tests: avoid use of banned function strncat (#489) - tests: satisfy checksrc regarding max line length of 79 chars Follow up to 2764bc8e06d51876b6796d6080c6ac51e20f3332 - tests: satisfy checksrc with whitespace only fixes checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT -AFOPENMODE tests/*.[ch] - tests: add support for ports published via Docker for Windows - tests: restore retry behaviour for docker-machine ip command - tests: fix mix of declarations and code failing C89 compliance - wincng: add and improve checks in bit counting function - wincng: align bits to bytes calculation in all functions - wincng: do not disable key validation that can be enabled The modular exponentiation also works with key validation enabled. - wincng: fix return value in _libssh2_dh_secret Do not ignore return value of modular exponentiation. - appveyor: build and run tests for WinCNG crypto backend GitHub (1 Jun 2020) - [suryakalpo brought this change] INSTALL_CMAKE.md: Update formatting (#481) File: INSTALL_CMAKE.md Notes: Although the original text would be immediately clear to seasoned users of CMAKE and/or Unix shell, the lack of newlines may cause some confusion for newcomers. Hence, wrapping the texts in a md code-block such that the newlines appear as intended. credit: suryakalpo Marc Hoersken (31 May 2020) - src: add new and align include guards in header files (#480) Make sure all include guards exist and follow the same format. - wincng: fix multiple definition of `_libssh2_wincng' (#479) Add missing include guard and move global state from header to source file by using extern. GitHub (28 May 2020) - [Will Cosgrove brought this change] transport.c: moving total_num check from #476 (#478) file: transport.c notes: moving total_num zero length check from #476 up to the prior bounds check which already includes a total_num check. Makes it slightly more readable. credit: Will Cosgrove - [lutianxiong brought this change] transport.c: fix use-of-uninitialized-value (#476) file:transport.c notes: return error if malloc(0) credit: lutianxiong - [Dr. Koutheir Attouchi brought this change] libssh2_sftp.h: Changed type of LIBSSH2_FX_* constants to unsigned long, fixes #474 File: libssh2_sftp.h Notes: Error constants `LIBSSH2_FX_*` are only returned by `libssh2_sftp_last_error()` which returns `unsigned long`. Therefore these constants should be defined as unsigned long literals, instead of int literals. Credit: Dr. Koutheir Attouchi - [monnerat brought this change] os400qc3.c: constify libssh2_os400qc3_hash_update() data parameter. (#469) Files: os400qc3.c, os400qc3.h Notes: Fixes building on OS400. #426 Credit: Reported-by: hjindra on github, dev by Monnerat - [monnerat brought this change] HACKING.CRYPTO: keep up to date with new crypto definitions from code. (#466) File: HACKING.CRYPTO Notes: This commit updates the HACKING.CRYPTO documentation file in an attempt to make it in sync with current code. New documented features are: SHA384 SHA512 ECDSA ED25519 Credit: monnerat - [Harry Sintonen brought this change] kex.c: Add diffie-hellman-group14-sha256 Key Exchange Method (#464) File: kex.c Notes: Added diffie-hellman-group14-sha256 kex Credit: Harry Sintonen - [Will Cosgrove brought this change] os400qc3.h: define sha512 macros (#465) file: os400qc3.h notes: fixes for building libssh2 1.9.x - [Will Cosgrove brought this change] os400qc3.h: define EC types to fix building #426 (#462) File: os400qc3.h Notes: define missing EC types which prevents building Credit: hjindra - [Brendan Shanks brought this change] hostkey.c: Fix 'unsigned int'/'uint32_t' mismatch (#461) File: hostkey.c Notes: These types are the same size so most compilers are fine with it, but CodeWarrior (on classic MacOS) throws an ‘illegal implicit conversion’ error Credit: Brendan Shanks - [Thomas Klausner brought this change] Makefile.am: Fix unportable test(1) operator. (#459) file: Makefile.am Notes: The POSIX comparison operator for test(1) is =; bash supports == but not even test from GNU coreutils does. Credit: Thomas Klausner - [Tseng Jun brought this change] openssl.c: minor changes of coding style (#454) File: openssl.c Notes: minor changes of coding style and align preprocessor conditional for #439 Credit: Tseng Jun - [Hans Meier brought this change] openssl.c: Fix for use of uninitialized aes_ctr_cipher.key_len (#453) File: Openssl.c Notes: * Fix for use of uninitialized aes_ctr_cipher.key_len when using HAVE_OPAQUE_STRUCTS, regression from #439 Credit: Hans Meirer, Tseng Jun - [Zenju brought this change] agent.c: Fix Unicode builds on Windows (#417) File: agent.c Notes: Fixes unicode builds for Windows in Visual Studio 16.3.2. Credit: Zenju - [Hans Meier brought this change] openssl.c: Fix use-after-free crash in openssl backend without memory leak (#439) Files: openssl.c Notes: Fixes memory leaks and use after free AES EVP_CIPHER contexts when using OpenSSL 1.0.x. Credit: Hans Meier - [Romain Geissler @ Amadeus brought this change] Session.c: Fix undefined warning when mixing with LTO-enabled libcurl. (#449) File: Session.c Notes: With gcc 9, libssh2, libcurl and LTO enabled for all binaries I see this warning (error with -Werror): vssh/libssh2.c: In function ‘ssh_statemach_act’: /data/mwrep/rgeissler/ospack/ssh2/BUILD/libssh2-libssh2-03c7c4a/src/session.c:579:9: error: ‘seconds_to_next’ is used uninitialized in this function [-Werror=uninitialized] 579 | int seconds_to_next; | ^ lto1: all warnings being treated as errors Gcc normally issues -Wuninitialized when it is sure there is a problem, and -Wmaybe-uninitialized when it's not sure, but it's possible. Here the compiler seems to have find a real case where this could happen. I looked in your code and overall it seems you always check if the return code is non null, not often that it's below zero. I think we should do the same here. With this patch, gcc is fine. Credit: Romain-Geissler-1A - [Zenju brought this change] transport.c: Fix crash with delayed compression (#443) Files: transport.c Notes: Fixes crash with delayed compression option using Bitvise server. Contributor: Zenju - [Will Cosgrove brought this change] Update INSTALL_MAKE path to INSTALL_MAKE.md (#446) Included for #429 - [Will Cosgrove brought this change] Update INSTALL_CMAKE filename to INSTALL_CMAKE.md (#445) Fixing for #429 - [Wallace Souza brought this change] Rename INSTALL_CMAKE to INTALL_CMAKE.md (#429) Adding Markdown file extension in order to Github render the instructions properly Will Cosgrove (17 Dec 2019) - [Daniel Stenberg brought this change] include/libssh2.h: fix comment: the known host key uses 4 bits (#438) - [Zenju brought this change] ssh-ed25519: Support PKIX + calc pubkey from private (#416) Files: openssl.c/h Author: Zenju Notes: Adds support for PKIX key reading by fixing: _libssh2_pub_priv_keyfile() is missing the code to extract the ed25519 public key from a given private key _libssh2_ed25519_new_private_frommemory is only parsing the openssh key format but does not understand PKIX (as retrieved via PEM_read_bio_PrivateKey) GitHub (15 Oct 2019) - [Will Cosgrove brought this change] .travis.yml: Fix Chrome and 32 bit builds (#423) File: .travis.yml Notes: * Fix Chrome installing by using Travis build in directive * Update to use libgcrypt20-dev package to fix 32 bit builds based on comments found here: https://launchpad.net/ubuntu/xenial/i386/libgcrypt11-dev - [Will Cosgrove brought this change] packet.c: improved parsing in packet_x11_open (#410) Use new API to parse data in packet_x11_open() for better bounds checking. Will Cosgrove (12 Sep 2019) - [Michael Buckley brought this change] knownhost.c: Double the static buffer size when reading and writing known hosts (#409) Notes: We had a user who was being repeatedly prompted to accept a server key repeatedly. It turns out the base64-encoded key was larger than the static buffers allocated to read and write known hosts. I doubled the size of these buffers. Credit: Michael Buckley GitHub (4 Sep 2019) - [Will Cosgrove brought this change] packet.c: improved packet parsing in packet_queue_listener (#404) * improved bounds checking in packet_queue_listener file: packet.c notes: improved parsing packet in packet_queue_listener - [Will Cosgrove brought this change] packet.c: improve message parsing (#402) * packet.c: improve parsing of packets file: packet.c notes: Use _libssh2_get_string API in SSH_MSG_DEBUG/SSH_MSG_DISCONNECT. Additional uint32 bounds check in SSH_MSG_GLOBAL_REQUEST. - [Will Cosgrove brought this change] misc.c: _libssh2_ntohu32 cast bit shifting (#401) To quite overly aggressive analyzers. Note, the builds pass, Travis is having some issues with Docker images. - [Will Cosgrove brought this change] kex.c: improve bounds checking in kex_agree_methods() (#399) file: kex.c notes: use _libssh2_get_string instead of kex_string_pair which does additional checks Will Cosgrove (23 Aug 2019) - [Fabrice Fontaine brought this change] acinclude.m4: add mbedtls to LIBS (#371) Notes: This is useful for static builds so that the Libs.private field in libssh2.pc contains correct info for the benefit of pkg-config users. Static link with libssh2 requires this information. Signed-off-by: Baruch Siach [Retrieved from: https://git.buildroot.net/buildroot/tree/package/libssh2/0002-acinclude.m4-add-mbedtls-to-LIBS.patch] Signed-off-by: Fabrice Fontaine Credit: Fabrice Fontaine - [jethrogb brought this change] Generate debug info when building with MSVC (#178) files: CMakeLists.txt notes: Generate debug info when building with MSVC credit: jethrogb - [Panos brought this change] Add agent forwarding implementation (#219) files: channel.c, test_agent_forward_succeeds.c, libssh2_priv.h, libssh2.h, ssh2_agent_forwarding.c notes: * Adding SSH agent forwarding. * Fix agent forwarding message, updated example. Added integration test code and cmake target. Added example to cmake list. credit: pkittenis GitHub (2 Aug 2019) - [Will Cosgrove brought this change] Update EditorConfig Added max_line_length = 80 - [Will Cosgrove brought this change] global.c : fixed call to libssh2_crypto_exit #394 (#396) * global.c : fixed call to libssh2_crypto_exit #394 File: global.c Notes: Don't call `libssh2_crypto_exit()` until `_libssh2_initialized` count is down to zero. Credit: seba30 Will Cosgrove (30 Jul 2019) - [hlefebvre brought this change] misc.c : Add an EWOULDBLOCK check for better portability (#172) File: misc.c Notes: Added support for all OS' that implement EWOULDBLOCK, not only VMS Credit: hlefebvre - [Etienne Samson brought this change] userauth.c: fix off by one error when loading public keys with no id (#386) File: userauth.c Credit: Etienne Samson Notes: Caught by ASAN: ================================================================= ==73797==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60700001bcf0 at pc 0x00010026198d bp 0x7ffeefbfed30 sp 0x7ffeefbfe4d8 READ of size 69 at 0x60700001bcf0 thread T0 2019-07-04 08:35:30.292502+0200 atos[73890:2639175] examining /Users/USER/*/libssh2_clar [73797] #0 0x10026198c in wrap_memchr (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x1f98c) #1 0x1000f8e66 in file_read_publickey userauth.c:633 #2 0x1000f2dc9 in userauth_publickey_fromfile userauth.c:1513 #3 0x1000f2948 in libssh2_userauth_publickey_fromfile_ex userauth.c:1590 #4 0x10000e254 in test_userauth_publickey__ed25519_auth_ok publickey.c:69 #5 0x1000090c3 in clar_run_test clar.c:260 #6 0x1000038f3 in clar_run_suite clar.c:343 #7 0x100003272 in clar_test_run clar.c:522 #8 0x10000c3cc in main runner.c:60 #9 0x7fff5b43b3d4 in start (libdyld.dylib:x86_64+0x163d4) 0x60700001bcf0 is located 0 bytes to the right of 80-byte region [0x60700001bca0,0x60700001bcf0) allocated by thread T0 here: #0 0x10029e053 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x5c053) #1 0x1000b4978 in libssh2_default_alloc session.c:67 #2 0x1000f8aba in file_read_publickey userauth.c:597 #3 0x1000f2dc9 in userauth_publickey_fromfile userauth.c:1513 #4 0x1000f2948 in libssh2_userauth_publickey_fromfile_ex userauth.c:1590 #5 0x10000e254 in test_userauth_publickey__ed25519_auth_ok publickey.c:69 #6 0x1000090c3 in clar_run_test clar.c:260 #7 0x1000038f3 in clar_run_suite clar.c:343 #8 0x100003272 in clar_test_run clar.c:522 #9 0x10000c3cc in main runner.c:60 #10 0x7fff5b43b3d4 in start (libdyld.dylib:x86_64+0x163d4) SUMMARY: AddressSanitizer: heap-buffer-overflow (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x1f98c) in wrap_memchr Shadow bytes around the buggy address: 0x1c0e00003740: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fd fd 0x1c0e00003750: fd fd fd fd fd fd fd fa fa fa fa fa 00 00 00 00 0x1c0e00003760: 00 00 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 0x1c0e00003770: 00 00 00 fa fa fa fa fa fd fd fd fd fd fd fd fd 0x1c0e00003780: fd fd fa fa fa fa fd fd fd fd fd fd fd fd fd fa =>0x1c0e00003790: fa fa fa fa 00 00 00 00 00 00 00 00 00 00[fa]fa 0x1c0e000037a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c0e000037b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c0e000037c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c0e000037d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x1c0e000037e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc - [Thilo Schulz brought this change] openssl.c : Fix use-after-free crash on reinitialization of openssl backend file : openssl.c notes : libssh2's openssl backend has a use-after-free condition if HAVE_OPAQUE_STRUCTS is defined and you call libssh2_init() again after prior initialisation/deinitialisation of libssh2 credit : Thilo Schulz - [axjowa brought this change] openssl.h : Use of ifdef where if should be used (#389) File : openssl.h Notes : LIBSSH2_ECDSA and LIBSSH2_ED25519 are always defined so the #ifdef checks would never be false. This change makes it possible to build libssh2 against OpenSSL built without EC support. Change-Id: I0a2f07c2d80178314dcb7d505d1295d19cf15afd Credit : axjowa - [Zenju brought this change] Agent.c : Preserve error info from agent_list_identities() (#374) Files : agent.c Notes : Currently the error details as returned by agent_transact_pageant() are overwritten by a generic "agent list id failed" message by int agent_list_identities(LIBSSH2_AGENT* agent). Credit : Zenju - [Who? Me?! brought this change] Channel.c: Make sure the error code is set in _libssh2_channel_open() (#381) File : Channel.c Notes : if _libssh2_channel_open() fails, set the error code. Credit : mark-i-m - [Orgad Shaneh brought this change] Kex.c, Remove unneeded call to strlen (#373) File : Kex.c Notes : Removed call to strlen Credit : Orgad Shaneh - [Pedro Monreal brought this change] Spelling corrections (#380) Files : libssh2.h, libssh2_sftp.h, bcrypt_pbkdf.c, mbedtls.c, sftp.c, ssh2.c Notes : * Fixed misspellings Credit : Pedro Monreal - [Sebastián Katzer brought this change] Fix Potential typecast error for `_libssh2_ecdsa_key_get_curve_type` (#383) Issue : #383 Files : hostkey.c, crypto.h, openssl.c Notes : * Fix potential typecast error for `_libssh2_ecdsa_key_get_curve_type` * Rename _libssh2_ecdsa_key_get_curve_type to _libssh2_ecdsa_get_curve_type Credit : Sebastián Katzer GitHub (20 Jun 2019) - [Will Cosgrove brought this change] bump copyright date Version 1.9.0 (19 Jun 2019) GitHub (19 Jun 2019) - [Will Cosgrove brought this change] 1.9 Formatting - [Will Cosgrove brought this change] 1.9 Release notes Will Cosgrove (17 May 2019) - [Alexander Curtiss brought this change] libgcrypt.c : Fixed _libssh2_rsa_sha1_sign memory leak. (#370) File: libgcrypt.c Notes : Added calls to gcry_sexp_release to free memory allocated by gcry_sexp_find_token Credit : Reporter : beckmi PR by: Alexander Curtiss - [Orivej Desh brought this change] libssh2_priv.h : Fix musl build warning on sys/poll.h (#346) File : libssh2_priv.h Notes : musl prints `redirecting incorrect #include to ` http://git.musl-libc.org/cgit/musl/commit/include/sys/poll.h?id=54446d730cfb17c5f7bcf57f139458678f5066cc poll is defined by POSIX to be in poll.h: http://pubs.opengroup.org/onlinepubs/7908799/xsh/poll.html Credit : Orivej Desh GitHub (1 May 2019) - [Will Cosgrove brought this change] kex.c : additional bounds checks in diffie_hellman_sha1/256 (#361) Files : kex.c, misc.c, misc.h Notes : Fixed possible out of bounds memory access when reading malformed data in diffie_hellman_sha1() and diffie_hellman_sha256(). Added _libssh2_copy_string() to misc.c to return an allocated and filled char buffer from a string_buf offset. Removed no longer needed s var in kmdhgGPshakex_state_t. Will Cosgrove (26 Apr 2019) - [Tseng Jun brought this change] sftp.c : sftp_bin2attr() Correct attrs->gid assignment (#366) Regression with fix for #339 Credit : Tseng Jun - [Tseng Jun brought this change] kex.c : Correct type cast in curve25519_sha256() (#365) GitHub (24 Apr 2019) - [Will Cosgrove brought this change] transport.c : scope local total_num var (#364) file : transport.c notes : move local `total_num` variable inside of if block to prevent scope access issues which caused #360. Will Cosgrove (24 Apr 2019) - [doublex brought this change] transport.c : fixes bounds check if partial packet is read Files : transport.c Issue : #360 Notes : 'p->total_num' instead of local value total_num when doing bounds check. Credit : Doublex GitHub (23 Apr 2019) - [Will Cosgrove brought this change] Editor config file for source files (#322) Simple start to an editor config file when editing source files to make sure they are configured correctly. - [Will Cosgrove brought this change] misc.c : String buffer API improvements (#332) Files : misc.c, hostkey.c, kex.c, misc.h, openssl.c, sftp.c Notes : * updated _libssh2_get_bignum_bytes and _libssh2_get_string. Now pass in length as an argument instead of returning it to keep signedness correct. Now returns -1 for failure, 0 for success. _libssh2_check_length now returns 0 on success and -1 on failure to match the other string_buf functions. Added comment to _libssh2_check_length. Credit : Will Cosgrove Will Cosgrove (19 Apr 2019) - [doublex brought this change] mbedtls.c : _libssh2_mbedtls_rsa_new_private_frommemory() allow private-key from memory (#359) File : mbedtls.c Notes: _libssh2_mbedtls_rsa_new_private_frommemory() fixes private-key from memory reading to by adding NULL terminator before parsing; adds passphrase support. Credit: doublex - [Ryan Kelley brought this change] Session.c : banner_receive() from leaking when accessing non ssh ports (#356) File : session.c Release previous banner in banner_receive() if the session is reused after a failed connection. Credit : Ryan Kelley GitHub (11 Apr 2019) - [Will Cosgrove brought this change] Formatting in agent.c Removed whitespace. - [Will Cosgrove brought this change] Fixed formatting in agent.c Quiet linter around a couple if blocks and pointer. Will Cosgrove (11 Apr 2019) - [Zhen-Huan HWANG brought this change] sftp.c : discard and reset oversized packet in sftp_packet_read() (#269) file : sftp.c notes : when sftp_packet_read() encounters an sftp packet which exceeds SFTP max packet size it now resets the reading state so it can continue reading. credit : Zhen-Huan HWANG GitHub (11 Apr 2019) - [Will Cosgrove brought this change] Add agent functions libssh2_agent_get_identity_path() and libssh2_agent_set_identity_path() (#308) File : agent.c Notes : Libssh2 uses the SSH_AUTH_SOCK env variable to read the system agent location. However, when using a custom agent path you have to set this value using setenv which is not thread-safe. The new functions allow for a way to set a custom agent socket path in a thread safe manor. - [Will Cosgrove brought this change] Simplified _libssh2_check_length (#350) * Simplified _libssh2_check_length misc.c : _libssh2_check_length() Removed cast and improved bounds checking and format. Credit : Yuriy M. Kaminskiy - [Will Cosgrove brought this change] _libssh2_check_length() : additional bounds check (#348) Misc.c : _libssh2_check_length() Ensure the requested length is less than the total length before doing the additional bounds check Daniel Stenberg (25 Mar 2019) - misc: remove 'offset' from string_buf It isn't necessary. Closes #343 - sftp: repair mtime from e1ead35e475 A regression from e1ead35e4759 broke the SFTP mtime logic in sftp_bin2attr Also simplified the _libssh2_get_u32/u64 functions slightly. Closes #342 - session_disconnect: don't zero state, just clear the right bit If we clear the entire field, the freeing of data in session_free() is skipped. Instead just clear the bit that risk making the code get stuck in the transport functions. Regression from 4d66f6762ca3fc45d9. Reported-by: dimmaq on github Fixes #338 Closes #340 - libssh2_sftp.h: restore broken ABI Commit 41fbd44 changed variable sizes/types in a public struct which broke the ABI, which breaks applications! This reverts that change. Closes #339 - style: make includes and examples code style strict make travis and the makefile rule verify them too Closes #334 GitHub (21 Mar 2019) - [Daniel Stenberg brought this change] create a github issue template Daniel Stenberg (21 Mar 2019) - stale-bot: activated The stale bot will automatically mark stale issues (inactive for 90 days) and if still untouched after 21 more days, close them. See https://probot.github.io/apps/stale/ - libssh2_session_supported_algs.3: fix formatting mistakes Reported-by: Max Horn Fixes #57 - [Zenju brought this change] libssh2.h: Fix Error C2371 'ssize_t': redefinition Closes #331 - travis: add code style check Closes #324 - code style: unify code style Indent-level: 4 Max columns: 79 No spaces after if/for/while Unified brace positions Unified white spaces - src/checksrc.pl: code style checker imported as-is from curl Will Cosgrove (19 Mar 2019) - Merge branch 'MichaelBuckley-michaelbuckley-security-fixes' - Silence unused var warnings (#329) Silence warnings about unused variables in this test - Removed unneeded > 0 check When checking `userauth_kybd_num_prompts > 100` we don't care if it's also above zero. - [Matthew D. Fuller brought this change] Spell OpenSS_H_ right when talking about their specific private key (#321) Good catch, thanks. GitHub (19 Mar 2019) - [Will Cosgrove brought this change] Silence unused var warnings (#329) Silence warnings about unused variables in this test Michael Buckley (19 Mar 2019) - Fix more scope and printf warning errors - Silence unused variable warning GitHub (19 Mar 2019) - [Will Cosgrove brought this change] Removed unneeded > 0 check When checking `userauth_kybd_num_prompts > 100` we don't care if it's also above zero. Will Cosgrove (19 Mar 2019) - [Matthew D. Fuller brought this change] Spell OpenSS_H_ right when talking about their specific private key (#321) Good catch, thanks. Michael Buckley (18 Mar 2019) - Fix errors identified by the build process - Fix casting errors after merge GitHub (18 Mar 2019) - [Michael Buckley brought this change] Merge branch 'master' into michaelbuckley-security-fixes Michael Buckley (18 Mar 2019) - Move fallback SIZE_MAX and UINT_MAX to libssh2_priv.h - Fix type and logic issues with _libssh2_get_u64 Daniel Stenberg (17 Mar 2019) - examples: fix various compiler warnings - lib: fix various compiler warnings - session: ignore pedantic warnings for funcpointer <=> void * - travis: add a build using configure Closes #320 - configure: provide --enable-werror - appveyor: remove old builds that mostly cause failures ... and only run on master branch. Closes #323 - cmake: add two missing man pages to get installed too Both libssh2_session_handshake.3 and libssh2_userauth_publickey_frommemory.3 were installed by the configure build already. Reported-by: Arfrever on github Fixes #278 - include/libssh2.h: warning: "_WIN64" is not defined, evaluates to 0 We don't use #if for defines that might not be defined. - pem: //-comments are not allowed Will Cosgrove (14 Mar 2019) - [Daniel Stenberg brought this change] userauth: fix "Function call argument is an uninitialized value" (#318) Detected by scan-build. - fixed unsigned/signed issue Daniel Stenberg (15 Mar 2019) - session_disconnect: clear state If authentication is started but not completed before the application gives up and instead wants to shut down the session, the '->state' field might still be set and thus effectively dead-lock session_disconnect. This happens because both _libssh2_transport_send() and _libssh2_transport_read() refuse to do anything as long as state is set without the LIBSSH2_STATE_KEX_ACTIVE bit. Reported in curl bug https://github.com/curl/curl/issues/3650 Closes #310 Will Cosgrove (14 Mar 2019) - Release notes from 1.8.1 Michael Buckley (14 Mar 2019) - Use string_buf in sftp_init(). - Guard against out-of-bounds reads in publickey.c - Guard against out-of-bounds reads in session.c - Guard against out-of-bounds reads in userauth.c - Use LIBSSH2_ERROR_BUFFER_TOO_SMALL instead of LIBSSH2_ERROR_OUT_OF_BOUNDARY in sftp.c - Additional bounds checking in sftp.c - Additional length checks to prevent out-of-bounds reads and writes in _libssh2_packet_add(). https://libssh2.org/CVE-2019-3862.html - Add a required_size parameter to sftp_packet_require et. al. to require callers of these functions to handle packets that are too short. https://libssh2.org/CVE-2019-3860.html - Check the length of data passed to sftp_packet_add() to prevent out-of-bounds reads. - Prevent zero-byte allocation in sftp_packet_read() which could lead to an out-of-bounds read. https://libssh2.org/CVE-2019-3858.html - Sanitize padding_length - _libssh2_transport_read(). https://libssh2.org/CVE-2019-3861.html This prevents an underflow resulting in a potential out-of-bounds read if a server sends a too-large padding_length, possibly with malicious intent. - Defend against writing beyond the end of the payload in _libssh2_transport_read(). - Defend against possible integer overflows in comp_method_zlib_decomp. GitHub (14 Mar 2019) - [Will Cosgrove brought this change] Security fixes (#315) * Bounds checks Fixes for CVEs https://www.libssh2.org/CVE-2019-3863.html https://www.libssh2.org/CVE-2019-3856.html * Packet length bounds check CVE https://www.libssh2.org/CVE-2019-3855.html * Response length check CVE https://www.libssh2.org/CVE-2019-3859.html * Bounds check CVE https://www.libssh2.org/CVE-2019-3857.html * Bounds checking CVE https://www.libssh2.org/CVE-2019-3859.html and additional data validation * Check bounds before reading into buffers * Bounds checking CVE https://www.libssh2.org/CVE-2019-3859.html * declare SIZE_MAX and UINT_MAX if needed - [Will Cosgrove brought this change] fixed type warnings (#309) - [Will Cosgrove brought this change] Bumping version number for pending 1.8.1 release Will Cosgrove (4 Mar 2019) - [Daniel Stenberg brought this change] _libssh2_string_buf_free: use correct free (#304) Use LIBSSH2_FREE() here, not free(). We allow memory function replacements so free() is rarely the right choice... GitHub (26 Feb 2019) - [Will Cosgrove brought this change] Fix for building against libreSSL #302 Changed to use the check we use elsewhere. - [Will Cosgrove brought this change] Fix for when building against LibreSSL #302 Will Cosgrove (25 Feb 2019) - [gartens brought this change] docs: update libssh2_hostkey_hash.3 [ci skip] (#301) GitHub (21 Feb 2019) - [Will Cosgrove brought this change] fix malloc/free mismatches #296 (#297) - [Will Cosgrove brought this change] Replaced malloc with calloc #295 - [Will Cosgrove brought this change] Abstracted OpenSSL calls out of hostkey.c (#294) - [Will Cosgrove brought this change] Fix memory dealloc impedance mis-match #292 (#293) When using ed25519 host keys and a custom memory allocator. - [Will Cosgrove brought this change] Added call to OpenSSL_add_all_digests() #288 For OpenSSL 1.0.x we need to call OpenSSL_add_all_digests(). Will Cosgrove (12 Feb 2019) - [Zhen-Huan HWANG brought this change] SFTP: increase maximum packet size to 256K (#268) to match implementations like OpenSSH. - [Zenju brought this change] Fix https://github.com/libssh2/libssh2/pull/271 (#284) GitHub (16 Jan 2019) - [Will Cosgrove brought this change] Agent NULL check in shutdown #281 Will Cosgrove (15 Jan 2019) - [Adrian Moran brought this change] mbedtls: Fix leak of 12 bytes by each key exchange. (#280) Correctly free ducts by calling _libssh2_mbedtls_bignum_free() in dtor. - [alex-weaver brought this change] Fix error compiling on Win32 with STDCALL=ON (#275) GitHub (8 Nov 2018) - [Will Cosgrove brought this change] Allow default permissions to be used in sftp_mkdir (#271) Added constant LIBSSH2_SFTP_DEFAULT_MODE to use the server default permissions when making a new directory Will Cosgrove (13 Sep 2018) - [Giulio Benetti brought this change] openssl: fix dereferencing ambiguity potentially causing build failure (#267) When dereferencing from *aes_ctr_cipher, being a pointer itself, ambiguity can occur; fixed possible build errors. Viktor Szakats (12 Sep 2018) - win32/GNUmakefile: define HAVE_WINDOWS_H This macro was only used in test/example code before, now it is also used in library code, but only defined automatically by automake/cmake, so let's do the same for the standalone win32 make file. It'd be probably better to just rely on the built-in _WIN32 macro to detect the presence of windows.h though. It's already used in most of libssh2 library code. There is a 3rd, similar macro named LIBSSH2_WIN32, which might also be replaced with _WIN32. Ref: https://github.com/libssh2/libssh2/commit/8b870ad771cbd9cd29edbb3dbb0878e950f868ab Closes https://github.com/libssh2/libssh2/pull/266 Marc Hoersken (2 Sep 2018) - Fix conditional check for HAVE_DECL_SECUREZEROMEMORY "Unlike the other `AC_CHECK_*S' macros, when a symbol is not declared, HAVE_DECL_symbol is defined to `0' instead of leaving HAVE_DECL_symbol undeclared. When you are sure that the check was performed, use HAVE_DECL_symbol in #if." Source: autoconf documentation for AC_CHECK_DECLS. - Fix implicit declaration of function 'SecureZeroMemory' Include window.h in order to use SecureZeroMemory on Windows. - Fix implicit declaration of function 'free' by including stdlib.h GitHub (27 Aug 2018) - [Will Cosgrove brought this change] Use malloc abstraction function in pem parse Fix warning on WinCNG build. - [Will Cosgrove brought this change] Fixed possible junk memory read in sftp_stat #258 - [Will Cosgrove brought this change] removed INT64_C define (#260) No longer used. - [Will Cosgrove brought this change] Added conditional around engine.h include Will Cosgrove (6 Aug 2018) - [Alex Crichton brought this change] Fix OpenSSL link error with `no-engine` support (#259) This commit fixes linking against an OpenSSL library that was compiled with `no-engine` support by bypassing the initialization routines as they won't be available anyway. GitHub (2 Aug 2018) - [Will Cosgrove brought this change] ED25519 Key Support #39 (#248) OpenSSH Key and ED25519 support #39 Added _libssh2_explicit_zero() to explicitly zero sensitive data in memory #120 * ED25519 Key file support - Requires OpenSSL 1.1.1 or later * OpenSSH Key format reading support - Supports RSA/DSA/ECDSA/ED25519 types * New string buffer reading functions - These add build-in bounds checking and convenance methods. Used for OpenSSL PEM file reading. * Added new tests for OpenSSH formatted Keys - [Will Cosgrove brought this change] ECDSA key types are now explicit (#251) * ECDSA key types are now explicit Issue was brough up in pull request #248 doc/nghttp2/README.rst000064400000140612152527666270010414 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 3c6315e00ab02d7bc9b8922aff1f85d8f81ee130); or OpenSSL >= 3.5.0 * `ngtcp2 `_ >= 1.23.0 * `nghttp3 `_ >= 1.17.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++23 compliant compiler is required. At least g++ >= 14 and clang++ >= 19 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 v5.4.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.18.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.25.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.7.0 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, use ``--h3`` option (or ``--alpn-list=h3`` option) like so: .. code-block:: text $ h2load --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.1000064400000264464152527666270007773 0ustar00.\" Man page generated from reStructuredText .\" by the Docutils 0.22.4 manpage writer. . . .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" "Jul 29, 2026" "1.70.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 \fB\-\-frontend\fP option. .UNINDENT .INDENT 0.0 .TP .B Set path to server\(aqs certificate. Required unless \(dqno\-tls\(dq parameter is used in \fB\-\-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, \fB\-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 \fB\-b\fP\(aq127.0.0.1,8080;nghttp2.org:www.nghttp2.org\(aq has the same effect to specify \fB\-b\fP\(aq127.0.0.1,8080;nghttp2.org\(aq and \fB\-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 \fB\-\-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, \fB\-\-backend\-read\-timeout\fP and \fB\-\-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 \fB\-\-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 \%/[:@]:. 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 \fB\-\-backend\-read\-timeout\fP and \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-http2\-proxy\fP option, use \fB\-\-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 \-\-frontend\-stream\-read\-timeout= Specify read timeout for HTTP/2 and HTTP/3 streams in the frontend connection. 0 means no timeout. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-stream\-write\-timeout= Specify write timeout for HTTP/2 and HTTP/3 streams in the frontend connection. 0 means no timeout. .sp Default: \fB1m\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-stream\-read\-timeout= Specify read timeout for HTTP/2 streams in the backend connection. 0 means no timeout. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-backend\-stream\-write\-timeout= Specify write timeout for HTTP/2 streams in the backend connection. 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 \fB\-\-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 .INDENT 0.0 .TP .B \-\-frontend\-min\-write\-rate= Set the minimum rate of stream data that client must read from frontend connection. The specifies the number of bytes per second. If client is unable to read at least the given rate, the connection is closed. The implementation extends the timeout by the stream data to send. Use \fB\-\-frontend\-initial\-write\-rate\-timeout\fP to specify the initial timeout. Use \fB\-\-frontend\-max\-write\-rate\-timeout\fP to set the maximum timeout. Setting 0 disables this feature. .sp Default: \fB0\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-initial\-write\-rate\-timeout= Set the initial timeout set by \fB\-\-frontend\-min\-write\-rate\fP feature. .sp Default: \fB10s\fP .UNINDENT .INDENT 0.0 .TP .B \-\-frontend\-max\-write\-rate\-timeout= Set the maximum timeout set by \fB\-\-frontend\-min\-write\-rate\fP feature. .sp Default: \fB1m\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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-tls\-min\-proto\-version\fP and \fB\-\-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 \fB\-\-tls\-min\-proto\-version\fP and \fB\-\-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 \fB\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly 48 bytes. If aes\-256\-cbc is given in \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \% 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 \% 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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 .INDENT 0.0 .TP .B \-\-ech\-config\-file= Read Encrypted Client Hello (ECH) server configuration from . See \fB\-\-ech\-retry\-config\-file\fP for details. .UNINDENT .INDENT 0.0 .TP .B \-\-ech\-retry\-config\-file= This option and \fB\-\-ech\-config\-file\fP option read Encrypted Client Hello (ECH) server configuration from . If \fB\-\-ech\-retry\-config\-file\fP is used, the configurations are included in the retry configurations. The file format must be PEM ECH file described in RFC 9934. These options can be used repeatedly to read multiple files. \fB\-\-ech\-retry\-config\-file\fP must be used at least once when enabling ECH. .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 \fB\-\-frontend\-http2\-connection\-window\-size\fP\&. Since the stream is subject to stream level window size, it should be adjusted using \fB\-\-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 \fB\-\-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, \fB\-\-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 $tls_ech_accepted: \(dqe\(dq if ECH was accepted in SSL/TLS session. Otherwise, \(dq.\(dq .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 \fB\-\-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, \fB\-\-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 \fB\-\-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 \fB\-\-forwarded\-by\fP and \fB\-\-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 \fB\-\-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 \fB\-\-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: \fB\-\-altsvc\fP=\(dqh2,443,,,ma=3600; persist=1\(dq .UNINDENT .INDENT 0.0 .TP .B \-\-http2\-altsvc= Just like \fB\-\-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: \fB\-\-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: \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-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 \fB\-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 \fB\-n\fP=N, where N >= 2. .UNINDENT .SS Process .INDENT 0.0 .TP .B \-D, \-\-daemon Run in a background. If \fB\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 \fB\-\-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 (RFC 5988 \%) in response headers from backend server and extracts URI\-reference with parameter \fBrel=preload\fP (see preload \%) 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 \fB\-\-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 \fB\-\-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 \fB\-\-tls\-ticket\-key\-cipher\fP=aes\-128\-cbc is used, LEN must be 48. If \fB\-\-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 \fB\-\-tls\-ticket\-key\-memcached\fP option. .sp If \fB\-\-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 (RFC 6962 \%). The relevant options are \fB\-\-tls\-sct\-dir\fP and \fBsct\-dir\fP parameter in \fB\-\-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 section 3.2 of RFC 69662 \%\&. This format is the same one used by nginx\-ct \% and mod_ssl_ct \%\&. ct\-submit \% 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 \fB\-\-mruby\-file\fP option and is called for all requests. The per\-pattern mruby script is set by \(dqmruby\(dq parameter in \fB\-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 \fBNghttpx::Env\fP object on request hook. Similarly, if app object defines \fBon_resp\fP method, it is called with \fBNghttpx::Env\fP object on response hook. For each method invocation, user can can access \fBNghttpx::Request\fP and \fBNghttpx::Response\fP objects via \fBNghttpx::Env#req\fP and \fBNghttpx::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 \fBRequest\fP object. .UNINDENT .INDENT 7.0 .TP .B attribute [R] resp Return \fBResponse\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 \fB\-\-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 \%), 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 \fBNghttpx::Request#add_header\fP or \fBNghttpx::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 \fBNghttpx::Response#add_header\fP or \fBNghttpx::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 \fBNghttpx::Response#status\fP\&. If status code is not set, 200 is used. To set response header fields, \fBNghttpx::Response#add_header\fP and \fBNghttpx::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 \fBNghttpx::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 \fBNghttpx::Response#return\fP is called. This method can be called multiple times. It cannot be called after \fBNghttpx::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 \fB\-\-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 FILES section. The line separator inside the request body must be single LF (0x0A). Currently, only \fBbackend\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 \fBbackend\fP option is found in request body, the current set of backend is replaced with the \fBbackend\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 \fBbackend\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 \fB\-\-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 .\" End of generated man page. man/man1/h2load.1000064400000036445152527666270007444 0ustar00.\" Man page generated from reStructuredText .\" by the Docutils 0.22.4 manpage writer. . . .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" "Jul 29, 2026" "1.70.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 \fB\-\-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 \fB\-\-duration\fP option). .sp Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP .B \-c, \-\-clients= Number of concurrent clients. With \fB\-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 \fB\-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 \fB\-c\fP option. This rate will be distributed among threads as evenly as possible. For example, with \fB\-t\fP2 and \fB\-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. \fB\-r\fP and \fB\-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. \fB\-D\fP and \fB\-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 \fB\-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 \fB\-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 \fB\-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. \fB\-\-timing\-script\-file\fP and \fB\-\-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 \fB\-\-alpn\-list\fP=http/1.1 \fB\-\-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 \-\-h3 Short hand for \fB\-\-alpn\-list\fP=h3, which effectively forces HTTP/3. .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. \fB\-\-rps\fP and \fB\-\-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 \-\-histogram Plot histogram for performance statistics. .UNINDENT .INDENT 0.0 .TP .B \-\-tls\-session\-file= Read TLS session from , and set it to all TLS connections to perform the session resumption. It is also used to store the new TLS session. At most one session is written to the given file. .UNINDENT .INDENT 0.0 .TP .B \-\-output\-file= Write the measurement results to in JSON format. This basically includes all numbers reported to the normal output. In addition, for performance measurements, all raw samples are included. .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 .SS REQUEST METRICS .INDENT 0.0 .TP .B requests .INDENT 7.0 .TP .B total The total number of requests h2load was instructed to make. .TP .B started The number of requests initiated by the tool. .TP .B done The number of requests that reached completion. .TP .B succeeded Requests resulting in an HTTP 2xx or 3xx status code. .TP .B failed The total number of failed requests. This includes both \fBerrored\fP requests and requests that completed with a non\-2xx/3xx status code. .TP .B errored A subset of \fBfailed\fP where the requests failed due to network\-level issues (e.g., TCP resets, \fBRST_STREAM\fP) rather than HTTP status codes. .TP .B timeout A subset of \fBerrored\fP where the connection timed out before completion. .UNINDENT .TP .B status codes The specific count of received HTTP status codes categorized by class (2xx, 3xx, 4xx, 5xx). .UNINDENT .SS TRAFFIC METRICS .INDENT 0.0 .TP .B traffic .INDENT 7.0 .TP .B total Total application data bytes received \(dqon the wire\(dq (decrypted if using TLS). .TP .B headers Total bytes used for response headers (pre\-decompression). .INDENT 7.0 .TP .B space savings Header compression efficiency, calculated as: .sp (1 \- headers / decompressed_headers) * 100 .sp where \fBheaders\fP is the compressed size and \fBdecompressed_headers\fP is the size after decompression. .UNINDENT .TP .B data Total bytes received in response bodies. .UNINDENT .UNINDENT .SS PERFORMANCE STATISTICS .INDENT 0.0 .TP .B Metric Definitions .INDENT 7.0 .TP .B request The duration from sending the first byte of a request to receiving the last byte of the response. .TP .B connect The time taken to establish a connection, including TLS handshakes. .TP .B TTFB The duration until the first byte of application data is received from the server (decrypted if using TLS). .TP .B req/s The requests per second measured individually across all clients. .TP .B min RTT The minimum RTT (QUIC). .TP .B smoothed RTT The smoothed RTT (QUIC). .TP .B packets sent The number of packets sent (QUIC). .TP .B packets recv The number of packets received (QUIC). .TP .B packets lost The number of packets declared lost (QUIC). .TP .B GRO packets The number of packets received in a single recvmsg call (QUIC). .UNINDENT .TP .B Distribution Fields .INDENT 7.0 .TP .B min / max The absolute minimum and maximum values recorded. .TP .B median The 50th percentile value. .TP .B p95 / p99 The 95th and 99th percentiles, indicating tail performance. .TP .B mean The arithmetic average of all samples. .TP .B sd The standard deviation (measure of data dispersion). .TP .B +/\- sd The percentage of successful samples falling within one standard deviation of the mean (mean +/\- sd). .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 \fB\-w\fP and \fB\-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 .\" End of generated man page. man/man1/nghttpd.1000064400000012724152527666270007735 0ustar00.\" Man page generated from reStructuredText .\" by the Docutils 0.22.4 manpage writer. . . .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" "Jul 29, 2026" "1.70.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 \fB\-\-no\-tls\fP is specified. .UNINDENT .INDENT 0.0 .TP .B Set path to server\(aqs certificate. Required unless \fB\-\-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 \fB\-D\fP is used, the current working directory is changed to \(aq\fI/\fP\(aq. Therefore if this option is used, \fB\-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 \fB\-\-htdocs\fP option. Example: \fB\-p\fP/=/foo.png \fB\-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: \fB\-\-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 .\" End of generated man page. man/man1/nghttp.1000064400000015355152527666270007574 0ustar00.\" Man page generated from reStructuredText .\" by the Docutils 0.22.4 manpage writer. . . .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" "Jul 29, 2026" "1.70.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: \fB\-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 \fB\-d\fP option to send request body. Example: \fB\-\-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 \fB\-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 \fB\-\-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 \fB\-\-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 \fB\-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 .\" End of generated man page. perl5/Types/Serialiser/Error.pm000044400000000703152530123070012424 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/Types/Serialiser.pm000044400000021674152530123070011345 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/HTTP/Tiny.pm000044400000236420152530123070007636 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.088'; 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 TLS/SSL #pod certificate of an C — connection (default is true). Changed from false #pod to true in version 0.083. #pod * C — A hashref of C — options to pass through to #pod L #pod * C<$ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT}> - Changes the default #pod certificate verification behavior to not check server identity if set to 1. #pod Only effective if C is not set. Added in version 0.083. #pod #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) = @_; # Support lower case verify_ssl argument, but only if verify_SSL is not # true. if ( exists $args{verify_ssl} ) { $args{verify_SSL} ||= $args{verify_ssl}; } my $self = { max_redirect => 5, timeout => defined $args{timeout} ? $args{timeout} : 60, keep_alive => 1, verify_SSL => defined $args{verify_SSL} ? $args{verify_SSL} : _verify_SSL_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 _verify_SSL_default { my ($self) = @_; # Check if insecure default certificate verification behaviour has been # changed by the user by setting PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT=1 return (($ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT} || '') eq '1') ? 0 : 1; } 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; } return $self->request('POST', $url, { # Any existing 'headers' key in $args will be overridden with a # normalized version below. %$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 Content data in the request/response is handled as "raw bytes". Any #pod encoding/decoding (with associated headers) are the responsibility of the #pod caller. #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 => HTTP::Tiny::_verify_SSL_default(), 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.088 =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 TLS/SSL certificate of an C — connection (default is true). Changed from false to true in version 0.083. =item * C — A hashref of C — options to pass through to L =item * C<$ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT}> - Changes the default certificate verification behavior to not check server identity if set to 1. Only effective if C is not set. Added in version 0.083. =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.) Content data in the request/response is handled as "raw bytes". Any encoding/decoding (with associated headers) are the responsibility of the caller. 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 TLS/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 TLS 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. TLS/SSL provides two distinct capabilities: =over 4 =item * Encrypted communication channel =item * Verification of server identity =back B. This was changed in version 0.083 due to security concerns. The previous default behavior can be enabled by setting C<$ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT}> to 1. Verification is done by checking that that the TLS/SSL connection has a valid certificate corresponding to the host name of the connection and that the certificate has been verified by a CA. Assuming you trust the CA, this will protect against L. 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. 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 =item * /etc/openssl/certs/ca-certificates.crt =item * /etc/ssl/cert.pem =item * /usr/local/share/certs/ca-root-nss.crt =item * /etc/pki/tls/cacert.pem =item * /etc/certs/ca-certificates.crt =back An error will be occur if C is true and no CA certificate file is available. If you desire complete control over TLS/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 TLS/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/Perl-Toolchain-Gang/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 Graham Knop 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 Stig Palmquist 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 * Graham Knop =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 * Stig Palmquist =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) 2023 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/lib/core/only.pm000044400000006235152530123070010612 0ustar00package lib::core::only; use strict; use warnings FATAL => 'all'; use Config; sub import { @INC = @Config{qw(privlibexp archlibexp)}; return } =head1 NAME lib::core::only - Remove all non-core paths from @INC to avoid site/vendor dirs =head1 SYNOPSIS use lib::core::only; # now @INC contains only the two core directories To get only the core directories plus the ones for the local::lib in scope: $ perl -mlocal::lib -Mlib::core::only -Mlocal::lib=~/perl5 myscript.pl To attempt to do a self-contained build (but note this will not reliably propagate into subprocesses, see the CAVEATS below): $ PERL5OPT='-mlocal::lib -Mlib::core::only -Mlocal::lib=~/perl5' cpan Please note that it is necessary to use C twice for this to work. First so that C doesn't prevent C from loading (it's not currently in core) and then again after C so that the local paths are not removed. =head1 DESCRIPTION lib::core::only is simply a shortcut to say "please reduce my @INC to only the core lib and archlib (architecture-specific lib) directories of this perl". You might want to do this to ensure a local::lib contains only the code you need, or to test an L tree, or to avoid known bad vendor packages. You might want to use this to try and install a self-contained tree of perl modules. Be warned that that probably won't work (see L). This module was extracted from L's --self-contained feature, and contains the only part that ever worked. I apologise to anybody who thought anything else did. =head1 CAVEATS This does B propagate properly across perl invocations like local::lib's stuff does. It can't. It's only a module import, so it B. If you want to cascade it across invocations, you can set the PERL5OPT environment variable to '-Mlib::core::only' and it'll sort of work. But be aware that taint mode ignores this, so some modules' build and test code probably will as well. You also need to be aware that perl's command line options are not processed in order - -I options take effect before -M options, so perl -Mlib::core::only -Ilib is unlike to do what you want - it's exactly equivalent to: perl -Mlib::core::only If you want to combine a core-only @INC with additional paths, you need to add the additional paths using -M options and the L module: perl -Mlib::core::only -Mlib=lib # or if you're trying to test compiled code: perl -Mlib::core::only -Mblib For more information on the impossibility of sanely propagating this across module builds without help from the build program, see L - and for ways to achieve the old --self-contained feature's results, look at L's tree function, and at L's --local-lib-contained feature. =head1 AUTHOR Matt S. Trout =head1 LICENSE This library is free software under the same terms as perl itself. =head1 COPYRIGHT (c) 2010 the lib::core::only L as specified above. =cut 1; perl5/Expect.pm000055500000305644152530123070007374 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; use Scalar::Util qw/ looks_like_number /; # 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.38'; # 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 timeout { my $self = shift; ${*$self}{expect_timeout} = shift if @_; return ${*$self}{expect_timeout}; } 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; if ( looks_like_number($_[0]) or not defined $_[0] ) { $timeout = shift; } else { $timeout = $self->timeout; } 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 'Regexp' ) { push @pattern_list, [ $parm_nr, '-re', $parm, undef ]; } elsif ( ref($parm) eq 'ARRAY' ) { # 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, use a regexp object (C) or prefix the pattern with '-re'. $object->expect(15, 'match me exactly', qr/match\s+me\s+exactly/); $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 you don't want to explicitly put the timeout on all calls to C, you can set it via the C method . If the first argument of C doesn't look like a number, that value will be used. $object->timeout(15); $object->expect('match me exactly','-re','match\s+me\s+exactly'); 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 perl5/CPAN/Version.pm000044400000010456152530123070010301 0ustar00package CPAN::Version; use strict; use vars qw($VERSION); $VERSION = "5.5003"; # CPAN::Version::vcmp courtesy Jost Krieger sub vcmp { my($self,$l,$r) = @_; local($^W) = 0; CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG; # treat undef as zero $l = 0 if $l eq 'undef'; $r = 0 if $r eq 'undef'; return 0 if $l eq $r; # short circuit for quicker success for ($l,$r) { s/_//g; } CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG; for ($l,$r) { next unless tr/.// > 1 || /^v/; s/^v?/v/; 1 while s/\.0+(\d)/.$1/; # remove leading zeroes per group } CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG; if ($l=~/^v/ <=> $r=~/^v/) { for ($l,$r) { next if /^v/; $_ = $self->float2vv($_); } } CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG; my $lvstring = "v0"; my $rvstring = "v0"; if ($] >= 5.006 && $l =~ /^v/ && $r =~ /^v/) { $lvstring = $self->vstring($l); $rvstring = $self->vstring($r); CPAN->debug(sprintf "lv[%vd] rv[%vd]", $lvstring, $rvstring) if $CPAN::DEBUG; } return ( ($l ne "undef") <=> ($r ne "undef") || $lvstring cmp $rvstring || $l <=> $r || $l cmp $r ); } sub vgt { my($self,$l,$r) = @_; $self->vcmp($l,$r) > 0; } sub vlt { my($self,$l,$r) = @_; $self->vcmp($l,$r) < 0; } sub vge { my($self,$l,$r) = @_; $self->vcmp($l,$r) >= 0; } sub vle { my($self,$l,$r) = @_; $self->vcmp($l,$r) <= 0; } sub vstring { my($self,$n) = @_; $n =~ s/^v// or die "CPAN::Version::vstring() called with invalid arg [$n]"; pack "U*", split /\./, $n; } # vv => visible vstring sub float2vv { my($self,$n) = @_; my($rev) = int($n); $rev ||= 0; my($mantissa) = $n =~ /\.(\d{1,12})/; # limit to 12 digits to limit # architecture influence $mantissa ||= 0; $mantissa .= "0" while length($mantissa)%3; my $ret = "v" . $rev; while ($mantissa) { $mantissa =~ s/(\d{1,3})// or die "Panic: length>0 but not a digit? mantissa[$mantissa]"; $ret .= ".".int($1); } # warn "n[$n]ret[$ret]"; $ret =~ s/(\.0)+/.0/; # v1.0.0 => v1.0 $ret; } sub readable { my($self,$n) = @_; $n =~ /^([\w\-\+\.]+)/; return $1 if defined $1 && length($1)>0; # if the first user reaches version v43, he will be treated as "+". # We'll have to decide about a new rule here then, depending on what # will be the prevailing versioning behavior then. if ($] < 5.006) { # or whenever v-strings were introduced # we get them wrong anyway, whatever we do, because 5.005 will # have already interpreted 0.2.4 to be "0.24". So even if he # indexer sends us something like "v0.2.4" we compare wrongly. # And if they say v1.2, then the old perl takes it as "v12" if (defined $CPAN::Frontend) { $CPAN::Frontend->mywarn("Suspicious version string seen [$n]\n"); } else { warn("Suspicious version string seen [$n]\n"); } return $n; } my $better = sprintf "v%vd", $n; CPAN->debug("n[$n] better[$better]") if $CPAN::DEBUG; return $better; } 1; __END__ =head1 NAME CPAN::Version - utility functions to compare CPAN versions =head1 SYNOPSIS use CPAN::Version; CPAN::Version->vgt("1.1","1.1.1"); # 1 bc. 1.1 > 1.001001 CPAN::Version->vlt("1.1","1.1"); # 0 bc. 1.1 not < 1.1 CPAN::Version->vcmp("1.1","1.1.1"); # 1 bc. first is larger CPAN::Version->vcmp("1.1.1","1.1"); # -1 bc. first is smaller CPAN::Version->readable(v1.2.3); # "v1.2.3" CPAN::Version->vstring("v1.2.3"); # v1.2.3 CPAN::Version->float2vv(1.002003); # "v1.2.3" =head1 DESCRIPTION This module mediates between some version that perl sees in a package and the version that is published by the CPAN indexer. It's only written as a helper module for both CPAN.pm and CPANPLUS.pm. As it stands it predates version.pm but has the same goal: make version strings visible and comparable. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut # Local Variables: # mode: cperl # cperl-indent-level: 4 # End: perl5/CPAN/Plugin.pm000044400000006223152530123070010107 0ustar00package CPAN::Plugin; use strict; use warnings; our $VERSION = '0.97'; require CPAN; ###################################################################### sub new { # ; my ($class, %params) = @_; my $self = +{ (ref $class ? (%$class) : ()), %params, }; $self = bless $self, ref $class ? ref $class : $class; unless (ref $class) { local $_; no warnings 'once'; $CPAN::META->use_inst ($_) for $self->plugin_requires; } $self; } ###################################################################### sub plugin_requires { # ; } ###################################################################### sub distribution_object { # ; my ($self) = @_; $self->{distribution_object}; } ###################################################################### sub distribution { # ; my ($self) = @_; my $distribution = $self->distribution_object->id; CPAN::Shell->expand("Distribution",$distribution) or $self->frontend->mydie("Unknowns distribution '$distribution'\n"); } ###################################################################### sub distribution_info { # ; my ($self) = @_; CPAN::DistnameInfo->new ($self->distribution->id); } ###################################################################### sub build_dir { # ; my ($self) = @_; my $build_dir = $self->distribution->{build_dir} or $self->frontend->mydie("Distribution has not been built yet, cannot proceed"); } ###################################################################### sub is_xs { # my ($self) = @_; my @xs = glob File::Spec->catfile ($self->build_dir, '*.xs'); # quick try unless (@xs) { require ExtUtils::Manifest; my $manifest_file = File::Spec->catfile ($self->build_dir, "MANIFEST"); my $manifest = ExtUtils::Manifest::maniread($manifest_file); @xs = grep /\.xs$/, keys %$manifest; } scalar @xs; } ###################################################################### package CPAN::Plugin; 1; __END__ =pod =head1 NAME CPAN::Plugin - Base class for CPAN shell extensions =head1 SYNOPSIS package CPAN::Plugin::Flurb; use parent 'CPAN::Plugin'; sub post_test { my ($self, $distribution_object) = @_; $self = $self->new (distribution_object => $distribution_object); ...; } =head1 DESCRIPTION =head2 Alpha Status The plugin system in the CPAN shell was introduced in version 2.07 and is still considered experimental. =head2 How Plugins work? See L. =head1 METHODS =head2 plugin_requires returns list of packages given plugin requires for functionality. This list is evaluated using C<< CPAN->use_inst >> method. =head2 distribution_object Get current distribution object. =head2 distribution =head2 distribution_info =head2 build_dir Simple delegatees for misc parameters derived from distribution =head2 is_xs Predicate to detect whether package contains XS. =head1 AUTHOR Branislav Zahradnik =cut perl5/CPAN/Kwalify/distroprefs.dd000044400000006233152530123070012577 0ustar00$VAR1 = { "mapping" => { "comment" => { "type" => "text" }, "cpanconfig" => { "mapping" => { "=" => { "type" => "text" } }, "type" => "map" }, "depends" => { "mapping" => { "build_requires" => { "mapping" => { "=" => { "type" => "text" } }, "type" => "map" }, "configure_requires" => {}, "requires" => {} }, "type" => "map" }, "disabled" => { "enum" => [ 0, 1 ], "type" => "int" }, "features" => { "sequence" => [ { "type" => "text" } ], "type" => "seq" }, "goto" => { "type" => "text" }, "install" => { "mapping" => { "args" => { "sequence" => [ { "type" => "text" } ], "type" => "seq" }, "commandline" => { "type" => "text" }, "eexpect" => { "mapping" => { "mode" => { "enum" => [ "deterministic", "anyorder" ], "type" => "text" }, "reuse" => { "type" => "int" }, "talk" => { "sequence" => [ { "type" => "text" } ], "type" => "seq" }, "timeout" => { "type" => "number" } }, "type" => "map" }, "env" => { "mapping" => { "=" => { "type" => "text" } }, "type" => "map" }, "expect" => { "sequence" => [ { "type" => "text" } ], "type" => "seq" } }, "type" => "map" }, "make" => {}, "match" => { "mapping" => { "distribution" => { "type" => "text" }, "env" => { "mapping" => { "=" => { "type" => "text" } }, "type" => "map" }, "module" => { "type" => "text" }, "perl" => { "type" => "text" }, "perlconfig" => {} }, "type" => "map" }, "patches" => { "sequence" => [ { "type" => "text" } ], "type" => "seq" }, "pl" => {}, "reminder" => { "type" => "text" }, "test" => {} }, "type" => "map" }; $VAR1->{"mapping"}{"depends"}{"mapping"}{"configure_requires"} = $VAR1->{"mapping"}{"depends"}{"mapping"}{"build_requires"}; $VAR1->{"mapping"}{"depends"}{"mapping"}{"requires"} = $VAR1->{"mapping"}{"depends"}{"mapping"}{"build_requires"}; $VAR1->{"mapping"}{"make"} = $VAR1->{"mapping"}{"install"}; $VAR1->{"mapping"}{"match"}{"mapping"}{"perlconfig"} = $VAR1->{"mapping"}{"match"}{"mapping"}{"env"}; $VAR1->{"mapping"}{"pl"} = $VAR1->{"mapping"}{"install"}; $VAR1->{"mapping"}{"test"} = $VAR1->{"mapping"}{"install"}; perl5/CPAN/Kwalify/distroprefs.yml000044400000003071152530123070013006 0ustar00--- type: map mapping: comment: type: text depends: type: map mapping: configure_requires: &requires_common type: map mapping: =: type: text build_requires: *requires_common requires: *requires_common match: type: map mapping: distribution: type: text module: type: text perl: type: text perlconfig: &matchhash_common type: map mapping: =: type: text env: *matchhash_common install: &args_env_expect type: map mapping: args: type: seq sequence: - type: text commandline: type: text env: type: map mapping: =: type: text expect: type: seq sequence: - type: text eexpect: type: map mapping: mode: type: text enum: - deterministic - anyorder timeout: type: number reuse: type: int talk: type: seq sequence: - type: text make: *args_env_expect pl: *args_env_expect test: *args_env_expect patches: type: seq sequence: - type: text disabled: type: int enum: - 0 - 1 goto: type: text cpanconfig: type: map mapping: =: type: text features: type: seq sequence: - type: text reminder: type: text perl5/CPAN/Plugin/Specfile.pm000044400000020751152530123070011643 0ustar00=head1 NAME CPAN::Plugin::Specfile - Proof of concept implementation of a trivial CPAN::Plugin =head1 SYNOPSIS # once in the cpan shell o conf plugin_list push CPAN::Plugin::Specfile # make permanent o conf commit # any time in the cpan shell to write a spec file test Acme::Meta # disable # if it is the last in plugin_list: o conf plugin_list pop # otherwise, determine the index to splice: o conf plugin_list # and then use splice, e.g. to splice position 3: o conf plugin_list splice 3 1 =head1 DESCRIPTION Implemented as a post-test hook, this plugin writes a specfile after every successful test run. The content is also written to the terminal. As a side effect, the timestamps of the written specfiles reflect the linear order of all dependencies. B This code is just a small demo how to use the plugin system of the CPAN shell, not a full fledged spec file writer. Do not expect new features in this plugin. =head2 OPTIONS The target directory to store the spec files in can be set using C as in o conf plugin_list push CPAN::Plugin::Specfile=dir,/tmp/specfiles-000042 The default directory for this is the C directory in the I directory. =head1 AUTHOR Andreas Koenig , Branislav Zahradnik =cut package CPAN::Plugin::Specfile; our $VERSION = '0.02'; use File::Path; use File::Spec; sub __accessor { my ($class, $key) = @_; no strict 'refs'; *{$class . '::' . $key} = sub { my $self = shift; if (@_) { $self->{$key} = shift; } return $self->{$key}; }; } BEGIN { __PACKAGE__->__accessor($_) for qw(dir dir_default) } sub new { my($class, @rest) = @_; my $self = bless {}, $class; while (my($arg,$val) = splice @rest, 0, 2) { $self->$arg($val); } $self->dir_default(File::Spec->catdir($CPAN::Config->{cpan_home},"plugins",__PACKAGE__)); $self; } sub post_test { my $self = shift; my $distribution_object = shift; my $distribution = $distribution_object->pretty_id; unless ($CPAN::META->has_inst("CPAN::DistnameInfo")){ $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue"); } my $d = CPAN::Shell->expand("Distribution",$distribution) or $CPAN::Frontend->mydie("Unknowns distribution '$distribution'\n"); my $build_dir = $d->{build_dir} or $CPAN::Frontend->mydie("Distribution has not been built yet, cannot proceed"); my %contains = map {($_ => undef)} $d->containsmods; my @m; my $width = 16; my $header = sub { my($header,$value) = @_; push @m, sprintf("%-s:%*s%s\n", $header, $width-length($header), "", $value); }; my $dni = CPAN::DistnameInfo->new($distribution); my $dist = $dni->dist; my $summary = CPAN::Shell->_guess_manpage($d,\%contains,$dist); $header->("Name", "perl-$dist"); my $version = $dni->version; $header->("Version", $version); $header->("Release", "1%{?dist}"); #Summary: Template processing system #Group: Development/Libraries #License: GPL+ or Artistic #URL: http://www.template-toolkit.org/ #Source0: http://search.cpan.org/CPAN/authors/id/A/AB/ABW/Template-Toolkit-%{version}.tar.gz #Patch0: Template-2.22-SREZIC-01.patch #BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) for my $h_tuple ([Summary => $summary], [Group => "Development/Libraries"], [License =>], [URL =>], [BuildRoot => "%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)"], [Requires => "perl(:MODULE_COMPAT_%(eval \"`%{__perl} -V:version`\"; echo \$version))"], ) { my($h,$v) = @$h_tuple; $v = "unknown" unless defined $v; $header->($h, $v); } $header->("Source0", sprintf( "http://search.cpan.org/CPAN/authors/id/%s/%s/%s", substr($distribution,0,1), substr($distribution,0,2), $distribution )); require POSIX; my @xs = glob "$build_dir/*.xs"; # quick try unless (@xs) { require ExtUtils::Manifest; my $manifest_file = "$build_dir/MANIFEST"; my $manifest = ExtUtils::Manifest::maniread($manifest_file); @xs = grep /\.xs$/, keys %$manifest; } if (! @xs) { $header->('BuildArch', 'noarch'); } for my $k (sort keys %contains) { my $m = CPAN::Shell->expand("Module",$k); my $v = $contains{$k} = $m->cpan_version; my $vspec = $v eq "undef" ? "" : " = $v"; $header->("Provides", "perl($k)$vspec"); } if (my $prereq_pm = $d->{prereq_pm}) { my %req; for my $reqkey (keys %$prereq_pm) { while (my($k,$v) = each %{$prereq_pm->{$reqkey}}) { $req{$k} = $v; } } if (-e "$build_dir/Build.PL" && ! exists $req{"Module::Build"}) { $req{"Module::Build"} = 0; } for my $k (sort keys %req) { next if $k eq "perl"; my $v = $req{$k}; my $vspec = defined $v && length $v && $v > 0 ? " >= $v" : ""; $header->(BuildRequires => "perl($k)$vspec"); next if $k =~ /^(Module::Build)$/; # MB is always only a # BuildRequires; if we # turn it into a # Requires, then we # would have to make it # a BuildRequires # everywhere we depend # on *one* MB built # module. $header->(Requires => "perl($k)$vspec"); } } push @m, "\n%define _use_internal_dependency_generator 0 %define __find_requires %{nil} %define __find_provides %{nil} "; push @m, "\n%description\n%{summary}.\n"; push @m, "\n%prep\n%setup -q -n $dist-%{version}\n"; if (-e "$build_dir/Build.PL") { # see http://www.redhat.com/archives/rpm-list/2002-July/msg00110.html about RPM_BUILD_ROOT vs %{buildroot} push @m, <<'EOF'; %build %{__perl} Build.PL --installdirs=vendor --libdoc installvendorman3dir ./Build %install rm -rf $RPM_BUILD_ROOT ./Build install destdir=$RPM_BUILD_ROOT create_packlist=0 find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null \; %{_fixperms} $RPM_BUILD_ROOT/* %check ./Build test EOF } elsif (-e "$build_dir/Makefile.PL") { push @m, <<'EOF'; %build %{__perl} Makefile.PL INSTALLDIRS=vendor make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make pure_install DESTDIR=$RPM_BUILD_ROOT find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';' find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null ';' %{_fixperms} $RPM_BUILD_ROOT/* %check make test EOF } else { $CPAN::Frontend->mydie("'$distribution' has neither a Build.PL nor a Makefile.PL\n"); } push @m, "\n%clean\nrm -rf \$RPM_BUILD_ROOT\n"; my $vendorlib = @xs ? "vendorarch" : "vendorlib"; my $date = POSIX::strftime("%a %b %d %Y", gmtime); my @doc = grep { -e "$build_dir/$_" } qw(README Changes); my $exe_stanza = "\n"; if (my $exe_files = $d->_exe_files) { if (@$exe_files) { $exe_stanza = "%{_mandir}/man1/*.1*\n"; for my $e (@$exe_files) { unless (CPAN->has_inst("File::Basename")) { $CPAN::Frontend->mydie("File::Basename not installed, cannot continue"); } my $basename = File::Basename::basename($e); $exe_stanza .= "/usr/bin/$basename\n"; } } } push @m, < - $version-1 - autogenerated by CPAN::Plugin::Specfile() EOF my $ret = join "", @m; $CPAN::Frontend->myprint($ret); my $target_dir = $self->dir || $self->dir_default; File::Path::mkpath($target_dir); my $outfile = File::Spec->catfile($target_dir, "perl-$dist.spec"); open my $specout, ">", $outfile or $CPAN::Frontend->mydie("Could not open >$outfile: $!"); print $specout $ret; $CPAN::Frontend->myprint("Wrote $outfile"); $ret; } 1; perl5/CPAN/Nox.pm000044400000001671152530123070007417 0ustar00package CPAN::Nox; use strict; use vars qw($VERSION @EXPORT); BEGIN{ $CPAN::Suppress_readline=1 unless defined $CPAN::term; } use Exporter (); @CPAN::ISA = ('Exporter'); use CPAN; $VERSION = "5.5001"; $CPAN::META->has_inst('Digest::MD5','no'); $CPAN::META->has_inst('LWP','no'); $CPAN::META->has_inst('Compress::Zlib','no'); @EXPORT = @CPAN::EXPORT; *AUTOLOAD = \&CPAN::AUTOLOAD; 1; __END__ =head1 NAME CPAN::Nox - Wrapper around CPAN.pm without using any XS module =head1 SYNOPSIS Interactive mode: perl -MCPAN::Nox -e shell; =head1 DESCRIPTION This package has the same functionality as CPAN.pm, but tries to prevent the usage of compiled extensions during its own execution. Its primary purpose is a rescue in case you upgraded perl and broke binary compatibility somehow. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =cut perl5/CPAN/HTTP/Client.pm000044400000017450152530123070010652 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::HTTP::Client; use strict; use vars qw(@ISA); use CPAN::HTTP::Credentials; use HTTP::Tiny 0.005; $CPAN::HTTP::Client::VERSION = $CPAN::HTTP::Client::VERSION = "1.9602"; # CPAN::HTTP::Client is adapted from parts of cpanm by Tatsuhiko Miyagawa # and parts of LWP by Gisle Aas sub new { my $class = shift; my %args = @_; for my $k ( keys %args ) { $args{$k} = '' unless defined $args{$k}; } $args{no_proxy} = [split(",", $args{no_proxy}) ] if $args{no_proxy}; return bless \%args, $class; } # This executes a request with redirection (up to 5) and returns the # response structure generated by HTTP::Tiny # # If authentication fails, it will attempt to get new authentication # information and repeat up to 5 times sub mirror { my($self, $uri, $path) = @_; my $want_proxy = $self->_want_proxy($uri); my $http = HTTP::Tiny->new( verify_SSL => 1, $want_proxy ? (proxy => $self->{proxy}) : () ); my ($response, %headers); my $retries = 0; while ( $retries++ < 5 ) { $response = $http->mirror( $uri, $path, {headers => \%headers} ); if ( $response->{status} eq '401' ) { last unless $self->_get_auth_params( $response, 'non_proxy' ); } elsif ( $response->{status} eq '407' ) { last unless $self->_get_auth_params( $response, 'proxy' ); } else { last; # either success or failure } my %headers = ( $self->_auth_headers( $uri, 'non_proxy' ), ( $want_proxy ? $self->_auth_headers($uri, 'proxy') : () ), ); } return $response; } sub _want_proxy { my ($self, $uri) = @_; return unless $self->{proxy}; my($host) = $uri =~ m|://([^/:]+)|; return ! grep { $host =~ /\Q$_\E$/ } @{ $self->{no_proxy} || [] }; } # Generates the authentication headers for a given mode # C is 'proxy' or 'non_proxy' # C<_${mode}_type> is 'basic' or 'digest' # C<_${mode}_params> will be the challenge parameters from the 401/407 headers sub _auth_headers { my ($self, $uri, $mode) = @_; # Get names for our mode-specific attributes my ($type_key, $param_key) = map {"_" . $mode . $_} qw/_type _params/; # If _prepare_auth has not been called, we can't prepare headers return unless $self->{$type_key}; # Get user credentials for mode my $cred_method = "get_" . ($mode ? "proxy" : "non_proxy") ."_credentials"; my ($user, $pass) = CPAN::HTTP::Credentials->$cred_method; # Generate the header for the mode & type my $header = $mode eq 'proxy' ? 'Proxy-Authorization' : 'Authorization'; my $value_method = "_" . $self->{$type_key} . "_auth"; my $value = $self->$value_method($user, $pass, $self->{$param_key}, $uri); # If we didn't get a value, we didn't have the right modules available return $value ? ( $header, $value ) : (); } # Extract authentication parameters from headers, but clear any prior # credentials if we failed (so we might prompt user for password again) sub _get_auth_params { my ($self, $response, $mode) = @_; my $prefix = $mode eq 'proxy' ? 'Proxy' : 'WWW'; my ($type_key, $param_key) = map {"_" . $mode . $_} qw/_type _params/; if ( ! $response->{success} ) { # auth failed my $method = "clear_${mode}_credentials"; CPAN::HTTP::Credentials->$method; delete $self->{$_} for $type_key, $param_key; } ($self->{$type_key}, $self->{$param_key}) = $self->_get_challenge( $response, "${prefix}-Authenticate"); return $self->{$type_key}; } # Extract challenge type and parameters for a challenge list sub _get_challenge { my ($self, $response, $auth_header) = @_; my $auth_list = $response->{headers}(lc $auth_header); return unless defined $auth_list; $auth_list = [$auth_list] unless ref $auth_list; for my $challenge (@$auth_list) { $challenge =~ tr/,/;/; # "," is used to separate auth-params!! ($challenge) = $self->split_header_words($challenge); my $scheme = shift(@$challenge); shift(@$challenge); # no value $challenge = { @$challenge }; # make rest into a hash unless ($scheme =~ /^(basic|digest)$/) { next; # bad scheme } $scheme = $1; # untainted now return ($scheme, $challenge); } return; } # Generate a basic authentication header value sub _basic_auth { my ($self, $user, $pass) = @_; unless ( $CPAN::META->has_usable('MIME::Base64') ) { $CPAN::Frontend->mywarn( "MIME::Base64 is required for 'Basic' style authentication" ); return; } return "Basic " . MIME::Base64::encode_base64("$user\:$pass", q{}); } # Generate a digest authentication header value sub _digest_auth { my ($self, $user, $pass, $auth_param, $uri) = @_; unless ( $CPAN::META->has_usable('Digest::MD5') ) { $CPAN::Frontend->mywarn( "Digest::MD5 is required for 'Digest' style authentication" ); return; } my $nc = sprintf "%08X", ++$self->{_nonce_count}{$auth_param->{nonce}}; my $cnonce = sprintf "%8x", time; my ($path) = $uri =~ m{^\w+?://[^/]+(/.*)$}; $path = "/" unless defined $path; 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(":", 'GET', $path)); 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, $path, $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{$_}; push(@pairs, "$_=" . qq("$resp{$_}")); } my $auth_value = "Digest " . join(", ", @pairs); return $auth_value; } # split_header_words adapted from HTTP::Headers::Util sub split_header_words { my ($self, @words) = @_; my @res = $self->_split_header_words(@words); for my $arr (@res) { for (my $i = @$arr - 2; $i >= 0; $i -= 2) { $arr->[$i] = lc($arr->[$i]); } } return @res; } sub _split_header_words { my($self, @val) = @_; my @res; for (@val) { my @cur; while (length) { if (s/^\s*(=*[^\s=;,]+)//) { # 'token' or parameter 'attribute' push(@cur, $1); # a quoted value if (s/^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"//) { my $val = $1; $val =~ s/\\(.)/$1/g; push(@cur, $val); # some unquoted value } elsif (s/^\s*=\s*([^;,\s]*)//) { my $val = $1; $val =~ s/\s+$//; push(@cur, $val); # no value, a lone token } else { push(@cur, undef); } } elsif (s/^\s*,//) { push(@res, [@cur]) if @cur; @cur = (); } elsif (s/^\s*;// || s/^\s+//) { # continue } else { die "This should not happen: '$_'"; } } push(@res, \@cur) if @cur; } @res; } 1; perl5/CPAN/HTTP/Credentials.pm000044400000005111152530123070011660 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::HTTP::Credentials; use strict; use vars qw($USER $PASSWORD $PROXY_USER $PROXY_PASSWORD); $CPAN::HTTP::Credentials::VERSION = $CPAN::HTTP::Credentials::VERSION = "1.9601"; sub clear_credentials { clear_non_proxy_credentials(); clear_proxy_credentials(); } sub clear_non_proxy_credentials { undef $USER; undef $PASSWORD; } sub clear_proxy_credentials { undef $PROXY_USER; undef $PROXY_PASSWORD; } sub get_proxy_credentials { my $self = shift; if ($PROXY_USER && $PROXY_PASSWORD) { return ($PROXY_USER, $PROXY_PASSWORD); } if ( defined $CPAN::Config->{proxy_user} && $CPAN::Config->{proxy_user} ) { $PROXY_USER = $CPAN::Config->{proxy_user}; $PROXY_PASSWORD = $CPAN::Config->{proxy_pass} || ""; return ($PROXY_USER, $PROXY_PASSWORD); } my $username_prompt = "\nProxy authentication needed! (Note: to permanently configure username and password run o conf proxy_user your_username o conf proxy_pass your_password )\nUsername:"; ($PROXY_USER, $PROXY_PASSWORD) = _get_username_and_password_from_user($username_prompt); return ($PROXY_USER,$PROXY_PASSWORD); } sub get_non_proxy_credentials { my $self = shift; if ($USER && $PASSWORD) { return ($USER, $PASSWORD); } if ( defined $CPAN::Config->{username} ) { $USER = $CPAN::Config->{username}; $PASSWORD = $CPAN::Config->{password} || ""; return ($USER, $PASSWORD); } my $username_prompt = "\nAuthentication needed! (Note: to permanently configure username and password run o conf username your_username o conf password your_password )\nUsername:"; ($USER, $PASSWORD) = _get_username_and_password_from_user($username_prompt); return ($USER,$PASSWORD); } sub _get_username_and_password_from_user { my $username_message = shift; my ($username,$password); ExtUtils::MakeMaker->import(qw(prompt)); $username = prompt($username_message); if ($CPAN::META->has_inst("Term::ReadKey")) { Term::ReadKey::ReadMode("noecho"); } else { $CPAN::Frontend->mywarn( "Warning: Term::ReadKey seems not to be available, your password will be echoed to the terminal!\n" ); } $password = prompt("Password:"); if ($CPAN::META->has_inst("Term::ReadKey")) { Term::ReadKey::ReadMode("restore"); } $CPAN::Frontend->myprint("\n\n"); return ($username,$password); } 1; perl5/CPAN/Mirrors.pm000044400000043512152530123070010310 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: =head1 NAME CPAN::Mirrors - Get CPAN mirror information and select a fast one =head1 SYNOPSIS use CPAN::Mirrors; my $mirrors = CPAN::Mirrors->new( $mirrored_by_file ); my $seen = {}; my $best_continent = $mirrors->find_best_continents( { seen => $seen } ); my @mirrors = $mirrors->get_mirrors_by_continents( $best_continent ); my $callback = sub { my( $m ) = @_; printf "%s = %s\n", $m->hostname, $m->rtt }; $mirrors->get_mirrors_timings( \@mirrors, $seen, $callback, %args ); @mirrors = sort { $a->rtt <=> $b->rtt } @mirrors; print "Best mirrors are ", map( { $_->rtt } @mirrors[0..3] ), "\n"; =head1 DESCRIPTION =over =cut package CPAN::Mirrors; use strict; use vars qw($VERSION $urllist $silent); $VERSION = "2.27"; use Carp; use FileHandle; use Fcntl ":flock"; use Net::Ping (); use CPAN::Version; =item new( LOCAL_FILE_NAME ) Create a new CPAN::Mirrors object from LOCAL_FILE_NAME. This file should look like that in http://www.cpan.org/MIRRORED.BY . =cut sub new { my ($class, $file) = @_; croak "CPAN::Mirrors->new requires a filename" unless defined $file; croak "The file [$file] was not found" unless -e $file; my $self = bless { mirrors => [], geography => {}, }, $class; $self->parse_mirrored_by( $file ); return $self; } sub parse_mirrored_by { my ($self, $file) = @_; my $handle = FileHandle->new; $handle->open($file) or croak "Couldn't open $file: $!"; flock $handle, LOCK_SH; $self->_parse($file,$handle); flock $handle, LOCK_UN; $handle->close; } =item continents() Return a list of continents based on those defined in F. =cut sub continents { my ($self) = @_; return sort keys %{$self->{geography} || {}}; } =item countries( [CONTINENTS] ) Return a list of countries based on those defined in F. It only returns countries for the continents you specify (as defined in C). If you don't specify any continents, it returns all of the countries listed in F. =cut sub countries { my ($self, @continents) = @_; @continents = $self->continents unless @continents; my @countries; for my $c (@continents) { push @countries, sort keys %{ $self->{geography}{$c} || {} }; } return @countries; } =item mirrors( [COUNTRIES] ) Return a list of mirrors based on those defined in F. It only returns mirrors for the countries you specify (as defined in C). If you don't specify any countries, it returns all of the mirrors listed in F. =cut sub mirrors { my ($self, @countries) = @_; return @{$self->{mirrors}} unless @countries; my %wanted = map { $_ => 1 } @countries; my @found; for my $m (@{$self->{mirrors}}) { push @found, $m if exists $wanted{$m->country}; } return @found; } =item get_mirrors_by_countries( [COUNTRIES] ) A more sensible synonym for mirrors. =cut sub get_mirrors_by_countries { &mirrors } =item get_mirrors_by_continents( [CONTINENTS] ) Return a list of mirrors for all of continents you specify. If you don't specify any continents, it returns all of the mirrors. You can specify a single continent or an array reference of continents. =cut sub get_mirrors_by_continents { my ($self, $continents ) = @_; $continents = [ $continents ] unless ref $continents; eval { $self->mirrors( $self->get_countries_by_continents( @$continents ) ); }; } =item get_countries_by_continents( [CONTINENTS] ) A more sensible synonym for countries. =cut sub get_countries_by_continents { &countries } =item default_mirror Returns the default mirror, http://www.cpan.org/ . This mirror uses dynamic DNS to give a close mirror. =cut sub default_mirror { CPAN::Mirrored::By->new({ http => 'http://www.cpan.org/'}); } =item best_mirrors C checks for the best mirrors based on the list of continents you pass, or, without that, all continents, as defined by C. It pings each mirror, up to the value of C. In list context, it returns up to C mirrors. In scalar context, it returns the single best mirror. Arguments how_many - the number of mirrors to return. Default: 1 callback - a callback for find_best_continents verbose - true or false on all the whining and moaning. Default: false continents - an array ref of the continents to check external_ping - if true, use external ping via Net::Ping::External. Default: false If you don't specify the continents, C calls C to get the list of continents to check. If you don't have L v2.13 or later, needed for timings, this returns the default mirror. C should be set and then C needs to be installed, if the local network has a transparent proxy. =cut sub best_mirrors { my ($self, %args) = @_; my $how_many = $args{how_many} || 1; my $callback = $args{callback}; my $verbose = defined $args{verbose} ? $args{verbose} : 0; my $continents = $args{continents} || []; $continents = [$continents] unless ref $continents; $args{external_ping} = 0 unless defined $args{external_ping}; my $external_ping = $args{external_ping}; # Old Net::Ping did not do timings at all my $min_version = '2.13'; unless( CPAN::Version->vgt(Net::Ping->VERSION, $min_version) ) { carp sprintf "Net::Ping version is %s (< %s). Returning %s", Net::Ping->VERSION, $min_version, $self->default_mirror; return $self->default_mirror; } my $seen = {}; if ( ! @$continents ) { print "Searching for the best continent ...\n" if $verbose; my @best_continents = $self->find_best_continents( seen => $seen, verbose => $verbose, callback => $callback, external_ping => $external_ping, ); # Only add enough continents to find enough mirrors my $count = 0; for my $continent ( @best_continents ) { push @$continents, $continent; $count += $self->mirrors( $self->countries($continent) ); last if $count >= $how_many; } } return $self->default_mirror unless @$continents; print "Scanning " . join(", ", @$continents) . " ...\n" if $verbose; my $trial_mirrors = $self->get_n_random_mirrors_by_continents( 3 * $how_many, $continents->[0] ); my $timings = $self->get_mirrors_timings( $trial_mirrors, $seen, $callback, %args, ); return $self->default_mirror unless @$timings; $how_many = @$timings if $how_many > @$timings; return wantarray ? @{$timings}[0 .. $how_many-1] : $timings->[0]; } =item get_n_random_mirrors_by_continents( N, [CONTINENTS] ) Returns up to N random mirrors for the specified continents. Specify the continents as an array reference. =cut sub get_n_random_mirrors_by_continents { my( $self, $n, $continents ) = @_; $n ||= 3; $continents = [ $continents ] unless ref $continents; if ( $n <= 0 ) { return wantarray ? () : []; } my @long_list = $self->get_mirrors_by_continents( $continents ); if ( $n eq '*' or $n > @long_list ) { return wantarray ? @long_list : \@long_list; } @long_list = map {$_->[0]} sort {$a->[1] <=> $b->[1]} map {[$_, rand]} @long_list; splice @long_list, $n; # truncate \@long_list; } =item get_mirrors_timings( MIRROR_LIST, SEEN, CALLBACK, %ARGS ); Pings the listed mirrors and returns a list of mirrors sorted in ascending ping times. C is an anonymous array of C objects to ping. The optional argument C is a hash reference used to track the mirrors you've already pinged. The optional argument C is a subroutine reference to call after each ping. It gets the C object after each ping. =cut sub get_mirrors_timings { my( $self, $mirror_list, $seen, $callback, %args ) = @_; $seen = {} unless defined $seen; croak "The mirror list argument must be an array reference" unless ref $mirror_list eq ref []; croak "The seen argument must be a hash reference" unless ref $seen eq ref {}; croak "callback must be a subroutine" if( defined $callback and ref $callback ne ref sub {} ); my $timings = []; for my $m ( @$mirror_list ) { $seen->{$m->hostname} = $m; next unless eval{ $m->http }; if( $self->_try_a_ping( $seen, $m, ) ) { my $ping = $m->ping(%args); next unless defined $ping; # printf "m %s ping %s\n", $m, $ping; push @$timings, $m; $callback->( $m ) if $callback; } else { push @$timings, $seen->{$m->hostname} if defined $seen->{$m->hostname}->rtt; } } my @best = sort { if( defined $a->rtt and defined $b->rtt ) { $a->rtt <=> $b->rtt } elsif( defined $a->rtt and ! defined $b->rtt ) { return -1; } elsif( ! defined $a->rtt and defined $b->rtt ) { return 1; } elsif( ! defined $a->rtt and ! defined $b->rtt ) { return 0; } } @$timings; return wantarray ? @best : \@best; } =item find_best_continents( HASH_REF ); C goes through each continent and pings C random mirrors on that continent. It then orders the continents by ascending median ping time. In list context, it returns the ordered list of continent. In scalar context, it returns the same list as an anonymous array. Arguments: n - the number of hosts to ping for each continent. Default: 3 seen - a hashref of cached hostname ping times verbose - true or false for noisy or quiet. Default: false callback - a subroutine to run after each ping. ping_cache_limit - how long, in seconds, to reuse previous ping times. Default: 1 day The C hash has hostnames as keys and anonymous arrays as values. The anonymous array is a triplet of a C object, a ping time, and the epoch time for the measurement. The callback subroutine gets the C object, the ping time, and measurement time (the same things in the C hashref) as arguments. C doesn't care what the callback does and ignores the return value. With a low value for C, a single mirror might skew the results enough to choose a worse continent. If you have that problem, try a larger value. =cut sub find_best_continents { my ($self, %args) = @_; $args{n} ||= 3; $args{verbose} = 0 unless defined $args{verbose}; $args{seen} = {} unless defined $args{seen}; croak "The seen argument must be a hash reference" unless ref $args{seen} eq ref {}; $args{ping_cache_limit} = 24 * 60 * 60 unless defined $args{ping_cache_limit}; croak "callback must be a subroutine" if( defined $args{callback} and ref $args{callback} ne ref sub {} ); my %medians; CONT: for my $c ( $self->continents ) { my @mirrors = $self->mirrors( $self->countries($c) ); printf "Testing %s (%d mirrors)\n", $c, scalar @mirrors if $args{verbose}; next CONT unless @mirrors; my $n = (@mirrors < $args{n}) ? @mirrors : $args{n}; my @tests; my $tries = 0; RANDOM: while ( @mirrors && @tests < $n && $tries++ < 15 ) { my $m = splice( @mirrors, int(rand(@mirrors)), 1 ); if( $self->_try_a_ping( $args{seen}, $m, $args{ping_cache_limit} )) { $self->get_mirrors_timings( [ $m ], $args{seen}, $args{callback}, %args, ); next RANDOM unless defined $args{seen}{$m->hostname}->rtt; } printf "(%s -> %0.2f ms)", $m->hostname, join ' ', 1000 * $args{seen}{$m->hostname}->rtt if $args{verbose}; push @tests, $args{seen}{$m->hostname}->rtt; } my $median = $self->_get_median_ping_time( \@tests, $args{verbose} ); $medians{$c} = $median if defined $median; } my @best_cont = sort { $medians{$a} <=> $medians{$b} } keys %medians; if ( $args{verbose} ) { print "Median result by continent:\n"; if ( @best_cont ) { for my $c ( @best_cont ) { printf( " %7.2f ms %s\n", $medians{$c}*1000, $c ); } } else { print " **** No results found ****\n" } } return wantarray ? @best_cont : $best_cont[0]; } # retry if sub _try_a_ping { my ($self, $seen, $mirror, $ping_cache_limit ) = @_; ( ! exists $seen->{$mirror->hostname} or ! defined $seen->{$mirror->hostname}->rtt or ! defined $ping_cache_limit or time - $seen->{$mirror->hostname}->ping_time > $ping_cache_limit ) } sub _get_median_ping_time { my ($self, $tests, $verbose ) = @_; my @sorted = sort { $a <=> $b } @$tests; my $median = do { if ( @sorted == 0 ) { undef } elsif ( @sorted == 1 ) { $sorted[0] } elsif ( @sorted % 2 ) { $sorted[ int(@sorted / 2) ] } else { my $mid_high = int(@sorted/2); ($sorted[$mid_high-1] + $sorted[$mid_high])/2; } }; if ($verbose){ if ($median) { printf " => median time: %.2f ms\n", $median * 1000 } else { printf " => **** no median time ****\n"; } } return $median; } # Adapted from Parse::CPAN::MirroredBy by Adam Kennedy sub _parse { my ($self, $file, $handle) = @_; my $output = $self->{mirrors}; my $geo = $self->{geography}; local $/ = "\012"; my $line = 0; my $mirror = undef; while ( 1 ) { # Next line my $string = <$handle>; last if ! defined $string; $line = $line + 1; # Remove the useless lines chomp( $string ); next if $string =~ /^\s*$/; next if $string =~ /^\s*#/; # Hostname or property? if ( $string =~ /^\s/ ) { # Property unless ( $string =~ /^\s+(\w+)\s+=\s+\"(.*)\"$/ ) { croak("Invalid property on line $line"); } my ($prop, $value) = ($1,$2); $mirror ||= {}; if ( $prop eq 'dst_location' ) { my (@location,$continent,$country); @location = (split /\s*,\s*/, $value) and ($continent, $country) = @location[-1,-2]; $continent =~ s/\s\(.*//; $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude $geo->{$continent}{$country} = 1 if $continent && $country; $mirror->{continent} = $continent || "unknown"; $mirror->{country} = $country || "unknown"; } elsif ( $prop eq 'dst_http' ) { $mirror->{http} = $value; } elsif ( $prop eq 'dst_ftp' ) { $mirror->{ftp} = $value; } elsif ( $prop eq 'dst_rsync' ) { $mirror->{rsync} = $value; } else { $prop =~ s/^dst_//; $mirror->{$prop} = $value; } } else { # Hostname unless ( $string =~ /^([\w\.-]+)\:\s*$/ ) { croak("Invalid host name on line $line"); } my $current = $mirror; $mirror = { hostname => "$1" }; if ( $current ) { push @$output, CPAN::Mirrored::By->new($current); } } } if ( $mirror ) { push @$output, CPAN::Mirrored::By->new($mirror); } return; } #--------------------------------------------------------------------------# package CPAN::Mirrored::By; use strict; use Net::Ping (); sub new { my($self,$arg) = @_; $arg ||= {}; bless $arg, $self; } sub hostname { shift->{hostname} } sub continent { shift->{continent} } sub country { shift->{country} } sub http { shift->{http} || '' } sub ftp { shift->{ftp} || '' } sub rsync { shift->{rsync} || '' } sub rtt { shift->{rtt} } sub ping_time { shift->{ping_time} } sub url { my $self = shift; return $self->{http} || $self->{ftp}; } sub ping { my($self, %args) = @_; my $external_ping = $args{external_ping}; if ($external_ping) { eval { require Net::Ping::External } or die "Net::Ping::External required to use external ping command"; } my $ping = Net::Ping->new( $external_ping ? 'external' : $^O eq 'VMS' ? 'icmp' : 'tcp', 1 ); my ($proto) = $self->url =~ m{^([^:]+)}; my $port = $proto eq 'http' ? 80 : 21; return unless $port; if ( $ping->can('port_number') ) { $ping->port_number($port); } else { $ping->{'port_num'} = $port; } $ping->hires(1) if $ping->can('hires'); my ($alive,$rtt) = eval { $ping->ping($self->hostname); }; my $verbose = $args{verbose}; if ($verbose && !$alive) { printf "(host %s not alive)", $self->hostname; } $self->{rtt} = $alive ? $rtt : undef; $self->{ping_time} = time; $self->rtt; } 1; =back =head1 AUTHOR Andreas Koenig C<< >>, David Golden C<< >>, brian d foy C<< >> =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L =cut perl5/CPAN/Shell.pm000044400000217724152530123070007732 0ustar00package CPAN::Shell; use strict; # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: use vars qw( $ADVANCED_QUERY $AUTOLOAD $COLOR_REGISTERED $Help $autoload_recursion $reload @ISA @relo $VERSION ); @relo = ( "CPAN.pm", "CPAN/Author.pm", "CPAN/CacheMgr.pm", "CPAN/Complete.pm", "CPAN/Debug.pm", "CPAN/DeferredCode.pm", "CPAN/Distribution.pm", "CPAN/Distroprefs.pm", "CPAN/Distrostatus.pm", "CPAN/Exception/RecursiveDependency.pm", "CPAN/Exception/yaml_not_installed.pm", "CPAN/FirstTime.pm", "CPAN/FTP.pm", "CPAN/FTP/netrc.pm", "CPAN/HandleConfig.pm", "CPAN/Index.pm", "CPAN/InfoObj.pm", "CPAN/Kwalify.pm", "CPAN/LWP/UserAgent.pm", "CPAN/Module.pm", "CPAN/Prompt.pm", "CPAN/Queue.pm", "CPAN/Reporter/Config.pm", "CPAN/Reporter/History.pm", "CPAN/Reporter/PrereqCheck.pm", "CPAN/Reporter.pm", "CPAN/Shell.pm", "CPAN/SQLite.pm", "CPAN/Tarzip.pm", "CPAN/Version.pm", ); $VERSION = "5.5009"; # record the initial timestamp for reload. $reload = { map {$INC{$_} ? ($_,(stat $INC{$_})[9]) : ()} @relo }; @CPAN::Shell::ISA = qw(CPAN::Debug); use Cwd qw(chdir); use Carp (); $COLOR_REGISTERED ||= 0; $Help = { '?' => \"help", '!' => "eval the rest of the line as perl", a => "whois author", autobundle => "write inventory into a bundle file", b => "info about bundle", bye => \"quit", clean => "clean up a distribution's build directory", # cvs_import d => "info about a distribution", # dump exit => \"quit", failed => "list all failed actions within current session", fforce => "redo a command from scratch", force => "redo a command", get => "download a distribution", h => \"help", help => "overview over commands; 'help ...' explains specific commands", hosts => "statistics about recently used hosts", i => "info about authors/bundles/distributions/modules", install => "install a distribution", install_tested => "install all distributions tested OK", is_tested => "list all distributions tested OK", look => "open a subshell in a distribution's directory", ls => "list distributions matching a fileglob", m => "info about a module", make => "make/build a distribution", mkmyconfig => "write current config into a CPAN/MyConfig.pm file", notest => "run a (usually install) command but leave out the test phase", o => "'o conf ...' for config stuff; 'o debug ...' for debugging", perldoc => "try to get a manpage for a module", q => \"quit", quit => "leave the cpan shell", r => "review upgradable modules", readme => "display the README of a distro with a pager", recent => "show recent uploads to the CPAN", # recompile reload => "'reload cpan' or 'reload index'", report => "test a distribution and send a test report to cpantesters", reports => "info about reported tests from cpantesters", # scripts # smoke test => "test a distribution", u => "display uninstalled modules", upgrade => "combine 'r' command with immediate installation", }; { $autoload_recursion ||= 0; #-> sub CPAN::Shell::AUTOLOAD ; sub AUTOLOAD { ## no critic $autoload_recursion++; my($l) = $AUTOLOAD; my $class = shift(@_); # warn "autoload[$l] class[$class]"; $l =~ s/.*:://; if ($CPAN::Signal) { warn "Refusing to autoload '$l' while signal pending"; $autoload_recursion--; return; } if ($autoload_recursion > 1) { my $fullcommand = join " ", map { "'$_'" } $l, @_; warn "Refusing to autoload $fullcommand in recursion\n"; $autoload_recursion--; return; } if ($l =~ /^w/) { # XXX needs to be reconsidered if ($CPAN::META->has_inst('CPAN::WAIT')) { CPAN::WAIT->$l(@_); } else { $CPAN::Frontend->mywarn(qq{ Commands starting with "w" require CPAN::WAIT to be installed. Please consider installing CPAN::WAIT to use the fulltext index. For this you just need to type install CPAN::WAIT }); } } else { $CPAN::Frontend->mywarn(qq{Unknown shell command '$l'. }. qq{Type ? for help. }); } $autoload_recursion--; } } #-> sub CPAN::Shell::h ; sub h { my($class,$about) = @_; if (defined $about) { my $help; if (exists $Help->{$about}) { if (ref $Help->{$about}) { # aliases $about = ${$Help->{$about}}; } $help = $Help->{$about}; } else { $help = "No help available"; } $CPAN::Frontend->myprint("$about\: $help\n"); } else { my $filler = " " x (80 - 28 - length($CPAN::VERSION)); $CPAN::Frontend->myprint(qq{ Display Information $filler (ver $CPAN::VERSION) command argument description a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules i WORD or /REGEXP/ about any of the above ls AUTHOR or GLOB about files in the author's directory (with WORD being a module, bundle or author name or a distribution name of the form AUTHOR/DISTRIBUTION) Download, Test, Make, Install... get download clean make clean make make (implies get) look open subshell in dist directory test make test (implies make) readme display these README files install make install (implies test) perldoc display POD documentation Upgrade installed modules r WORDs or /REGEXP/ or NONE report updates for some/matching/all upgrade WORDs or /REGEXP/ or NONE upgrade some/matching/all modules Pragmas force CMD try hard to do command fforce CMD try harder notest CMD skip testing Other h,? display this menu ! perl-code eval a perl command o conf [opt] set and query options q quit the cpan shell reload cpan load CPAN.pm again reload index load newer indices autobundle Snapshot recent latest CPAN uploads}); } } *help = \&h; #-> sub CPAN::Shell::a ; sub a { my($self,@arg) = @_; # authors are always UPPERCASE for (@arg) { $_ = uc $_ unless /=/; } $CPAN::Frontend->myprint($self->format_result('Author',@arg)); } #-> sub CPAN::Shell::globls ; sub globls { my($self,$s,$pragmas) = @_; # ls is really very different, but we had it once as an ordinary # command in the Shell (up to rev. 321) and we could not handle # force well then my(@accept,@preexpand); if ($s =~ /[\*\?\/]/) { if ($CPAN::META->has_inst("Text::Glob")) { if (my($au,$pathglob) = $s =~ m|(.*?)/(.*)|) { my $rau = Text::Glob::glob_to_regex(uc $au); CPAN::Shell->debug("au[$au]pathglob[$pathglob]rau[$rau]") if $CPAN::DEBUG; push @preexpand, map { $_->id . "/" . $pathglob } CPAN::Shell->expand_by_method('CPAN::Author',['id'],"/$rau/"); } else { my $rau = Text::Glob::glob_to_regex(uc $s); push @preexpand, map { $_->id } CPAN::Shell->expand_by_method('CPAN::Author', ['id'], "/$rau/"); } } else { $CPAN::Frontend->mydie("Text::Glob not installed, cannot proceed"); } } else { push @preexpand, uc $s; } for (@preexpand) { unless (/^[A-Z0-9\-]+(\/|$)/i) { $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author\n"); next; } push @accept, $_; } my $silent = @accept>1; my $last_alpha = ""; my @results; for my $a (@accept) { my($author,$pathglob); if ($a =~ m|(.*?)/(.*)|) { my $a2 = $1; $pathglob = $2; $author = CPAN::Shell->expand_by_method('CPAN::Author', ['id'], $a2) or $CPAN::Frontend->mydie("No author found for $a2\n"); } else { $author = CPAN::Shell->expand_by_method('CPAN::Author', ['id'], $a) or $CPAN::Frontend->mydie("No author found for $a\n"); } if ($silent) { my $alpha = substr $author->id, 0, 1; my $ad; if ($alpha eq $last_alpha) { $ad = ""; } else { $ad = "[$alpha]"; $last_alpha = $alpha; } $CPAN::Frontend->myprint($ad); } for my $pragma (@$pragmas) { if ($author->can($pragma)) { $author->$pragma(); } } CPAN->debug("author[$author]pathglob[$pathglob]silent[$silent]") if $CPAN::DEBUG; push @results, $author->ls($pathglob,$silent); # silent if # more than one # author for my $pragma (@$pragmas) { my $unpragma = "un$pragma"; if ($author->can($unpragma)) { $author->$unpragma(); } } } @results; } #-> sub CPAN::Shell::local_bundles ; sub local_bundles { my($self,@which) = @_; my($incdir,$bdir,$dh); foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) { my @bbase = "Bundle"; while (my $bbase = shift @bbase) { $bdir = File::Spec->catdir($incdir,split /::/, $bbase); CPAN->debug("bdir[$bdir]\@bbase[@bbase]") if $CPAN::DEBUG; if ($dh = DirHandle->new($bdir)) { # may fail my($entry); for $entry ($dh->read) { next if $entry =~ /^\./; next unless $entry =~ /^\w+(\.pm)?(?!\n)\Z/; if (-d File::Spec->catdir($bdir,$entry)) { push @bbase, "$bbase\::$entry"; } else { next unless $entry =~ s/\.pm(?!\n)\Z//; $CPAN::META->instance('CPAN::Bundle',"$bbase\::$entry"); } } } } } } #-> sub CPAN::Shell::b ; sub b { my($self,@which) = @_; CPAN->debug("which[@which]") if $CPAN::DEBUG; $self->local_bundles; $CPAN::Frontend->myprint($self->format_result('Bundle',@which)); } #-> sub CPAN::Shell::d ; sub d { $CPAN::Frontend->myprint(shift->format_result('Distribution',@_));} #-> sub CPAN::Shell::m ; sub m { # emacs confused here }; sub mimimimimi { # emacs in sync here my $self = shift; my @m = @_; for (@m) { if (m|(?:\w+/)*\w+\.pm$|) { # same regexp in expandany s/.pm$//; s|/|::|g; } } $CPAN::Frontend->myprint($self->format_result('Module',@m)); } #-> sub CPAN::Shell::i ; sub i { my($self) = shift; my(@args) = @_; @args = '/./' unless @args; my(@result); for my $type (qw/Bundle Distribution Module/) { push @result, $self->expand($type,@args); } # Authors are always uppercase. push @result, $self->expand("Author", map { uc $_ } @args); my $result = @result == 1 ? $result[0]->as_string : @result == 0 ? "No objects found of any type for argument @args\n" : join("", (map {$_->as_glimpse} @result), scalar @result, " items found\n", ); $CPAN::Frontend->myprint($result); } #-> sub CPAN::Shell::o ; # CPAN::Shell::o and CPAN::HandleConfig::edit are closely related. 'o # conf' calls through to CPAN::HandleConfig::edit. 'o conf' should # probably have been called 'set' and 'o debug' maybe 'set debug' or # 'debug'; 'o conf ARGS' calls ->edit in CPAN/HandleConfig.pm sub o { my($self,$o_type,@o_what) = @_; $o_type ||= ""; CPAN->debug("o_type[$o_type] o_what[".join(" | ",@o_what)."]\n"); if ($o_type eq 'conf') { my($cfilter); ($cfilter) = $o_what[0] =~ m|^/(.*)/$| if @o_what; if (!@o_what or $cfilter) { # print all things, "o conf" $cfilter ||= ""; my $qrfilter = eval 'qr/$cfilter/'; if ($@) { $CPAN::Frontend->mydie("Cannot parse commandline: $@"); } my($k,$v); my $configpm = CPAN::HandleConfig->require_myconfig_or_config; $CPAN::Frontend->myprint("\$CPAN::Config options from $configpm\:\n"); for $k (sort keys %CPAN::HandleConfig::can) { next unless $k =~ /$qrfilter/; $v = $CPAN::HandleConfig::can{$k}; $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, $v); } $CPAN::Frontend->myprint("\n"); for $k (sort keys %CPAN::HandleConfig::keys) { next unless $k =~ /$qrfilter/; CPAN::HandleConfig->prettyprint($k); } $CPAN::Frontend->myprint("\n"); } else { if (CPAN::HandleConfig->edit(@o_what)) { } else { $CPAN::Frontend->myprint(qq{Type 'o conf' to view all configuration }. qq{items\n\n}); } } } elsif ($o_type eq 'debug') { my(%valid); @o_what = () if defined $o_what[0] && $o_what[0] =~ /help/i; if (@o_what) { while (@o_what) { my($what) = shift @o_what; if ($what =~ s/^-// && exists $CPAN::DEBUG{$what}) { $CPAN::DEBUG &= $CPAN::DEBUG ^ $CPAN::DEBUG{$what}; next; } if ( exists $CPAN::DEBUG{$what} ) { $CPAN::DEBUG |= $CPAN::DEBUG{$what}; } elsif ($what =~ /^\d/) { $CPAN::DEBUG = $what; } elsif (lc $what eq 'all') { my($max) = 0; for (values %CPAN::DEBUG) { $max += $_; } $CPAN::DEBUG = $max; } else { my($known) = 0; for (keys %CPAN::DEBUG) { next unless lc($_) eq lc($what); $CPAN::DEBUG |= $CPAN::DEBUG{$_}; $known = 1; } $CPAN::Frontend->myprint("unknown argument [$what]\n") unless $known; } } } else { my $raw = "Valid options for debug are ". join(", ",sort(keys %CPAN::DEBUG), 'all'). qq{ or a number. Completion works on the options. }. qq{Case is ignored.}; require Text::Wrap; $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw)); $CPAN::Frontend->myprint("\n\n"); } if ($CPAN::DEBUG) { $CPAN::Frontend->myprint("Options set for debugging ($CPAN::DEBUG):\n"); my($k,$v); for $k (sort {$CPAN::DEBUG{$a} <=> $CPAN::DEBUG{$b}} keys %CPAN::DEBUG) { $v = $CPAN::DEBUG{$k}; $CPAN::Frontend->myprint(sprintf " %-14s(%s)\n", $k, $v) if $v & $CPAN::DEBUG; } } else { $CPAN::Frontend->myprint("Debugging turned off completely.\n"); } } else { $CPAN::Frontend->myprint(qq{ Known options: conf set or get configuration variables debug set or get debugging options }); } } # CPAN::Shell::paintdots_onreload sub paintdots_onreload { my($ref) = shift; sub { if ( $_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) { my($subr) = $1; ++$$ref; local($|) = 1; # $CPAN::Frontend->myprint(".($subr)"); $CPAN::Frontend->myprint("."); if ($subr =~ /\bshell\b/i) { # warn "debug[$_[0]]"; # It would be nice if we could detect that a # subroutine has actually changed, but for now we # practically always set the GOTOSHELL global $CPAN::GOTOSHELL=1; } return; } warn @_; }; } #-> sub CPAN::Shell::hosts ; sub hosts { my($self) = @_; my $fullstats = CPAN::FTP->_ftp_statistics(); my $history = $fullstats->{history} || []; my %S; # statistics while (my $last = pop @$history) { my $attempts = $last->{attempts} or next; my $start; if (@$attempts) { $start = $attempts->[-1]{start}; if ($#$attempts > 0) { for my $i (0..$#$attempts-1) { my $url = $attempts->[$i]{url} or next; $S{no}{$url}++; } } } else { $start = $last->{start}; } next unless $last->{thesiteurl}; # C-C? bad filenames? $S{start} = $start; $S{end} ||= $last->{end}; my $dltime = $last->{end} - $start; my $dlsize = $last->{filesize} || 0; my $url = ref $last->{thesiteurl} ? $last->{thesiteurl}->text : $last->{thesiteurl}; my $s = $S{ok}{$url} ||= {}; $s->{n}++; $s->{dlsize} ||= 0; $s->{dlsize} += $dlsize/1024; $s->{dltime} ||= 0; $s->{dltime} += $dltime; } my $res; for my $url (sort keys %{$S{ok}}) { next if $S{ok}{$url}{dltime} == 0; # div by zero push @{$res->{ok}}, [@{$S{ok}{$url}}{qw(n dlsize dltime)}, $S{ok}{$url}{dlsize}/$S{ok}{$url}{dltime}, $url, ]; } for my $url (sort keys %{$S{no}}) { push @{$res->{no}}, [$S{no}{$url}, $url, ]; } my $R = ""; # report if ($S{start} && $S{end}) { $R .= sprintf "Log starts: %s\n", $S{start} ? scalar(localtime $S{start}) : "unknown"; $R .= sprintf "Log ends : %s\n", $S{end} ? scalar(localtime $S{end}) : "unknown"; } if ($res->{ok} && @{$res->{ok}}) { $R .= sprintf "\nSuccessful downloads: N kB secs kB/s url\n"; my $i = 20; for (sort { $b->[3] <=> $a->[3] } @{$res->{ok}}) { $R .= sprintf "%4d %8d %5d %9.1f %s\n", @$_; last if --$i<=0; } } if ($res->{no} && @{$res->{no}}) { $R .= sprintf "\nUnsuccessful downloads:\n"; my $i = 20; for (sort { $b->[0] <=> $a->[0] } @{$res->{no}}) { $R .= sprintf "%4d %s\n", @$_; last if --$i<=0; } } $CPAN::Frontend->myprint($R); } # here is where 'reload cpan' is done #-> sub CPAN::Shell::reload ; sub reload { my($self,$command,@arg) = @_; $command ||= ""; $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG; if ($command =~ /^cpan$/i) { my $redef = 0; chdir "$CPAN::iCwd" if $CPAN::iCwd; # may fail my $failed; MFILE: for my $f (@relo) { next unless exists $INC{$f}; my $p = $f; $p =~ s/\.pm$//; $p =~ s|/|::|g; $CPAN::Frontend->myprint("($p"); local($SIG{__WARN__}) = paintdots_onreload(\$redef); $self->_reload_this($f) or $failed++; my $v = eval "$p\::->VERSION"; $CPAN::Frontend->myprint("v$v)"); } $CPAN::Frontend->myprint("\n$redef subroutines redefined\n"); if ($failed) { my $errors = $failed == 1 ? "error" : "errors"; $CPAN::Frontend->mywarn("\n$failed $errors during reload. You better quit ". "this session.\n"); } } elsif ($command =~ /^index$/i) { CPAN::Index->force_reload; } else { $CPAN::Frontend->myprint(qq{cpan re-evals the CPAN modules index re-reads the index files\n}); } } # reload means only load again what we have loaded before #-> sub CPAN::Shell::_reload_this ; sub _reload_this { my($self,$f,$args) = @_; CPAN->debug("f[$f]") if $CPAN::DEBUG; return 1 unless $INC{$f}; # we never loaded this, so we do not # reload but say OK my $pwd = CPAN::anycwd(); CPAN->debug("pwd[$pwd]") if $CPAN::DEBUG; my($file); for my $inc (@INC) { $file = File::Spec->catfile($inc,split /\//, $f); last if -f $file; $file = ""; } CPAN->debug("file[$file]") if $CPAN::DEBUG; my @inc = @INC; unless ($file && -f $file) { # this thingy is not in the INC path, maybe CPAN/MyConfig.pm? $file = $INC{$f}; unless (CPAN->has_inst("File::Basename")) { @inc = File::Basename::dirname($file); } else { # do we ever need this? @inc = substr($file,0,-length($f)-1); # bring in back to me! } } CPAN->debug("file[$file]inc[@inc]") if $CPAN::DEBUG; unless (-f $file) { $CPAN::Frontend->mywarn("Found no file to reload for '$f'\n"); return; } my $mtime = (stat $file)[9]; $reload->{$f} ||= -1; my $must_reload = $mtime != $reload->{$f}; $args ||= {}; $must_reload ||= $args->{reloforce}; # o conf defaults needs this if ($must_reload) { my $fh = FileHandle->new($file) or $CPAN::Frontend->mydie("Could not open $file: $!"); my $content; { local($/); local $^W = 1; $content = <$fh>; } CPAN->debug(sprintf("reload file[%s] content[%s...]",$file,substr($content,0,128))) if $CPAN::DEBUG; my $includefile; if ($includefile = $INC{$f} and -e $includefile) { $f = $includefile; } delete $INC{$f}; local @INC = @inc; eval "require '$f'"; if ($@) { warn $@; return; } $reload->{$f} = $mtime; } else { $CPAN::Frontend->myprint("__unchanged__"); } return 1; } #-> sub CPAN::Shell::mkmyconfig ; sub mkmyconfig { my($self) = @_; if ( my $configpm = $INC{'CPAN/MyConfig.pm'} ) { $CPAN::Frontend->myprint( "CPAN::MyConfig already exists as $configpm.\n" . "Running configuration again...\n" ); require CPAN::FirstTime; CPAN::FirstTime::init($configpm); } else { # force some missing values to be filled in with defaults delete $CPAN::Config->{$_} for qw/build_dir cpan_home keep_source_where histfile/; CPAN::HandleConfig->load( make_myconfig => 1 ); } } #-> sub CPAN::Shell::_binary_extensions ; sub _binary_extensions { my($self) = shift @_; my(@result,$module,%seen,%need,$headerdone); for $module ($self->expand('Module','/./')) { my $file = $module->cpan_file; next if $file eq "N/A"; next if $file =~ /^Contact Author/; my $dist = $CPAN::META->instance('CPAN::Distribution',$file); next if $dist->isa_perl; next unless $module->xs_file; local($|) = 1; $CPAN::Frontend->myprint("."); push @result, $module; } # print join " | ", @result; $CPAN::Frontend->myprint("\n"); return @result; } #-> sub CPAN::Shell::recompile ; sub recompile { my($self) = shift @_; my($module,@module,$cpan_file,%dist); @module = $self->_binary_extensions(); for $module (@module) { # we force now and compile later, so we # don't do it twice $cpan_file = $module->cpan_file; my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); $pack->force; $dist{$cpan_file}++; } for $cpan_file (sort keys %dist) { $CPAN::Frontend->myprint(" CPAN: Recompiling $cpan_file\n\n"); my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); $pack->install; $CPAN::Signal = 0; # it's tempting to reset Signal, so we can # stop a package from recompiling, # e.g. IO-1.12 when we have perl5.003_10 } } #-> sub CPAN::Shell::scripts ; sub scripts { my($self, $arg) = @_; $CPAN::Frontend->mywarn(">>>> experimental command, currently unsupported <<<<\n\n"); for my $req (qw( HTML::LinkExtor Sort::Versions List::Util )) { unless ($CPAN::META->has_inst($req)) { $CPAN::Frontend->mywarn(" $req not available\n"); } } my $p = HTML::LinkExtor->new(); my $indexfile = "/home/ftp/pub/PAUSE/scripts/new/index.html"; unless (-f $indexfile) { $CPAN::Frontend->mydie("found no indexfile[$indexfile]\n"); } $p->parse_file($indexfile); my @hrefs; my $qrarg; if ($arg =~ s|^/(.+)/$|$1|) { $qrarg = eval 'qr/$arg/'; # hide construct from 5.004 } for my $l ($p->links) { my $tag = shift @$l; next unless $tag eq "a"; my %att = @$l; my $href = $att{href}; next unless $href =~ s|^\.\./authors/id/./../||; if ($arg) { if ($qrarg) { if ($href =~ $qrarg) { push @hrefs, $href; } } else { if ($href =~ /\Q$arg\E/) { push @hrefs, $href; } } } else { push @hrefs, $href; } } # now filter for the latest version if there is more than one of a name my %stems; for (sort @hrefs) { my $href = $_; s/-v?\d.*//; my $stem = $_; $stems{$stem} ||= []; push @{$stems{$stem}}, $href; } for (sort keys %stems) { my $highest; if (@{$stems{$_}} > 1) { $highest = List::Util::reduce { Sort::Versions::versioncmp($a,$b) > 0 ? $a : $b } @{$stems{$_}}; } else { $highest = $stems{$_}[0]; } $CPAN::Frontend->myprint("$highest\n"); } } sub _guess_manpage { my($self,$d,$contains,$dist) = @_; $dist =~ s/-/::/g; my $module; if (exists $contains->{$dist}) { $module = $dist; } elsif (1 == keys %$contains) { ($module) = keys %$contains; } my $manpage; if ($module) { my $m = $self->expand("Module",$module); $m->as_string; # called for side-effects, shame $manpage = $m->{MANPAGE}; } else { $manpage = "unknown"; } return $manpage; } #-> sub CPAN::Shell::_specfile ; sub _specfile { die "CPAN::Shell::_specfile() has been moved to CPAN::Plugin::Specfile::post_test()"; } #-> sub CPAN::Shell::report ; sub report { my($self,@args) = @_; unless ($CPAN::META->has_inst("CPAN::Reporter")) { $CPAN::Frontend->mydie("CPAN::Reporter not installed; cannot continue"); } local $CPAN::Config->{test_report} = 1; $self->force("test",@args); # force is there so that the test be # re-run (as documented) } # compare with is_tested #-> sub CPAN::Shell::install_tested sub install_tested { my($self,@some) = @_; $CPAN::Frontend->mywarn("install_tested() must not be called with arguments.\n"), return if @some; CPAN::Index->reload; for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) { my $yaml = "$b.yml"; unless (-f $yaml) { $CPAN::Frontend->mywarn("No YAML file for $b available, skipping\n"); next; } my $yaml_content = CPAN->_yaml_loadfile($yaml); my $id = $yaml_content->[0]{distribution}{ID}; unless ($id) { $CPAN::Frontend->mywarn("No ID found in '$yaml', skipping\n"); next; } my $do = CPAN::Shell->expandany($id); unless ($do) { $CPAN::Frontend->mywarn("Could not expand ID '$id', skipping\n"); next; } unless ($do->{build_dir}) { $CPAN::Frontend->mywarn("Distro '$id' has no build_dir, skipping\n"); next; } unless ($do->{build_dir} eq $b) { $CPAN::Frontend->mywarn("Distro '$id' has build_dir '$do->{build_dir}' but expected '$b', skipping\n"); next; } push @some, $do; } $CPAN::Frontend->mywarn("No tested distributions found.\n"), return unless @some; @some = grep { $_->{make_test} && ! $_->{make_test}->failed } @some; $CPAN::Frontend->mywarn("No distributions tested with this build of perl found.\n"), return unless @some; # @some = grep { not $_->uptodate } @some; # $CPAN::Frontend->mywarn("No non-uptodate distributions tested with this build of perl found.\n"), # return unless @some; CPAN->debug("some[@some]"); for my $d (@some) { my $id = $d->can("pretty_id") ? $d->pretty_id : $d->id; $CPAN::Frontend->myprint("install_tested: Running for $id\n"); $CPAN::Frontend->mysleep(1); $self->install($d); } } #-> sub CPAN::Shell::upgrade ; sub upgrade { my($self,@args) = @_; $self->install($self->r(@args)); } #-> sub CPAN::Shell::_u_r_common ; sub _u_r_common { my($self) = shift @_; my($what) = shift @_; CPAN->debug("self[$self] what[$what] args[@_]") if $CPAN::DEBUG; Carp::croak "Usage: \$obj->_u_r_common(a|r|u)" unless $what && $what =~ /^[aru]$/; my(@args) = @_; @args = '/./' unless @args; my(@result,$module,%seen,%need,$headerdone, $version_undefs,$version_zeroes, @version_undefs,@version_zeroes); $version_undefs = $version_zeroes = 0; my $sprintf = "%s%-25s%s %9s %9s %s\n"; my @expand = $self->expand('Module',@args); if ($CPAN::DEBUG) { # Looks like noise to me, was very useful for debugging # for metadata cache my $expand = scalar @expand; $CPAN::Frontend->myprint(sprintf "%d matches in the database, time[%d]\n", $expand, time); } my @sexpand; if ($] < 5.008) { # hard to believe that the more complex sorting can lead to # stack curruptions on older perl @sexpand = sort {$a->id cmp $b->id} @expand; } else { @sexpand = map { $_->[1] } sort { $b->[0] <=> $a->[0] || $a->[1]{ID} cmp $b->[1]{ID}, } map { [$_->_is_representative_module, $_ ] } @expand; } if ($CPAN::DEBUG) { $CPAN::Frontend->myprint(sprintf "sorted at time[%d]\n", time); sleep 1; } MODULE: for $module (@sexpand) { my $file = $module->cpan_file; next MODULE unless defined $file; # ?? $file =~ s!^./../!!; my($latest) = $module->cpan_version; my($inst_file) = $module->inst_file; CPAN->debug("file[$file]latest[$latest]") if $CPAN::DEBUG; my($have); return if $CPAN::Signal; my($next_MODULE); eval { # version.pm involved! if ($inst_file) { if ($what eq "a") { $have = $module->inst_version; } elsif ($what eq "r") { $have = $module->inst_version; local($^W) = 0; if ($have eq "undef") { $version_undefs++; push @version_undefs, $module->as_glimpse; } elsif (CPAN::Version->vcmp($have,0)==0) { $version_zeroes++; push @version_zeroes, $module->as_glimpse; } ++$next_MODULE unless CPAN::Version->vgt($latest, $have); # to be pedantic we should probably say: # && !($have eq "undef" && $latest ne "undef" && $latest gt ""); # to catch the case where CPAN has a version 0 and we have a version undef } elsif ($what eq "u") { ++$next_MODULE; } } else { if ($what eq "a") { ++$next_MODULE; } elsif ($what eq "r") { ++$next_MODULE; } elsif ($what eq "u") { $have = "-"; } } }; next MODULE if $next_MODULE; if ($@) { $CPAN::Frontend->mywarn (sprintf("Error while comparing cpan/installed versions of '%s': INST_FILE: %s INST_VERSION: %s %s CPAN_VERSION: %s %s ", $module->id, $inst_file || "", (defined $have ? $have : "[UNDEFINED]"), (ref $have ? ref $have : ""), $latest, (ref $latest ? ref $latest : ""), )); next MODULE; } return if $CPAN::Signal; # this is sometimes lengthy $seen{$file} ||= 0; if ($what eq "a") { push @result, sprintf "%s %s\n", $module->id, $have; } elsif ($what eq "r") { push @result, $module->id; next MODULE if $seen{$file}++; } elsif ($what eq "u") { push @result, $module->id; next MODULE if $seen{$file}++; next MODULE if $file =~ /^Contact/; } unless ($headerdone++) { $CPAN::Frontend->myprint("\n"); $CPAN::Frontend->myprint(sprintf( $sprintf, "", "Package namespace", "", "installed", "latest", "in CPAN file" )); } my $color_on = ""; my $color_off = ""; if ( $COLOR_REGISTERED && $CPAN::META->has_inst("Term::ANSIColor") && $module->description ) { $color_on = Term::ANSIColor::color("green"); $color_off = Term::ANSIColor::color("reset"); } $CPAN::Frontend->myprint(sprintf $sprintf, $color_on, $module->id, $color_off, $have, $latest, $file); $need{$module->id}++; } unless (%need) { if (!@expand || $what eq "u") { $CPAN::Frontend->myprint("No modules found for @args\n"); } elsif ($what eq "r") { $CPAN::Frontend->myprint("All modules are up to date for @args\n"); } } if ($what eq "r") { if ($version_zeroes) { my $s_has = $version_zeroes > 1 ? "s have" : " has"; $CPAN::Frontend->myprint(qq{$version_zeroes installed module$s_has }. qq{a version number of 0\n}); if ($CPAN::Config->{show_zero_versions}) { local $" = "\t"; $CPAN::Frontend->myprint(qq{ they are\n\t@version_zeroes\n}); $CPAN::Frontend->myprint(qq{(use 'o conf show_zero_versions 0' }. qq{to hide them)\n}); } else { $CPAN::Frontend->myprint(qq{(use 'o conf show_zero_versions 1' }. qq{to show them)\n}); } } if ($version_undefs) { my $s_has = $version_undefs > 1 ? "s have" : " has"; $CPAN::Frontend->myprint(qq{$version_undefs installed module$s_has no }. qq{parsable version number\n}); if ($CPAN::Config->{show_unparsable_versions}) { local $" = "\t"; $CPAN::Frontend->myprint(qq{ they are\n\t@version_undefs\n}); $CPAN::Frontend->myprint(qq{(use 'o conf show_unparsable_versions 0' }. qq{to hide them)\n}); } else { $CPAN::Frontend->myprint(qq{(use 'o conf show_unparsable_versions 1' }. qq{to show them)\n}); } } } @result; } #-> sub CPAN::Shell::r ; sub r { shift->_u_r_common("r",@_); } #-> sub CPAN::Shell::u ; sub u { shift->_u_r_common("u",@_); } #-> sub CPAN::Shell::failed ; sub failed { my($self,$only_id,$silent) = @_; my @failed = $self->find_failed($only_id); my $scope; if ($only_id) { $scope = "this command"; } elsif ($CPAN::Index::HAVE_REANIMATED) { $scope = "this or a previous session"; # it might be nice to have a section for previous session and # a second for this } else { $scope = "this session"; } if (@failed) { my $print; my $debug = 0; if ($debug) { $print = join "", map { sprintf "%5d %-45s: %s %s\n", @$_ } sort { $a->[0] <=> $b->[0] } @failed; } else { $print = join "", map { sprintf " %-45s: %s %s\n", @$_[1..3] } sort { $a->[0] <=> $b->[0] || $a->[4] <=> $b->[4] } @failed; } $CPAN::Frontend->myprint("Failed during $scope:\n$print"); } elsif (!$only_id || !$silent) { $CPAN::Frontend->myprint("Nothing failed in $scope\n"); } } sub find_failed { my($self,$only_id) = @_; my @failed; DIST: for my $d (sort { $a->id cmp $b->id } $CPAN::META->all_objects("CPAN::Distribution")) { my $failed = ""; NAY: for my $nosayer ( # order matters! "unwrapped", "writemakefile", "signature_verify", "make", "make_test", "install", "make_clean", ) { next unless exists $d->{$nosayer}; next unless defined $d->{$nosayer}; next unless ( UNIVERSAL::can($d->{$nosayer},"failed") ? $d->{$nosayer}->failed : $d->{$nosayer} =~ /^NO/ ); next NAY if $only_id && $only_id != ( UNIVERSAL::can($d->{$nosayer},"commandid") ? $d->{$nosayer}->commandid : $CPAN::CurrentCommandId ); $failed = $nosayer; last; } next DIST unless $failed; my $id = $d->id; $id =~ s|^./../||; ### XXX need to flag optional modules as '(optional)' if they are # from recommends/suggests -- i.e. *show* failure, but make it clear # it was failure of optional module -- xdg, 2012-04-01 $id = "(optional) $id" if ! $d->{mandatory}; #$print .= sprintf( # " %-45s: %s %s\n", push @failed, ( UNIVERSAL::can($d->{$failed},"failed") ? [ $d->{$failed}->commandid, $id, $failed, $d->{$failed}->text, $d->{$failed}{TIME}||0, !! $d->{mandatory}, ] : [ 1, $id, $failed, $d->{$failed}, 0, !! $d->{mandatory}, ] ); } return @failed; } sub mandatory_dist_failed { my ($self) = @_; return grep { $_->[5] } $self->find_failed($CPAN::CurrentCommandID); } # XXX intentionally undocumented because completely bogus, unportable, # useless, etc. #-> sub CPAN::Shell::status ; sub status { my($self) = @_; require Devel::Size; my $ps = FileHandle->new; open $ps, "/proc/$$/status"; my $vm = 0; while (<$ps>) { next unless /VmSize:\s+(\d+)/; $vm = $1; last; } $CPAN::Frontend->mywarn(sprintf( "%-27s %6d\n%-27s %6d\n", "vm", $vm, "CPAN::META", Devel::Size::total_size($CPAN::META)/1024, )); for my $k (sort keys %$CPAN::META) { next unless substr($k,0,4) eq "read"; warn sprintf " %-26s %6d\n", $k, Devel::Size::total_size($CPAN::META->{$k})/1024; for my $k2 (sort keys %{$CPAN::META->{$k}}) { warn sprintf " %-25s %6d (keys: %6d)\n", $k2, Devel::Size::total_size($CPAN::META->{$k}{$k2})/1024, scalar keys %{$CPAN::META->{$k}{$k2}}; } } } # compare with install_tested #-> sub CPAN::Shell::is_tested sub is_tested { my($self) = @_; CPAN::Index->reload; for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) { my $time; if ($CPAN::META->{is_tested}{$b}) { $time = scalar(localtime $CPAN::META->{is_tested}{$b}); } else { $time = scalar localtime; $time =~ s/\S/?/g; } $CPAN::Frontend->myprint(sprintf "%s %s\n", $time, $b); } } #-> sub CPAN::Shell::autobundle ; sub autobundle { my($self) = shift; CPAN::HandleConfig->load unless $CPAN::Config_loaded++; my(@bundle) = $self->_u_r_common("a",@_); my($todir) = File::Spec->catdir($CPAN::Config->{'cpan_home'},"Bundle"); File::Path::mkpath($todir); unless (-d $todir) { $CPAN::Frontend->myprint("Couldn't mkdir $todir for some reason\n"); return; } my($y,$m,$d) = (localtime)[5,4,3]; $y+=1900; $m++; my($c) = 0; my($me) = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, $c; my($to) = File::Spec->catfile($todir,"$me.pm"); while (-f $to) { $me = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, ++$c; $to = File::Spec->catfile($todir,"$me.pm"); } my($fh) = FileHandle->new(">$to") or Carp::croak "Can't open >$to: $!"; $fh->print( "package Bundle::$me;\n\n", "\$","VERSION = '0.01';\n\n", # hide from perl-reversion "1;\n\n", "__END__\n\n", "=head1 NAME\n\n", "Bundle::$me - Snapshot of installation on ", $Config::Config{'myhostname'}, " on ", scalar(localtime), "\n\n=head1 SYNOPSIS\n\n", "perl -MCPAN -e 'install Bundle::$me'\n\n", "=head1 CONTENTS\n\n", join("\n", @bundle), "\n\n=head1 CONFIGURATION\n\n", Config->myconfig, "\n\n=head1 AUTHOR\n\n", "This Bundle has been generated automatically ", "by the autobundle routine in CPAN.pm.\n", ); $fh->close; $CPAN::Frontend->myprint("\nWrote bundle file $to\n\n"); return $to; } #-> sub CPAN::Shell::expandany ; sub expandany { my($self,$s) = @_; CPAN->debug("s[$s]") if $CPAN::DEBUG; my $module_as_path = ""; if ($s =~ m|(?:\w+/)*\w+\.pm$|) { # same regexp in sub m $module_as_path = $s; $module_as_path =~ s/.pm$//; $module_as_path =~ s|/|::|g; } if ($module_as_path) { if ($module_as_path =~ m|^Bundle::|) { $self->local_bundles; return $self->expand('Bundle',$module_as_path); } else { return $self->expand('Module',$module_as_path) if $CPAN::META->exists('CPAN::Module',$module_as_path); } } elsif ($s =~ m|/| or substr($s,-1,1) eq ".") { # looks like a file or a directory $s = CPAN::Distribution->normalize($s); return $CPAN::META->instance('CPAN::Distribution',$s); # Distributions spring into existence, not expand } elsif ($s =~ m|^Bundle::|) { $self->local_bundles; # scanning so late for bundles seems # both attractive and crumpy: always # current state but easy to forget # somewhere return $self->expand('Bundle',$s); } else { return $self->expand('Module',$s) if $CPAN::META->exists('CPAN::Module',$s); } return; } #-> sub CPAN::Shell::expand ; sub expand { my $self = shift; my($type,@args) = @_; CPAN->debug("type[$type]args[@args]") if $CPAN::DEBUG; my $class = "CPAN::$type"; my $methods = ['id']; for my $meth (qw(name)) { next unless $class->can($meth); push @$methods, $meth; } $self->expand_by_method($class,$methods,@args); } #-> sub CPAN::Shell::expand_by_method ; sub expand_by_method { my $self = shift; my($class,$methods,@args) = @_; my($arg,@m); for $arg (@args) { my($regex,$command); if ($arg =~ m|^/(.*)/$|) { $regex = $1; # FIXME: there seem to be some ='s in the author data, which trigger # a failure here. This needs to be contemplated. # } elsif ($arg =~ m/=/) { # $command = 1; } my $obj; CPAN->debug(sprintf "class[%s]regex[%s]command[%s]", $class, defined $regex ? $regex : "UNDEFINED", defined $command ? $command : "UNDEFINED", ) if $CPAN::DEBUG; if (defined $regex) { if (CPAN::_sqlite_running()) { CPAN::Index->reload; $CPAN::SQLite->search($class, $regex); } for $obj ( $CPAN::META->all_objects($class) ) { unless ($obj && UNIVERSAL::can($obj,"id") && $obj->id) { # BUG, we got an empty object somewhere require Data::Dumper; CPAN->debug(sprintf( "Bug in CPAN: Empty id on obj[%s][%s]", $obj, Data::Dumper::Dumper($obj) )) if $CPAN::DEBUG; next; } for my $method (@$methods) { my $match = eval {$obj->$method() =~ /$regex/i}; if ($@) { my($err) = $@ =~ /^(.+) at .+? line \d+\.$/; $err ||= $@; # if we were too restrictive above $CPAN::Frontend->mydie("$err\n"); } elsif ($match) { push @m, $obj; last; } } } } elsif ($command) { die "equal sign in command disabled (immature interface), ". "you can set ! \$CPAN::Shell::ADVANCED_QUERY=1 to enable it. But please note, this is HIGHLY EXPERIMENTAL code that may go away anytime.\n" unless $ADVANCED_QUERY; my($method,$criterion) = $arg =~ /(.+?)=(.+)/; my($matchcrit) = $criterion =~ m/^~(.+)/; for my $self ( sort {$a->id cmp $b->id} $CPAN::META->all_objects($class) ) { my $lhs = $self->$method() or next; # () for 5.00503 if ($matchcrit) { push @m, $self if $lhs =~ m/$matchcrit/; } else { push @m, $self if $lhs eq $criterion; } } } else { my($xarg) = $arg; if ( $class eq 'CPAN::Bundle' ) { $xarg =~ s/^(Bundle::)?(.*)/Bundle::$2/; } elsif ($class eq "CPAN::Distribution") { $xarg = CPAN::Distribution->normalize($arg); } else { $xarg =~ s/:+/::/g; } if ($CPAN::META->exists($class,$xarg)) { $obj = $CPAN::META->instance($class,$xarg); } elsif ($CPAN::META->exists($class,$arg)) { $obj = $CPAN::META->instance($class,$arg); } else { next; } push @m, $obj; } } @m = sort {$a->id cmp $b->id} @m; if ( $CPAN::DEBUG ) { my $wantarray = wantarray; my $join_m = join ",", map {$_->id} @m; # $self->debug("wantarray[$wantarray]join_m[$join_m]"); my $count = scalar @m; $self->debug("class[$class]wantarray[$wantarray]count m[$count]"); } return wantarray ? @m : $m[0]; } #-> sub CPAN::Shell::format_result ; sub format_result { my($self) = shift; my($type,@args) = @_; @args = '/./' unless @args; my(@result) = $self->expand($type,@args); my $result = @result == 1 ? $result[0]->as_string : @result == 0 ? "No objects of type $type found for argument @args\n" : join("", (map {$_->as_glimpse} @result), scalar @result, " items found\n", ); $result; } #-> sub CPAN::Shell::report_fh ; { my $installation_report_fh; my $previously_noticed = 0; sub report_fh { return $installation_report_fh if $installation_report_fh; if ($CPAN::META->has_usable("File::Temp")) { $installation_report_fh = File::Temp->new( dir => File::Spec->tmpdir, template => 'cpan_install_XXXX', suffix => '.txt', unlink => 0, ); } unless ( $installation_report_fh ) { warn("Couldn't open installation report file; " . "no report file will be generated." ) unless $previously_noticed++; } } } # The only reason for this method is currently to have a reliable # debugging utility that reveals which output is going through which # channel. No, I don't like the colors ;-) # to turn colordebugging on, write # cpan> o conf colorize_output 1 #-> sub CPAN::Shell::colorize_output ; { my $print_ornamented_have_warned = 0; sub colorize_output { my $colorize_output = $CPAN::Config->{colorize_output}; if ($colorize_output && $^O eq 'MSWin32' && !$CPAN::META->has_inst("Win32::Console::ANSI")) { unless ($print_ornamented_have_warned++) { # no myprint/mywarn within myprint/mywarn! warn "Colorize_output is set to true but Win32::Console::ANSI is not installed. To activate colorized output, please install Win32::Console::ANSI.\n\n"; } $colorize_output = 0; } if ($colorize_output && !$CPAN::META->has_inst("Term::ANSIColor")) { unless ($print_ornamented_have_warned++) { # no myprint/mywarn within myprint/mywarn! warn "Colorize_output is set to true but Term::ANSIColor is not installed. To activate colorized output, please install Term::ANSIColor.\n\n"; } $colorize_output = 0; } return $colorize_output; } } #-> sub CPAN::Shell::print_ornamented ; sub print_ornamented { my($self,$what,$ornament) = @_; return unless defined $what; local $| = 1; # Flush immediately if ( $CPAN::Be_Silent ) { # WARNING: variable Be_Silent is poisoned and must be eliminated. print {report_fh()} $what; return; } my $swhat = "$what"; # stringify if it is an object if ($CPAN::Config->{term_is_latin}) { # note: deprecated, need to switch to $LANG and $LC_* # courtesy jhi: $swhat =~ s{([\xC0-\xDF])([\x80-\xBF])}{chr(ord($1)<<6&0xC0|ord($2)&0x3F)}eg; #}; } if ($self->colorize_output) { if ( $CPAN::DEBUG && $swhat =~ /^Debug\(/ ) { # if you want to have this configurable, please file a bug report $ornament = $CPAN::Config->{colorize_debug} || "black on_cyan"; } my $color_on = eval { Term::ANSIColor::color($ornament) } || ""; if ($@) { print "Term::ANSIColor rejects color[$ornament]: $@\n Please choose a different color (Hint: try 'o conf init /color/')\n"; } # GGOLDBACH/Test-GreaterVersion-0.008 broke without this # $trailer construct. We want the newline be the last thing if # there is a newline at the end ensuring that the next line is # empty for other players my $trailer = ""; $trailer = $1 if $swhat =~ s/([\r\n]+)\z//; print $color_on, $swhat, Term::ANSIColor::color("reset"), $trailer; } else { print $swhat; } } #-> sub CPAN::Shell::myprint ; # where is myprint/mywarn/Frontend/etc. documented? Where to use what? # I think, we send everything to STDOUT and use print for normal/good # news and warn for news that need more attention. Yes, this is our # working contract for now. sub myprint { my($self,$what) = @_; $self->print_ornamented($what, $CPAN::Config->{colorize_print}||'bold blue on_white', ); } my %already_printed; #-> sub CPAN::Shell::mywarnonce ; sub myprintonce { my($self,$what) = @_; $self->myprint($what) unless $already_printed{$what}++; } sub optprint { my($self,$category,$what) = @_; my $vname = $category . "_verbosity"; CPAN::HandleConfig->load unless $CPAN::Config_loaded++; if (!$CPAN::Config->{$vname} || $CPAN::Config->{$vname} =~ /^v/ ) { $CPAN::Frontend->myprint($what); } } #-> sub CPAN::Shell::myexit ; sub myexit { my($self,$what) = @_; $self->myprint($what); exit; } #-> sub CPAN::Shell::mywarn ; sub mywarn { my($self,$what) = @_; $self->print_ornamented($what, $CPAN::Config->{colorize_warn}||'bold red on_white'); } my %already_warned; #-> sub CPAN::Shell::mywarnonce ; sub mywarnonce { my($self,$what) = @_; $self->mywarn($what) unless $already_warned{$what}++; } # only to be used for shell commands #-> sub CPAN::Shell::mydie ; sub mydie { my($self,$what) = @_; $self->mywarn($what); # If it is the shell, we want the following die to be silent, # but if it is not the shell, we would need a 'die $what'. We need # to take care that only shell commands use mydie. Is this # possible? die "\n"; } # sub CPAN::Shell::colorable_makemaker_prompt ; sub colorable_makemaker_prompt { my($foo,$bar,$ornament) = @_; $ornament ||= "colorize_print"; if (CPAN::Shell->colorize_output) { my $ornament = $CPAN::Config->{$ornament}||'bold blue on_white'; my $color_on = eval { Term::ANSIColor::color($ornament); } || ""; print $color_on; } my $ans = ExtUtils::MakeMaker::prompt($foo,$bar); if (CPAN::Shell->colorize_output) { print Term::ANSIColor::color('reset'); } return $ans; } # use this only for unrecoverable errors! #-> sub CPAN::Shell::unrecoverable_error ; sub unrecoverable_error { my($self,$what) = @_; my @lines = split /\n/, $what; my $longest = 0; for my $l (@lines) { $longest = length $l if length $l > $longest; } $longest = 62 if $longest > 62; for my $l (@lines) { if ($l =~ /^\s*$/) { $l = "\n"; next; } $l = "==> $l"; if (length $l < 66) { $l = pack "A66 A*", $l, "<=="; } $l .= "\n"; } unshift @lines, "\n"; $self->mydie(join "", @lines); } #-> sub CPAN::Shell::mysleep ; sub mysleep { return if $ENV{AUTOMATED_TESTING} || ! -t STDOUT; my($self, $sleep) = @_; if (CPAN->has_inst("Time::HiRes")) { Time::HiRes::sleep($sleep); } else { sleep($sleep < 1 ? 1 : int($sleep + 0.5)); } } #-> sub CPAN::Shell::setup_output ; sub setup_output { return if -t STDOUT; my $odef = select STDERR; $| = 1; select STDOUT; $| = 1; select $odef; } #-> sub CPAN::Shell::rematein ; # RE-adme||MA-ke||TE-st||IN-stall : nearly everything runs through here sub rematein { my $self = shift; # this variable was global and disturbed programmers, so localize: local $CPAN::Distrostatus::something_has_failed_at; my($meth,@some) = @_; my @pragma; while($meth =~ /^(ff?orce|notest)$/) { push @pragma, $meth; $meth = shift @some or $CPAN::Frontend->mydie("Pragma $pragma[-1] used without method: ". "cannot continue"); } setup_output(); CPAN->debug("pragma[@pragma]meth[$meth]some[@some]") if $CPAN::DEBUG; # Here is the place to set "test_count" on all involved parties to # 0. We then can pass this counter on to the involved # distributions and those can refuse to test if test_count > X. In # the first stab at it we could use a 1 for "X". # But when do I reset the distributions to start with 0 again? # Jost suggested to have a random or cycling interaction ID that # we pass through. But the ID is something that is just left lying # around in addition to the counter, so I'd prefer to set the # counter to 0 now, and repeat at the end of the loop. But what # about dependencies? They appear later and are not reset, they # enter the queue but not its copy. How do they get a sensible # test_count? # With configure_requires, "get" is vulnerable in recursion. my $needs_recursion_protection = "get|make|test|install"; # construct the queue my($s,@s,@qcopy); STHING: foreach $s (@some) { my $obj; if (ref $s) { CPAN->debug("s is an object[$s]") if $CPAN::DEBUG; $obj = $s; } elsif ($s =~ m|[\$\@\%]|) { # looks like a perl variable } elsif ($s =~ m|^/|) { # looks like a regexp if (substr($s,-1,1) eq ".") { $obj = CPAN::Shell->expandany($s); } else { my @obj; CLASS: for my $class (qw(Distribution Bundle Module)) { if (@obj = $self->expand($class,$s)) { last CLASS; } } if (@obj) { if (1==@obj) { $obj = $obj[0]; } else { $CPAN::Frontend->mywarn("Sorry, $meth with a regular expression is ". "only supported when unambiguous.\nRejecting argument '$s'\n"); $CPAN::Frontend->mysleep(2); next STHING; } } } } elsif ($meth eq "ls") { $self->globls($s,\@pragma); next STHING; } else { CPAN->debug("calling expandany [$s]") if $CPAN::DEBUG; $obj = CPAN::Shell->expandany($s); } if (0) { } elsif (ref $obj) { if ($meth =~ /^($needs_recursion_protection)$/) { # it would be silly to check for recursion for look or dump # (we are in CPAN::Shell::rematein) CPAN->debug("Testing against recursion") if $CPAN::DEBUG; eval { $obj->color_cmd_tmps(0,1); }; if ($@) { if (ref $@ and $@->isa("CPAN::Exception::RecursiveDependency")) { $CPAN::Frontend->mywarn($@); } else { if (0) { require Carp; Carp::confess(sprintf "DEBUG: \$\@[%s]ref[%s]", $@, ref $@); } die; } } } CPAN::Queue->queue_item(qmod => $obj->id, reqtype => "c", optional => ''); push @qcopy, $obj; } elsif ($CPAN::META->exists('CPAN::Author',uc($s))) { $obj = $CPAN::META->instance('CPAN::Author',uc($s)); if ($meth =~ /^(dump|ls|reports)$/) { $obj->$meth(); } else { $CPAN::Frontend->mywarn( join "", "Don't be silly, you can't $meth ", $obj->fullname, " ;-)\n" ); $CPAN::Frontend->mysleep(2); } } elsif ($s =~ m|[\$\@\%]| && $meth eq "dump") { CPAN::InfoObj->dump($s); } else { $CPAN::Frontend ->mywarn(qq{Warning: Cannot $meth $s, }. qq{don't know what it is. Try the command i /$s/ to find objects with matching identifiers. }); $CPAN::Frontend->mysleep(2); } } # queuerunner (please be warned: when I started to change the # queue to hold objects instead of names, I made one or two # mistakes and never found which. I reverted back instead) QITEM: while (my $q = CPAN::Queue->first) { my $obj; my $s = $q->as_string; my $reqtype = $q->reqtype || ""; my $optional = $q->optional || ""; $obj = CPAN::Shell->expandany($s); unless ($obj) { # don't know how this can happen, maybe we should panic, # but maybe we get a solution from the first user who hits # this unfortunate exception? $CPAN::Frontend->mywarn("Warning: Could not expand string '$s' ". "to an object. Skipping.\n"); $CPAN::Frontend->mysleep(5); CPAN::Queue->delete_first($s); next QITEM; } $obj->{reqtype} ||= ""; my $type = ref $obj; if ( $type eq 'CPAN::Distribution' || $type eq 'CPAN::Bundle' ) { $obj->{mandatory} ||= ! $optional; # once mandatory, always mandatory } elsif ( $type eq 'CPAN::Module' ) { $obj->{mandatory} ||= ! $optional; # once mandatory, always mandatory if (my $d = $obj->distribution) { $d->{mandatory} ||= ! $optional; # once mandatory, always mandatory } elsif ($optional) { # the queue object does not know who was recommending/suggesting us:( # So we only vaguely write "optional". $CPAN::Frontend->mywarn("Warning: optional module '$s' ". "not known. Skipping.\n"); CPAN::Queue->delete_first($s); next QITEM; } } { # force debugging because CPAN::SQLite somehow delivers us # an empty object; # local $CPAN::DEBUG = 1024; # Shell; probably fixed now CPAN->debug("s[$s]obj-reqtype[$obj->{reqtype}]". "q-reqtype[$reqtype]") if $CPAN::DEBUG; } if ($obj->{reqtype}) { if ($obj->{reqtype} eq "b" && $reqtype =~ /^[rc]$/) { $obj->{reqtype} = $reqtype; if ( exists $obj->{install} && ( UNIVERSAL::can($obj->{install},"failed") ? $obj->{install}->failed : $obj->{install} =~ /^NO/ ) ) { delete $obj->{install}; $CPAN::Frontend->mywarn ("Promoting $obj->{ID} from 'build_requires' to 'requires'"); } } } else { $obj->{reqtype} = $reqtype; } for my $pragma (@pragma) { if ($pragma && $obj->can($pragma)) { $obj->$pragma($meth); } } if (UNIVERSAL::can($obj, 'called_for')) { $obj->called_for($s) unless $obj->called_for; } CPAN->debug(qq{pragma[@pragma]meth[$meth]}. qq{ID[$obj->{ID}]}) if $CPAN::DEBUG; push @qcopy, $obj; if ($meth =~ /^(report)$/) { # they came here with a pragma? $self->$meth($obj); } elsif (! UNIVERSAL::can($obj,$meth)) { # Must never happen my $serialized = ""; if (0) { } elsif ($CPAN::META->has_inst("YAML::Syck")) { $serialized = YAML::Syck::Dump($obj); } elsif ($CPAN::META->has_inst("YAML")) { $serialized = YAML::Dump($obj); } elsif ($CPAN::META->has_inst("Data::Dumper")) { $serialized = Data::Dumper::Dumper($obj); } else { require overload; $serialized = overload::StrVal($obj); } CPAN->debug("Going to panic. meth[$meth]s[$s]") if $CPAN::DEBUG; $CPAN::Frontend->mydie("Panic: obj[$serialized] cannot meth[$meth]"); } else { my $upgraded_meth = $meth; if ( $meth eq "make" and $obj->{reqtype} eq "b" ) { # rt 86915 $upgraded_meth = "test"; } if ($obj->$upgraded_meth()) { CPAN::Queue->delete($s); CPAN->debug("Succeeded and deleted from queue. pragma[@pragma]meth[$meth][s][$s]") if $CPAN::DEBUG; } else { CPAN->debug("Failed. pragma[@pragma]meth[$meth]s[$s]") if $CPAN::DEBUG; } } $obj->undelay; for my $pragma (@pragma) { my $unpragma = "un$pragma"; if ($obj->can($unpragma)) { $obj->$unpragma(); } } # if any failures occurred and the current object is mandatory, we # still don't know if *it* failed or if it was another (optional) # module, so we have to check that explicitly (and expensively) if ( $CPAN::Config->{halt_on_failure} && $obj->{mandatory} && CPAN::Distrostatus::something_has_just_failed() && $self->mandatory_dist_failed() ) { $CPAN::Frontend->mywarn("Stopping: '$meth' failed for '$s'.\n"); CPAN::Queue->nullify_queue; last QITEM; } CPAN::Queue->delete_first($s); } if ($meth =~ /^($needs_recursion_protection)$/) { for my $obj (@qcopy) { $obj->color_cmd_tmps(0,0); } } } #-> sub CPAN::Shell::recent ; sub recent { my($self) = @_; if ($CPAN::META->has_inst("XML::LibXML")) { my $url = $CPAN::Defaultrecent; $CPAN::Frontend->myprint("Fetching '$url'\n"); unless ($CPAN::META->has_usable("LWP")) { $CPAN::Frontend->mydie("LWP not installed; cannot continue"); } CPAN::LWP::UserAgent->config; my $Ua; eval { $Ua = CPAN::LWP::UserAgent->new; }; if ($@) { $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n"); } my $resp = $Ua->get($url); unless ($resp->is_success) { $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code); } $CPAN::Frontend->myprint("DONE\n\n"); my $xml = XML::LibXML->new->parse_string($resp->content); if (0) { my $s = $xml->serialize(2); $s =~ s/\n\s*\n/\n/g; $CPAN::Frontend->myprint($s); return; } my @distros; if ($url =~ /winnipeg/) { my $pubdate = $xml->findvalue("/rss/channel/pubDate"); $CPAN::Frontend->myprint(" pubDate: $pubdate\n\n"); for my $eitem ($xml->findnodes("/rss/channel/item")) { my $distro = $eitem->findvalue("enclosure/\@url"); $distro =~ s|.*?/authors/id/./../||; my $size = $eitem->findvalue("enclosure/\@length"); my $desc = $eitem->findvalue("description"); $desc =~ s/.+? - //; $CPAN::Frontend->myprint("$distro [$size b]\n $desc\n"); push @distros, $distro; } } elsif ($url =~ /search.*uploads.rdf/) { # xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" # xmlns="http://purl.org/rss/1.0/" # xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" # xmlns:dc="http://purl.org/dc/elements/1.1/" # xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" # xmlns:admin="http://webns.net/mvcb/" my $dc_date = $xml->findvalue("//*[local-name(.) = 'RDF']/*[local-name(.) = 'channel']/*[local-name(.) = 'date']"); $CPAN::Frontend->myprint(" dc:date: $dc_date\n\n"); my $finish_eitem = 0; local $SIG{INT} = sub { $finish_eitem = 1 }; EITEM: for my $eitem ($xml->findnodes("//*[local-name(.) = 'RDF']/*[local-name(.) = 'item']")) { my $distro = $eitem->findvalue("\@rdf:about"); $distro =~ s|.*~||; # remove up to the tilde before the name $distro =~ s|/$||; # remove trailing slash $distro =~ s|([^/]+)|\U$1\E|; # upcase the name my $author = uc $1 or die "distro[$distro] without author, cannot continue"; my $desc = $eitem->findvalue("*[local-name(.) = 'description']"); my $i = 0; SUBDIRTEST: while () { last SUBDIRTEST if ++$i >= 6; # half a dozen must do! if (my @ret = $self->globls("$distro*")) { @ret = grep {$_->[2] !~ /meta/} @ret; @ret = grep {length $_->[2]} @ret; if (@ret) { $distro = "$author/$ret[0][2]"; last SUBDIRTEST; } } $distro =~ s|/|/*/|; # allow it to reside in a subdirectory } next EITEM if $distro =~ m|\*|; # did not find the thing $CPAN::Frontend->myprint("____$desc\n"); push @distros, $distro; last EITEM if $finish_eitem; } } return \@distros; } else { # deprecated old version $CPAN::Frontend->mydie("no XML::LibXML installed, cannot continue\n"); } } #-> sub CPAN::Shell::smoke ; sub smoke { my($self) = @_; my $distros = $self->recent; DISTRO: for my $distro (@$distros) { next if $distro =~ m|/Bundle-|; # XXX crude heuristic to skip bundles $CPAN::Frontend->myprint(sprintf "Downloading and testing '$distro'\n"); { my $skip = 0; local $SIG{INT} = sub { $skip = 1 }; for (0..9) { $CPAN::Frontend->myprint(sprintf "\r%2d (Hit ^C to skip)", 10-$_); sleep 1; if ($skip) { $CPAN::Frontend->myprint(" skipped\n"); next DISTRO; } } } $CPAN::Frontend->myprint("\r \n"); # leave the dirty line with a newline $self->test($distro); } } { # set up the dispatching methods no strict "refs"; for my $command (qw( clean cvs_import dump force fforce get install look ls make notest perldoc readme reports test )) { *$command = sub { shift->rematein($command, @_); }; } } 1; perl5/CPAN/Prompt.pm000044400000001067152530123070010133 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Prompt; use overload '""' => "as_string"; use vars qw($prompt); use vars qw( $VERSION ); $VERSION = "5.5"; $prompt = "cpan> "; $CPAN::CurrentCommandId ||= 0; sub new { bless {}, shift; } sub as_string { my $word = "cpan"; unless ($CPAN::META->{LOCK}) { $word = "nolock_cpan"; } if ($CPAN::Config->{commandnumber_in_prompt}) { sprintf "$word\[%d]> ", $CPAN::CurrentCommandId; } else { "$word> "; } } 1; perl5/CPAN/Complete.pm000044400000013607152530123070010425 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Complete; use strict; @CPAN::Complete::ISA = qw(CPAN::Debug); # Q: where is the "How do I add a new command" HOWTO? # A: git log -p -1 355c44e9caaec857e4b12f51afb96498833c3e36 where andk added the report command @CPAN::Complete::COMMANDS = sort qw( ? ! a b d h i m o q r u autobundle bye clean cvs_import dump exit failed force fforce hosts install install_tested is_tested look ls make mkmyconfig notest perldoc quit readme recent recompile reload report reports scripts smoke test upgrade ); use vars qw( $VERSION ); $VERSION = "5.5001"; package CPAN::Complete; use strict; sub gnu_cpl { my($text, $line, $start, $end) = @_; my(@perlret) = cpl($text, $line, $start); # find longest common match. Can anybody show me how to peruse # T::R::Gnu to have this done automatically? Seems expensive. return () unless @perlret; my($newtext) = $text; for (my $i = length($text)+1;;$i++) { last unless length($perlret[0]) && length($perlret[0]) >= $i; my $try = substr($perlret[0],0,$i); my @tries = grep {substr($_,0,$i) eq $try} @perlret; # warn "try[$try]tries[@tries]"; if (@tries == @perlret) { $newtext = $try; } else { last; } } ($newtext,@perlret); } #-> sub CPAN::Complete::cpl ; sub cpl { my($word,$line,$pos) = @_; $word ||= ""; $line ||= ""; $pos ||= 0; CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG; $line =~ s/^\s*//; if ($line =~ s/^((?:notest|f?force)\s*)//) { $pos -= length($1); } my @return; if ($pos == 0 || $line =~ /^(?:h(?:elp)?|\?)\s/) { @return = grep /^\Q$word\E/, @CPAN::Complete::COMMANDS; } elsif ( $line !~ /^[\!abcdghimorutl]/ ) { @return = (); } elsif ($line =~ /^a\s/) { @return = cplx('CPAN::Author',uc($word)); } elsif ($line =~ /^ls\s/) { my($author,$rest) = $word =~ m|([^/]+)/?(.*)|; @return = $rest ? () : map {"$_/"} cplx('CPAN::Author',uc($author||"")); if (0 && 1==@return) { # XXX too slow and even wrong when there is a * already @return = grep /^\Q$word\E/, map {"$author/$_->[2]"} CPAN::Shell->expand("Author",$author)->ls("$rest*","2"); } } elsif ($line =~ /^b\s/) { CPAN::Shell->local_bundles; @return = cplx('CPAN::Bundle',$word); } elsif ($line =~ /^d\s/) { @return = cplx('CPAN::Distribution',$word); } elsif ($line =~ m/^( [mru]|make|clean|dump|get|test|install|readme|look|cvs_import|perldoc|recent )\s/x ) { if ($word =~ /^Bundle::/) { CPAN::Shell->local_bundles; } @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word)); } elsif ($line =~ /^i\s/) { @return = cpl_any($word); } elsif ($line =~ /^reload\s/) { @return = cpl_reload($word,$line,$pos); } elsif ($line =~ /^o\s/) { @return = cpl_option($word,$line,$pos); } elsif ($line =~ m/^\S+\s/ ) { # fallback for future commands and what we have forgotten above @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word)); } else { @return = (); } return @return; } #-> sub CPAN::Complete::cplx ; sub cplx { my($class, $word) = @_; if (CPAN::_sqlite_running()) { $CPAN::SQLite->search($class, "^\Q$word\E"); } my $method = "id"; $method = "pretty_id" if $class eq "CPAN::Distribution"; sort grep /^\Q$word\E/, map { $_->$method() } $CPAN::META->all_objects($class); } #-> sub CPAN::Complete::cpl_any ; sub cpl_any { my($word) = shift; return ( cplx('CPAN::Author',$word), cplx('CPAN::Bundle',$word), cplx('CPAN::Distribution',$word), cplx('CPAN::Module',$word), ); } #-> sub CPAN::Complete::cpl_reload ; sub cpl_reload { my($word,$line,$pos) = @_; $word ||= ""; my(@words) = split " ", $line; CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; my(@ok) = qw(cpan index); return @ok if @words == 1; return grep /^\Q$word\E/, @ok if @words == 2 && $word; } #-> sub CPAN::Complete::cpl_option ; sub cpl_option { my($word,$line,$pos) = @_; $word ||= ""; my(@words) = split " ", $line; CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; my(@ok) = qw(conf debug); return @ok if @words == 1; return grep /^\Q$word\E/, @ok if @words == 2 && length($word); if (0) { } elsif ($words[1] eq 'index') { return (); } elsif ($words[1] eq 'conf') { return CPAN::HandleConfig::cpl(@_); } elsif ($words[1] eq 'debug') { return sort grep /^\Q$word\E/i, sort keys %CPAN::DEBUG, 'all'; } } 1; perl5/CPAN/HandleConfig.pm000044400000057167152530123070011207 0ustar00package CPAN::HandleConfig; use strict; use vars qw(%can %keys $loading $VERSION); use File::Path (); use File::Spec (); use File::Basename (); use Carp (); =head1 NAME CPAN::HandleConfig - internal configuration handling for CPAN.pm =cut $VERSION = "5.5012"; # see also CPAN::Config::VERSION at end of file %can = ( commit => "Commit changes to disk", defaults => "Reload defaults from disk", help => "Short help about 'o conf' usage", init => "Interactive setting of all options", ); # Q: where is the "How do I add a new config option" HOWTO? # A1: svn diff -r 757:758 # where dagolden added test_report [git e997b71de88f1019a1472fc13cb97b1b7f96610f] # A2: svn diff -r 985:986 # where andk added yaml_module [git 312b6d9b12b1bdec0b6e282d853482145475021f] # A3: 1. add new config option to %keys below # 2. add a Pod description in CPAN::FirstTime in the DESCRIPTION # section; it should include a prompt line; see others for # examples # 3. add a "matcher" section in CPAN::FirstTime::init that includes # a prompt function; see others for examples # 4. add config option to documentation section in CPAN.pm %keys = map { $_ => undef } ( "allow_installing_module_downgrades", "allow_installing_outdated_dists", "applypatch", "auto_commit", "build_cache", "build_dir", "build_dir_reuse", "build_requires_install_policy", "bzip2", "cache_metadata", "check_sigs", "cleanup_after_install", "colorize_debug", "colorize_output", "colorize_print", "colorize_warn", "commandnumber_in_prompt", "commands_quote", "connect_to_internet_ok", "cpan_home", "curl", "dontload_hash", # deprecated after 1.83_68 (rev. 581) "dontload_list", "ftp", "ftp_passive", "ftp_proxy", "ftpstats_size", "ftpstats_period", "getcwd", "gpg", "gzip", "halt_on_failure", "histfile", "histsize", "http_proxy", "inactivity_timeout", "index_expire", "inhibit_startup_message", "keep_source_where", "load_module_verbosity", "lynx", "make", "make_arg", "make_install_arg", "make_install_make_command", "makepl_arg", "mbuild_arg", "mbuild_install_arg", "mbuild_install_build_command", "mbuildpl_arg", "ncftp", "ncftpget", "no_proxy", "pager", "password", "patch", "patches_dir", "perl5lib_verbosity", "plugin_list", "prefer_external_tar", "prefer_installer", "prefs_dir", "prerequisites_policy", "proxy_pass", "proxy_user", "pushy_https", "randomize_urllist", "recommends_policy", "scan_cache", "shell", "show_unparsable_versions", "show_upload_date", "show_zero_versions", "suggests_policy", "tar", "tar_verbosity", "term_is_latin", "term_ornaments", "test_report", "trust_test_report_history", "unzip", "urllist", "urllist_ping_verbose", "urllist_ping_external", "use_prompt_default", "use_sqlite", "username", "version_timeout", "wait_list", "wget", "yaml_load_code", "yaml_module", ); my %prefssupport = map { $_ => 1 } ( "allow_installing_module_downgrades", "allow_installing_outdated_dists", "build_requires_install_policy", "check_sigs", "make", "make_install_make_command", "prefer_installer", "test_report", ); # returns true on successful action sub edit { my($self,@args) = @_; return unless @args; CPAN->debug("self[$self]args[".join(" | ",@args)."]"); my($o,$str,$func,$args,$key_exists); $o = shift @args; if($can{$o}) { my $success = $self->$o(args => \@args); # o conf init => sub init => sub load unless ($success) { die "Panic: could not configure CPAN.pm for args [@args]. Giving up."; } } else { CPAN->debug("o[$o]") if $CPAN::DEBUG; unless (exists $keys{$o}) { $CPAN::Frontend->mywarn("Warning: unknown configuration variable '$o'\n"); } my $changed; # one day I used randomize_urllist for a boolean, so we must # list them explicitly --ak if (0) { } elsif ($o =~ /^(wait_list|urllist|dontload_list|plugin_list)$/) { # # ARRAYS # $func = shift @args; $func ||= ""; CPAN->debug("func[$func]args[@args]") if $CPAN::DEBUG; # Let's avoid eval, it's easier to comprehend without. if ($func eq "push") { push @{$CPAN::Config->{$o}}, @args; $changed = 1; } elsif ($func eq "pop") { pop @{$CPAN::Config->{$o}}; $changed = 1; } elsif ($func eq "shift") { shift @{$CPAN::Config->{$o}}; $changed = 1; } elsif ($func eq "unshift") { unshift @{$CPAN::Config->{$o}}, @args; $changed = 1; } elsif ($func eq "splice") { my $offset = shift @args || 0; my $length = shift @args || 0; splice @{$CPAN::Config->{$o}}, $offset, $length, @args; # may warn $changed = 1; } elsif ($func) { $CPAN::Config->{$o} = [$func, @args]; $changed = 1; } else { $self->prettyprint($o); } if ($changed) { if ($o eq "urllist") { # reset the cached values undef $CPAN::FTP::Thesite; undef $CPAN::FTP::Themethod; $CPAN::Index::LAST_TIME = 0; } elsif ($o eq "dontload_list") { # empty it, it will be built up again $CPAN::META->{dontload_hash} = {}; } } } elsif ($o =~ /_hash$/) { # # HASHES # if (@args==1 && $args[0] eq "") { @args = (); } elsif (@args % 2) { push @args, ""; } $CPAN::Config->{$o} = { @args }; $changed = 1; } else { # # SCALARS # if (defined $args[0]) { $CPAN::CONFIG_DIRTY = 1; $CPAN::Config->{$o} = $args[0]; $changed = 1; } $self->prettyprint($o) if exists $keys{$o} or defined $CPAN::Config->{$o}; } if ($changed) { if ($CPAN::Config->{auto_commit}) { $self->commit; } else { $CPAN::CONFIG_DIRTY = 1; $CPAN::Frontend->myprint("Please use 'o conf commit' to ". "make the config permanent!\n\n"); } } } } sub prettyprint { my($self,$k) = @_; my $v = $CPAN::Config->{$k}; if (ref $v) { my(@report); if (ref $v eq "ARRAY") { @report = map {"\t$_ \[$v->[$_]]\n"} 0..$#$v; } else { @report = map { sprintf "\t%-18s => %s\n", "[$_]", defined $v->{$_} ? "[$v->{$_}]" : "undef" } sort keys %$v; } $CPAN::Frontend->myprint( join( "", sprintf( " %-18s\n", $k ), @report ) ); } elsif (defined $v) { $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, $v); } else { $CPAN::Frontend->myprint(sprintf " %-18s undef\n", $k); } } # generally, this should be called without arguments so that the currently # loaded config file is where changes are committed. sub commit { my($self,@args) = @_; CPAN->debug("args[@args]") if $CPAN::DEBUG; if ($CPAN::RUN_DEGRADED) { $CPAN::Frontend->mydie( "'o conf commit' disabled in ". "degraded mode. Maybe try\n". " !undef \$CPAN::RUN_DEGRADED\n" ); } my ($configpm, $must_reload); # XXX does anything do this? can it be simplified? -- dagolden, 2011-01-19 if (@args) { if ($args[0] eq "args") { # we have not signed that contract } else { $configpm = $args[0]; } } # use provided name or the current config or create a new MyConfig $configpm ||= require_myconfig_or_config() || make_new_config(); # commit to MyConfig if we can't write to Config if ( ! -w $configpm && $configpm =~ m{CPAN/Config\.pm} ) { my $myconfig = _new_config_name(); $CPAN::Frontend->mywarn( "Your $configpm file\n". "is not writable. I will attempt to write your configuration to\n" . "$myconfig instead.\n\n" ); $configpm = make_new_config(); $must_reload++; # so it gets loaded as $INC{'CPAN/MyConfig.pm'} } # XXX why not just "-w $configpm"? -- dagolden, 2011-01-19 my($mode); if (-f $configpm) { $mode = (stat $configpm)[2]; if ($mode && ! -w _) { _die_cant_write_config($configpm); } } $self->_write_config_file($configpm); require_myconfig_or_config() if $must_reload; #$mode = 0444 | ( $mode & 0111 ? 0111 : 0 ); #chmod $mode, $configpm; ###why was that so? $self->defaults; $CPAN::Frontend->myprint("commit: wrote '$configpm'\n"); $CPAN::CONFIG_DIRTY = 0; 1; } sub _write_config_file { my ($self, $configpm) = @_; my $msg; $msg = <new; rename $configpm, "$configpm~" if -f $configpm; open $fh, ">$configpm" or $CPAN::Frontend->mydie("Couldn't open >$configpm: $!"); $fh->print(qq[$msg\$CPAN::Config = \{\n]); foreach (sort keys %$CPAN::Config) { unless (exists $keys{$_}) { # do not drop them: forward compatibility! $CPAN::Frontend->mywarn("Unknown config variable '$_'\n"); next; } $fh->print( " '$_' => ", $self->neatvalue($CPAN::Config->{$_}), ",\n" ); } $fh->print("};\n1;\n__END__\n"); close $fh; return; } # stolen from MakeMaker; not taking the original because it is buggy; # bugreport will have to say: keys of hashes remain unquoted and can # produce syntax errors sub neatvalue { my($self, $v) = @_; return "undef" unless defined $v; my($t) = ref $v; unless ($t) { $v =~ s/\\/\\\\/g; return "q[$v]"; } if ($t eq 'ARRAY') { my(@m, @neat); push @m, "["; foreach my $elem (@$v) { push @neat, "q[$elem]"; } push @m, join ", ", @neat; push @m, "]"; return join "", @m; } return "$v" unless $t eq 'HASH'; my @m; foreach my $key (sort keys %$v) { my $val = $v->{$key}; push(@m,"q[$key]=>".$self->neatvalue($val)) ; } return "{ ".join(', ',@m)." }"; } sub defaults { my($self) = @_; if ($CPAN::RUN_DEGRADED) { $CPAN::Frontend->mydie( "'o conf defaults' disabled in ". "degraded mode. Maybe try\n". " !undef \$CPAN::RUN_DEGRADED\n" ); } my $done; for my $config (qw(CPAN/MyConfig.pm CPAN/Config.pm)) { if ($INC{$config}) { CPAN->debug("INC{'$config'}[$INC{$config}]") if $CPAN::DEBUG; CPAN::Shell->_reload_this($config,{reloforce => 1}); $CPAN::Frontend->myprint("'$INC{$config}' reread\n"); last; } } $CPAN::CONFIG_DIRTY = 0; 1; } =head2 C<< CLASS->safe_quote ITEM >> Quotes an item to become safe against spaces in shell interpolation. An item is enclosed in double quotes if: - the item contains spaces in the middle - the item does not start with a quote This happens to avoid shell interpolation problems when whitespace is present in directory names. This method uses C to determine the correct quote. If C is a space, no quoting will take place. if it starts and ends with the same quote character: leave it as it is if it contains no whitespace: leave it as it is if it contains whitespace, then if it contains quotes: better leave it as it is else: quote it with the correct quote type for the box we're on =cut { # Instead of patching the guess, set commands_quote # to the right value my ($quotes,$use_quote) = $^O eq 'MSWin32' ? ('"', '"') : (q{"'}, "'") ; sub safe_quote { my ($self, $command) = @_; # Set up quote/default quote my $quote = $CPAN::Config->{commands_quote} || $quotes; if ($quote ne ' ' and defined($command ) and $command =~ /\s/ and $command !~ /[$quote]/) { return qq<$use_quote$command$use_quote> } return $command; } } sub init { my($self,@args) = @_; CPAN->debug("self[$self]args[".join(",",@args)."]"); $self->load(do_init => 1, @args); 1; } # Loads CPAN::MyConfig or fall-back to CPAN::Config. Will not reload a file # if already loaded. Returns the path to the file %INC or else the empty string # # Note -- if CPAN::Config were loaded and CPAN::MyConfig subsequently # created, calling this again will leave *both* in %INC sub require_myconfig_or_config () { if ( $INC{"CPAN/MyConfig.pm"} || _try_loading("CPAN::MyConfig", cpan_home())) { return $INC{"CPAN/MyConfig.pm"}; } elsif ( $INC{"CPAN/Config.pm"} || _try_loading("CPAN::Config") ) { return $INC{"CPAN/Config.pm"}; } else { return q{}; } } # Load a module, but ignore "can't locate..." errors # Optionally take a list of directories to add to @INC for the load sub _try_loading { my ($module, @dirs) = @_; (my $file = $module) =~ s{::}{/}g; $file .= ".pm"; local @INC = @INC; for my $dir ( @dirs ) { if ( -f File::Spec->catfile($dir, $file) ) { unshift @INC, $dir; last; } } eval { require $file }; my $err_myconfig = $@; if ($err_myconfig and $err_myconfig !~ m#locate \Q$file\E#) { die "Error while requiring ${module}:\n$err_myconfig"; } return $INC{$file}; } # prioritized list of possible places for finding "CPAN/MyConfig.pm" sub cpan_home_dir_candidates { my @dirs; my $old_v = $CPAN::Config->{load_module_verbosity}; $CPAN::Config->{load_module_verbosity} = q[none]; if ($CPAN::META->has_usable('File::HomeDir')) { if ($^O ne 'darwin') { push @dirs, File::HomeDir->my_data; # my_data is ~/Library/Application Support on darwin, # which causes issues in the toolchain. } push @dirs, File::HomeDir->my_home; } # Windows might not have HOME, so check it first push @dirs, $ENV{HOME} if $ENV{HOME}; # Windows might have these instead push( @dirs, File::Spec->catpath($ENV{HOMEDRIVE}, $ENV{HOMEPATH}, '') ) if $ENV{HOMEDRIVE} && $ENV{HOMEPATH}; push @dirs, $ENV{USERPROFILE} if $ENV{USERPROFILE}; $CPAN::Config->{load_module_verbosity} = $old_v; my $dotcpan = $^O eq 'VMS' ? '_cpan' : '.cpan'; @dirs = map { File::Spec->catdir($_, $dotcpan) } grep { defined } @dirs; return wantarray ? @dirs : $dirs[0]; } sub load { my($self, %args) = @_; $CPAN::Be_Silent+=0; # protect against 'used only once' $CPAN::Be_Silent++ if $args{be_silent}; # do not use; planned to be removed in 2011 my $do_init = delete $args{do_init} || 0; my $make_myconfig = delete $args{make_myconfig}; $loading = 0 unless defined $loading; my $configpm = require_myconfig_or_config; my @miss = $self->missing_config_data; CPAN->debug("do_init[$do_init]loading[$loading]miss[@miss]") if $CPAN::DEBUG; return unless $do_init || @miss; if (@miss==1 and $miss[0] eq "pushy_https" && !$do_init) { $CPAN::Frontend->myprint(<<'END'); Starting with version 2.29 of the cpan shell, a new download mechanism is the default which exclusively uses cpan.org as the host to download from. The configuration variable pushy_https can be used to (de)select the new mechanism. Please read more about it and make your choice between the old and the new mechanism by running o conf init pushy_https Once you have done that and stored the config variable this dialog will disappear. END return; } # I'm not how we'd ever wind up in a recursive loop, but I'm leaving # this here for safety's sake -- dagolden, 2011-01-19 return if $loading; local $loading = ($loading||0) + 1; # Warn if we have a config file, but things were found missing if ($configpm && @miss && !$do_init) { if ($make_myconfig || ( ! -w $configpm && $configpm =~ m{CPAN/Config\.pm})) { $configpm = make_new_config(); $CPAN::Frontend->myprint(<> END } else { $CPAN::Frontend->myprint(<> END } } require CPAN::FirstTime; return CPAN::FirstTime::init($configpm || make_new_config(), %args); } # Creates a new, empty config file at the preferred location # Any existing will be renamed with a ".bak" suffix if possible # If the file cannot be created, an exception is thrown sub make_new_config { my $configpm = _new_config_name(); my $configpmdir = File::Basename::dirname( $configpm ); File::Path::mkpath($configpmdir) unless -d $configpmdir; if ( -w $configpmdir ) { #_#_# following code dumped core on me with 5.003_11, a.k. if( -f $configpm ) { my $configpm_bak = "$configpm.bak"; unlink $configpm_bak if -f $configpm_bak; if( rename $configpm, $configpm_bak ) { $CPAN::Frontend->mywarn(<new; if ($fh->open(">$configpm")) { $fh->print("1;\n"); return $configpm; } } _die_cant_write_config($configpm); } sub _die_cant_write_config { my ($configpm) = @_; $CPAN::Frontend->mydie(<<"END"); WARNING: CPAN.pm is unable to write a configuration file. You must be able to create and write to '$configpm'. Aborting configuration. END } # From candidate directories, we would like (in descending preference order): # * the one that contains a MyConfig file # * one that exists (even without MyConfig) # * the first one on the list sub cpan_home { my @dirs = cpan_home_dir_candidates(); for my $d (@dirs) { return $d if -f "$d/CPAN/MyConfig.pm"; } for my $d (@dirs) { return $d if -d $d; } return $dirs[0]; } sub _new_config_name { return File::Spec->catfile(cpan_home(), 'CPAN', 'MyConfig.pm'); } # returns mandatory but missing entries in the Config sub missing_config_data { my(@miss); for ( "auto_commit", "build_cache", "build_dir", "cache_metadata", "cpan_home", "ftp_proxy", #"gzip", "http_proxy", "index_expire", #"inhibit_startup_message", "keep_source_where", #"make", "make_arg", "make_install_arg", "makepl_arg", "mbuild_arg", "mbuild_install_arg", ($^O eq "MSWin32" ? "" : "mbuild_install_build_command"), "mbuildpl_arg", "no_proxy", #"pager", "prerequisites_policy", "pushy_https", "scan_cache", #"tar", #"unzip", "urllist", ) { next unless exists $keys{$_}; push @miss, $_ unless defined $CPAN::Config->{$_}; } return @miss; } sub help { $CPAN::Frontend->myprint(q[ Known options: commit commit session changes to disk defaults reload default config values from disk help this help init enter a dialog to set all or a set of parameters Edit key values as in the following (the "o" is a literal letter o): o conf build_cache 15 o conf build_dir "/foo/bar" o conf urllist shift o conf urllist unshift ftp://ftp.foo.bar/ o conf inhibit_startup_message 1 ]); 1; #don't reprint CPAN::Config } sub cpl { my($word,$line,$pos) = @_; $word ||= ""; CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG; my(@words) = split " ", substr($line,0,$pos+1); if ( defined($words[2]) and $words[2] =~ /list$/ and ( @words == 3 || @words == 4 && length($word) ) ) { return grep /^\Q$word\E/, qw(splice shift unshift pop push); } elsif (defined($words[2]) and $words[2] eq "init" and ( @words == 3 || @words >= 4 && length($word) )) { return sort grep /^\Q$word\E/, keys %keys; } elsif (@words >= 4) { return (); } my %seen; my(@o_conf) = sort grep { !$seen{$_}++ } keys %can, keys %$CPAN::Config, keys %keys; return grep /^\Q$word\E/, @o_conf; } sub prefs_lookup { my($self,$distro,$what) = @_; if ($prefssupport{$what}) { return $CPAN::Config->{$what} unless $distro and $distro->prefs and $distro->prefs->{cpanconfig} and defined $distro->prefs->{cpanconfig}{$what}; return $distro->prefs->{cpanconfig}{$what}; } else { $CPAN::Frontend->mywarn("Warning: $what not yet officially ". "supported for distroprefs, doing a normal lookup\n"); return $CPAN::Config->{$what}; } } { package CPAN::Config; ####::###### #hide from indexer # note: J. Nick Koston wrote me that they are using # CPAN::Config->commit although undocumented. I suggested # CPAN::Shell->o("conf","commit") even when ugly it is at least # documented # that's why I added the CPAN::Config class with autoload and # deprecated warning use strict; use vars qw($AUTOLOAD $VERSION); $VERSION = "5.5012"; # formerly CPAN::HandleConfig was known as CPAN::Config sub AUTOLOAD { ## no critic my $class = shift; # e.g. in dh-make-perl: CPAN::Config my($l) = $AUTOLOAD; $CPAN::Frontend->mywarn("Dispatching deprecated method '$l' to CPAN::HandleConfig\n"); $l =~ s/.*:://; CPAN::HandleConfig->$l(@_); } } 1; __END__ =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut # Local Variables: # mode: cperl # cperl-indent-level: 4 # End: # vim: ts=4 sts=4 sw=4: perl5/CPAN/CacheMgr.pm000044400000016760152530123070010331 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::CacheMgr; use strict; use CPAN::InfoObj; @CPAN::CacheMgr::ISA = qw(CPAN::InfoObj CPAN); use Cwd qw(chdir); use File::Find; use vars qw( $VERSION ); $VERSION = "5.5002"; package CPAN::CacheMgr; use strict; #-> sub CPAN::CacheMgr::as_string ; sub as_string { eval { require Data::Dumper }; if ($@) { return shift->SUPER::as_string; } else { return Data::Dumper::Dumper(shift); } } #-> sub CPAN::CacheMgr::cachesize ; sub cachesize { shift->{DU}; } #-> sub CPAN::CacheMgr::tidyup ; sub tidyup { my($self) = @_; return unless $CPAN::META->{LOCK}; return unless -d $self->{ID}; my @toremove = grep { $self->{SIZE}{$_}==0 } @{$self->{FIFO}}; for my $current (0..$#toremove) { my $toremove = $toremove[$current]; $CPAN::Frontend->myprint(sprintf( "DEL(%d/%d): %s \n", $current+1, scalar @toremove, $toremove, ) ); return if $CPAN::Signal; $self->_clean_cache($toremove); return if $CPAN::Signal; } $self->{FIFO} = []; } #-> sub CPAN::CacheMgr::dir ; sub dir { shift->{ID}; } #-> sub CPAN::CacheMgr::entries ; sub entries { my($self,$dir) = @_; return unless defined $dir; $self->debug("reading dir[$dir]") if $CPAN::DEBUG; $dir ||= $self->{ID}; my($cwd) = CPAN::anycwd(); chdir $dir or Carp::croak("Can't chdir to $dir: $!"); my $dh = DirHandle->new(File::Spec->curdir) or Carp::croak("Couldn't opendir $dir: $!"); my(@entries); for ($dh->read) { next if $_ eq "." || $_ eq ".."; if (-f $_) { push @entries, File::Spec->catfile($dir,$_); } elsif (-d _) { push @entries, File::Spec->catdir($dir,$_); } else { $CPAN::Frontend->mywarn("Warning: weird direntry in $dir: $_\n"); } } chdir $cwd or Carp::croak("Can't chdir to $cwd: $!"); sort { -M $a <=> -M $b} @entries; } #-> sub CPAN::CacheMgr::disk_usage ; sub disk_usage { my($self,$dir,$fast) = @_; return if exists $self->{SIZE}{$dir}; return if $CPAN::Signal; my($Du) = 0; if (-e $dir) { if (-d $dir) { unless (-x $dir) { unless (chmod 0755, $dir) { $CPAN::Frontend->mywarn("I have neither the -x permission nor the ". "permission to change the permission; cannot ". "estimate disk usage of '$dir'\n"); $CPAN::Frontend->mysleep(5); return; } } } elsif (-f $dir) { # nothing to say, no matter what the permissions } } else { $CPAN::Frontend->mywarn("File or directory '$dir' has gone, ignoring\n"); return; } if ($fast) { $Du = 0; # placeholder } else { find( sub { $File::Find::prune++ if $CPAN::Signal; return if -l $_; if ($^O eq 'MacOS') { require Mac::Files; my $cat = Mac::Files::FSpGetCatInfo($_); $Du += $cat->ioFlLgLen() + $cat->ioFlRLgLen() if $cat; } else { if (-d _) { unless (-x _) { unless (chmod 0755, $_) { $CPAN::Frontend->mywarn("I have neither the -x permission nor ". "the permission to change the permission; ". "can only partially estimate disk usage ". "of '$_'\n"); $CPAN::Frontend->mysleep(5); return; } } } else { $Du += (-s _); } } }, $dir ); } return if $CPAN::Signal; $self->{SIZE}{$dir} = $Du/1024/1024; unshift @{$self->{FIFO}}, $dir; $self->debug("measured $dir is $Du") if $CPAN::DEBUG; $self->{DU} += $Du/1024/1024; $self->{DU}; } #-> sub CPAN::CacheMgr::_clean_cache ; sub _clean_cache { my($self,$dir) = @_; return unless -e $dir; unless (File::Spec->canonpath(File::Basename::dirname($dir)) eq File::Spec->canonpath($CPAN::Config->{build_dir})) { $CPAN::Frontend->mywarn("Directory '$dir' not below $CPAN::Config->{build_dir}, ". "will not remove\n"); $CPAN::Frontend->mysleep(5); return; } $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}") if $CPAN::DEBUG; File::Path::rmtree($dir); my $id_deleted = 0; if ($dir !~ /\.yml$/ && -f "$dir.yml") { my $yaml_module = CPAN::_yaml_module(); if ($CPAN::META->has_inst($yaml_module)) { my($peek_yaml) = eval { CPAN->_yaml_loadfile("$dir.yml"); }; if ($@) { $CPAN::Frontend->mywarn("(parse error on '$dir.yml' removing anyway)"); unlink "$dir.yml" or $CPAN::Frontend->mywarn("(Could not unlink '$dir.yml': $!)"); return; } elsif (my $id = $peek_yaml->[0]{distribution}{ID}) { $CPAN::META->delete("CPAN::Distribution", $id); # XXX we should restore the state NOW, otherwise this # distro does not exist until we read an index. BUG ALERT(?) # $CPAN::Frontend->mywarn (" +++\n"); $id_deleted++; } } unlink "$dir.yml"; # may fail unless ($id_deleted) { CPAN->debug("no distro found associated with '$dir'"); } } $self->{DU} -= $self->{SIZE}{$dir}; delete $self->{SIZE}{$dir}; } #-> sub CPAN::CacheMgr::new ; sub new { my($class,$phase) = @_; $phase ||= "atstart"; my $time = time; my($debug,$t2); $debug = ""; my $self = { ID => $CPAN::Config->{build_dir}, MAX => $CPAN::Config->{'build_cache'}, SCAN => $CPAN::Config->{'scan_cache'} || 'atstart', DU => 0 }; $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}") unless $self->{SCAN} =~ /never|atstart|atexit/; File::Path::mkpath($self->{ID}); my $dh = DirHandle->new($self->{ID}); bless $self, $class; $self->scan_cache($phase); $t2 = time; $debug .= "timing of CacheMgr->new: ".($t2 - $time); $time = $t2; CPAN->debug($debug) if $CPAN::DEBUG; $self; } #-> sub CPAN::CacheMgr::scan_cache ; sub scan_cache { my ($self, $phase) = @_; $phase = '' unless defined $phase; return unless $phase eq $self->{SCAN}; return unless $CPAN::META->{LOCK}; $CPAN::Frontend->myprint( sprintf("Scanning cache %s for sizes\n", $self->{ID})); my $e; my @entries = $self->entries($self->{ID}); my $i = 0; my $painted = 0; for $e (@entries) { my $symbol = "."; if ($self->{DU} > $self->{MAX}) { $symbol = "-"; $self->disk_usage($e,1); } else { $self->disk_usage($e); } $i++; while (($painted/76) < ($i/@entries)) { $CPAN::Frontend->myprint($symbol); $painted++; } return if $CPAN::Signal; } $CPAN::Frontend->myprint("DONE\n"); $self->tidyup; } 1; perl5/CPAN/Distroprefs.pm000044400000027326152530123070011164 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: use 5.006; use strict; package CPAN::Distroprefs; use vars qw($VERSION); $VERSION = '6.0001'; package CPAN::Distroprefs::Result; use File::Spec; sub new { bless $_[1] || {} => $_[0] } sub abs { File::Spec->catfile($_[0]->dir, $_[0]->file) } sub __cloner { my ($class, $name, $newclass) = @_; $newclass = 'CPAN::Distroprefs::Result::' . $newclass; no strict 'refs'; *{$class . '::' . $name} = sub { $newclass->new({ %{ $_[0] }, %{ $_[1] }, }); }; } BEGIN { __PACKAGE__->__cloner(as_warning => 'Warning') } BEGIN { __PACKAGE__->__cloner(as_fatal => 'Fatal') } BEGIN { __PACKAGE__->__cloner(as_success => 'Success') } sub __accessor { my ($class, $key) = @_; no strict 'refs'; *{$class . '::' . $key} = sub { $_[0]->{$key} }; } BEGIN { __PACKAGE__->__accessor($_) for qw(type file ext dir) } sub is_warning { 0 } sub is_fatal { 0 } sub is_success { 0 } package CPAN::Distroprefs::Result::Error; use vars qw(@ISA); BEGIN { @ISA = 'CPAN::Distroprefs::Result' } ## no critic BEGIN { __PACKAGE__->__accessor($_) for qw(msg) } sub as_string { my ($self) = @_; if ($self->msg) { return sprintf $self->fmt_reason, $self->file, $self->msg; } else { return sprintf $self->fmt_unknown, $self->file; } } package CPAN::Distroprefs::Result::Warning; use vars qw(@ISA); BEGIN { @ISA = 'CPAN::Distroprefs::Result::Error' } ## no critic sub is_warning { 1 } sub fmt_reason { "Error reading distroprefs file %s, skipping: %s" } sub fmt_unknown { "Unknown error reading distroprefs file %s, skipping." } package CPAN::Distroprefs::Result::Fatal; use vars qw(@ISA); BEGIN { @ISA = 'CPAN::Distroprefs::Result::Error' } ## no critic sub is_fatal { 1 } sub fmt_reason { "Error reading distroprefs file %s: %s" } sub fmt_unknown { "Unknown error reading distroprefs file %s." } package CPAN::Distroprefs::Result::Success; use vars qw(@ISA); BEGIN { @ISA = 'CPAN::Distroprefs::Result' } ## no critic BEGIN { __PACKAGE__->__accessor($_) for qw(prefs extension) } sub is_success { 1 } package CPAN::Distroprefs::Iterator; sub new { bless $_[1] => $_[0] } sub next { $_[0]->() } package CPAN::Distroprefs; use Carp (); use DirHandle; sub _load_method { my ($self, $loader, $result) = @_; return '_load_yaml' if $loader eq 'CPAN' or $loader =~ /^YAML(::|$)/; return '_load_' . $result->ext; } sub _load_yaml { my ($self, $loader, $result) = @_; my $data = eval { $loader eq 'CPAN' ? $loader->_yaml_loadfile($result->abs) : [ $loader->can('LoadFile')->($result->abs) ] }; if (my $err = $@) { die $result->as_warning({ msg => $err, }); } elsif (!$data) { die $result->as_warning; } else { return @$data; } } sub _load_dd { my ($self, $loader, $result) = @_; my @data; { package CPAN::Eval; # this caused a die in CPAN.pm, and I am leaving it 'fatal', though I'm # not sure why we wouldn't just skip the file as we do for all other # errors. -- hdp my $abs = $result->abs; open FH, "<$abs" or die $result->as_fatal(msg => "$!"); local $/; my $eval = ; close FH; no strict; eval $eval; if (my $err = $@) { die $result->as_warning({ msg => $err }); } my $i = 1; while (${"VAR$i"}) { push @data, ${"VAR$i"}; $i++; } } return @data; } sub _load_st { my ($self, $loader, $result) = @_; # eval because Storable is never forward compatible my @data = eval { @{scalar $loader->can('retrieve')->($result->abs) } }; if (my $err = $@) { die $result->as_warning({ msg => $err }); } return @data; } sub _build_file_list { if (@_ > 3) { die "_build_file_list should be called with 3 arguments, was called with more. First argument is '$_[0]'."; } my ($dir, $dir1, $ext_re) = @_; my @list; my $dh; unless (opendir($dh, $dir)) { $CPAN::Frontend->mywarn("ignoring prefs directory '$dir': $!"); return @list; } while (my $fn = readdir $dh) { next if $fn eq '.' || $fn eq '..'; if (-d "$dir/$fn") { next if $fn =~ /^[._]/; # prune .svn, .git, .hg, _darcs and what the user wants to hide push @list, _build_file_list("$dir/$fn", "$dir1$fn/", $ext_re); } else { if ($fn =~ $ext_re) { push @list, "$dir1$fn"; } } } return @list; } sub find { my ($self, $dir, $ext_map) = @_; return CPAN::Distroprefs::Iterator->new(sub { return }) unless %$ext_map; my $possible_ext = join "|", map { quotemeta } keys %$ext_map; my $ext_re = qr/\.($possible_ext)$/; my @files = _build_file_list($dir, '', $ext_re); @files = sort @files if @files; # label the block so that we can use redo in the middle return CPAN::Distroprefs::Iterator->new(sub { LOOP: { my $fn = shift @files; return unless defined $fn; my ($ext) = $fn =~ $ext_re; my $loader = $ext_map->{$ext}; my $result = CPAN::Distroprefs::Result->new({ file => $fn, ext => $ext, dir => $dir }); # copied from CPAN.pm; is this ever actually possible? redo unless -f $result->abs; my $load_method = $self->_load_method($loader, $result); my @prefs = eval { $self->$load_method($loader, $result) }; if (my $err = $@) { if (ref($err) && eval { $err->isa('CPAN::Distroprefs::Result') }) { return $err; } # rethrow any exceptions that we did not generate die $err; } elsif (!@prefs) { # the loader should have handled this, but just in case: return $result->as_warning; } return $result->as_success({ prefs => [ map { CPAN::Distroprefs::Pref->new({ data => $_ }) } @prefs ], }); } }); } package CPAN::Distroprefs::Pref; use Carp (); sub new { bless $_[1] => $_[0] } sub data { shift->{data} } sub has_any_match { $_[0]->data->{match} ? 1 : 0 } sub has_match { my $match = $_[0]->data->{match} || return 0; exists $match->{$_[1]} || exists $match->{"not_$_[1]"} } sub has_valid_subkeys { grep { exists $_[0]->data->{match}{$_} } map { $_, "not_$_" } $_[0]->match_attributes } sub _pattern { my $re = shift; my $p = eval sprintf 'qr{%s}', $re; if ($@) { $@ =~ s/\n$//; die "Error in Distroprefs pattern qr{$re}\n$@"; } return $p; } sub _match_scalar { my ($match, $data) = @_; my $qr = _pattern($match); return $data =~ /$qr/; } sub _match_hash { my ($match, $data) = @_; for my $mkey (keys %$match) { (my $dkey = $mkey) =~ s/^not_//; my $val = defined $data->{$dkey} ? $data->{$dkey} : ''; if (_match_scalar($match->{$mkey}, $val)) { return 0 if $mkey =~ /^not_/; } else { return 0 if $mkey !~ /^not_/; } } return 1; } sub _match { my ($self, $key, $data, $matcher) = @_; my $m = $self->data->{match}; if (exists $m->{$key}) { return 0 unless $matcher->($m->{$key}, $data); } if (exists $m->{"not_$key"}) { return 0 if $matcher->($m->{"not_$key"}, $data); } return 1; } sub _scalar_match { my ($self, $key, $data) = @_; return $self->_match($key, $data, \&_match_scalar); } sub _hash_match { my ($self, $key, $data) = @_; return $self->_match($key, $data, \&_match_hash); } # do not take the order of C because "module" is by far the # slowest sub match_attributes { qw(env distribution perl perlconfig module) } sub match_module { my ($self, $modules) = @_; return $self->_match("module", $modules, sub { my($match, $data) = @_; my $qr = _pattern($match); for my $module (@$data) { return 1 if $module =~ /$qr/; } return 0; }); } sub match_distribution { shift->_scalar_match(distribution => @_) } sub match_perl { shift->_scalar_match(perl => @_) } sub match_perlconfig { shift->_hash_match(perlconfig => @_) } sub match_env { shift->_hash_match(env => @_) } sub matches { my ($self, $arg) = @_; my $default_match = 0; for my $key (grep { $self->has_match($_) } $self->match_attributes) { unless (exists $arg->{$key}) { Carp::croak "Can't match pref: missing argument key $key"; } $default_match = 1; my $val = $arg->{$key}; # make it possible to avoid computing things until we have to if (ref($val) eq 'CODE') { $val = $val->() } my $meth = "match_$key"; return 0 unless $self->$meth($val); } return $default_match; } 1; __END__ =head1 NAME CPAN::Distroprefs -- read and match distroprefs =head1 SYNOPSIS use CPAN::Distroprefs; my %info = (... distribution/environment info ...); my $finder = CPAN::Distroprefs->find($prefs_dir, \%ext_map); while (my $result = $finder->next) { die $result->as_string if $result->is_fatal; warn($result->as_string), next if $result->is_warning; for my $pref (@{ $result->prefs }) { if ($pref->matches(\%info)) { return $pref; } } } =head1 DESCRIPTION This module encapsulates reading L and matching them against CPAN distributions. =head1 INTERFACE my $finder = CPAN::Distroprefs->find($dir, \%ext_map); while (my $result = $finder->next) { ... } Build an iterator which finds distroprefs files in the tree below the given directory. Within the tree directories matching C are pruned. C<%ext_map> is a hashref whose keys are file extensions and whose values are modules used to load matching files: { 'yml' => 'YAML::Syck', 'dd' => 'Data::Dumper', ... } Each time C<< $finder->next >> is called, the iterator returns one of two possible values: =over =item * a CPAN::Distroprefs::Result object =item * C, indicating that no prefs files remain to be found =back =head1 RESULTS L|/INTERFACE> returns CPAN::Distroprefs::Result objects to indicate success or failure when reading a prefs file. =head2 Common All results share some common attributes: =head3 type C, C, or C =head3 file the file from which these prefs were read, or to which this error refers (relative filename) =head3 ext the file's extension, which determines how to load it =head3 dir the directory the file was read from =head3 abs the absolute path to the file =head2 Errors Error results (warning and fatal) contain: =head3 msg the error message (usually either C<$!> or a YAML error) =head2 Successes Success results contain: =head3 prefs an arrayref of CPAN::Distroprefs::Pref objects =head1 PREFS CPAN::Distroprefs::Pref objects represent individual distroprefs documents. They are constructed automatically as part of C results from C. =head3 data the pref information as a hashref, suitable for e.g. passing to Kwalify =head3 match_attributes returns a list of the valid match attributes (see the Distroprefs section in L) currently: C =head3 has_any_match true if this pref has a 'match' attribute at all =head3 has_valid_subkeys true if this pref has a 'match' attribute and at least one valid match attribute =head3 matches if ($pref->matches(\%arg)) { ... } true if this pref matches the passed-in hashref, which must have a value for each of the C (above) =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/CPAN/DeferredCode.pm000044400000000275152530123070011165 0ustar00package CPAN::DeferredCode; use strict; use vars qw/$VERSION/; use overload fallback => 1, map { ($_ => 'run') } qw/ bool "" 0+ /; $VERSION = "5.50"; sub run { $_[0]->(); } 1; perl5/CPAN/Author.pm000044400000015272152530123070010117 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Author; use strict; use CPAN::InfoObj; @CPAN::Author::ISA = qw(CPAN::InfoObj); use vars qw( $VERSION ); $VERSION = "5.5002"; package CPAN::Author; use strict; #-> sub CPAN::Author::force sub force { my $self = shift; $self->{force}++; } #-> sub CPAN::Author::force sub unforce { my $self = shift; delete $self->{force}; } #-> sub CPAN::Author::id sub id { my $self = shift; my $id = $self->{ID}; $CPAN::Frontend->mydie("Illegal author id[$id]") unless $id =~ /^[A-Z]/; $id; } #-> sub CPAN::Author::as_glimpse ; sub as_glimpse { my($self) = @_; my(@m); my $class = ref($self); $class =~ s/^CPAN:://; push @m, sprintf(qq{%-15s %s ("%s" <%s>)\n}, $class, $self->{ID}, $self->fullname, $self->email); join "", @m; } #-> sub CPAN::Author::fullname ; sub fullname { shift->ro->{FULLNAME}; } *name = \&fullname; #-> sub CPAN::Author::email ; sub email { shift->ro->{EMAIL}; } #-> sub CPAN::Author::ls ; sub ls { my $self = shift; my $glob = shift || ""; my $silent = shift || 0; my $id = $self->id; # adapted from CPAN::Distribution::verifyCHECKSUM ; my(@csf); # chksumfile @csf = $self->id =~ /(.)(.)(.*)/; $csf[1] = join "", @csf[0,1]; $csf[2] = join "", @csf[1,2]; # ("A","AN","ANDK") my(@dl); @dl = $self->dir_listing([$csf[0],"CHECKSUMS"], 0, 1); unless (grep {$_->[2] eq $csf[1]} @dl) { $CPAN::Frontend->myprint("Directory $csf[1]/ does not exist\n") unless $silent ; return; } @dl = $self->dir_listing([@csf[0,1],"CHECKSUMS"], 0, 1); unless (grep {$_->[2] eq $csf[2]} @dl) { $CPAN::Frontend->myprint("Directory $id/ does not exist\n") unless $silent; return; } @dl = $self->dir_listing([@csf,"CHECKSUMS"], 1, 1); if ($glob) { if ($CPAN::META->has_inst("Text::Glob")) { $glob =~ s|/$|/*|; my $rglob = Text::Glob::glob_to_regex($glob); CPAN->debug("glob[$glob]rglob[$rglob]dl[@dl]") if $CPAN::DEBUG; my @tmpdl = grep { $_->[2] =~ /$rglob/ } @dl; if (1==@tmpdl && $tmpdl[0][0]==0) { $rglob = Text::Glob::glob_to_regex("$glob/*"); @dl = grep { $_->[2] =~ /$rglob/ } @dl; } else { @dl = @tmpdl; } CPAN->debug("rglob[$rglob]dl[@dl]") if $CPAN::DEBUG; } else { $CPAN::Frontend->mydie("Text::Glob not installed, cannot proceed"); } } unless ($silent >= 2) { $CPAN::Frontend->myprint ( join "", map { sprintf ( "%8d %10s %s/%s%s\n", $_->[0], $_->[1], $id, $_->[2], 0==$_->[0]?"/":"", ) } sort { $a->[2] cmp $b->[2] } @dl ); } @dl; } # returns an array of arrays, the latter contain (size,mtime,filename) #-> sub CPAN::Author::dir_listing ; sub dir_listing { my $self = shift; my $chksumfile = shift; my $recursive = shift; my $may_ftp = shift; my $lc_want = File::Spec->catfile($CPAN::Config->{keep_source_where}, "authors", "id", @$chksumfile); my $fh; CPAN->debug("chksumfile[@$chksumfile]recursive[$recursive]may_ftp[$may_ftp]") if $CPAN::DEBUG; # Purge and refetch old (pre-PGP) CHECKSUMS; they are a security # hazard. (Without GPG installed they are not that much better, # though.) $fh = FileHandle->new; if (open($fh, $lc_want)) { my $line = <$fh>; close $fh; unlink($lc_want) unless $line =~ /PGP/; } local($") = "/"; # connect "force" argument with "index_expire". my $force = $self->{force}; if (my @stat = stat $lc_want) { $force ||= $stat[9] + $CPAN::Config->{index_expire}*86400 <= time; } my $lc_file; if ($may_ftp) { $lc_file = eval { CPAN::FTP->localize ( "authors/id/@$chksumfile", $lc_want, $force, ); }; unless ($lc_file) { $CPAN::Frontend->myprint("Trying $lc_want.gz\n"); $chksumfile->[-1] .= ".gz"; $lc_file = eval { CPAN::FTP->localize ("authors/id/@$chksumfile", "$lc_want.gz", 1, ); }; if ($lc_file) { $lc_file =~ s{\.gz(?!\n)\Z}{}; #}; eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)}; } else { return; } } } else { $lc_file = $lc_want; # we *could* second-guess and if the user has a file: URL, # then we could look there. But on the other hand, if they do # have a file: URL, why did they choose to set # $CPAN::Config->{show_upload_date} to false? } # adapted from CPAN::Distribution::CHECKSUM_check_file ; $fh = FileHandle->new; my($cksum); if (open $fh, $lc_file) { local($/); my $eval = <$fh>; $eval =~ s/\015?\012/\n/g; close $fh; my($compmt) = Safe->new(); $cksum = $compmt->reval($eval); if ($@) { rename $lc_file, "$lc_file.bad"; Carp::confess($@) if $@; } } elsif ($may_ftp) { Carp::carp ("Could not open '$lc_file' for reading."); } else { # Maybe should warn: "You may want to set show_upload_date to a true value" return; } my(@result,$f); for $f (sort keys %$cksum) { if (exists $cksum->{$f}{isdir}) { if ($recursive) { my(@dir) = @$chksumfile; pop @dir; push @dir, $f, "CHECKSUMS"; push @result, [ 0, "-", $f ]; push @result, map { [$_->[0], $_->[1], "$f/$_->[2]"] } $self->dir_listing(\@dir,1,$may_ftp); } else { push @result, [ 0, "-", $f ]; } } else { push @result, [ ($cksum->{$f}{"size"}||0), $cksum->{$f}{"mtime"}||"---", $f ]; } } @result; } #-> sub CPAN::Author::reports sub reports { $CPAN::Frontend->mywarn("reports on authors not implemented. Please file a bugreport if you need this.\n"); } 1; perl5/CPAN/Tarzip.pm000044400000040400152530123070010115 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- package CPAN::Tarzip; use strict; use vars qw($VERSION @ISA $BUGHUNTING); use CPAN::Debug; use File::Basename qw(basename); $VERSION = "5.5013"; # module is internal to CPAN.pm @ISA = qw(CPAN::Debug); ## no critic $BUGHUNTING ||= 0; # released code must have turned off # it's ok if file doesn't exist, it just matters if it is .gz or .bz2 sub new { my($class,$file) = @_; $CPAN::Frontend->mydie("CPAN::Tarzip->new called without arg") unless defined $file; my $me = { FILE => $file }; if ($file =~ /\.(bz2|gz|zip|tbz|tgz)$/i) { $me->{ISCOMPRESSED} = 1; } else { $me->{ISCOMPRESSED} = 0; } if (0) { } elsif ($file =~ /\.(?:bz2|tbz)$/i) { unless ($me->{UNGZIPPRG} = $CPAN::Config->{bzip2}) { my $bzip2 = _my_which("bzip2"); if ($bzip2) { $me->{UNGZIPPRG} = $bzip2; } else { $CPAN::Frontend->mydie(qq{ CPAN.pm needs the external program bzip2 in order to handle '$file'. Please install it now and run 'o conf init bzip2' from the CPAN shell prompt to register it as external program. }); } } } else { $me->{UNGZIPPRG} = _my_which("gzip"); } $me->{TARPRG} = _my_which("tar") || _my_which("gtar"); bless $me, $class; } sub _zlib_ok () { $CPAN::META->has_inst("Compress::Zlib") or return; Compress::Zlib->can('gzopen'); } sub _my_which { my($what) = @_; if ($CPAN::Config->{$what}) { return $CPAN::Config->{$what}; } if ($CPAN::META->has_inst("File::Which")) { return File::Which::which($what); } my @cand = MM->maybe_command($what); return $cand[0] if @cand; require File::Spec; my $component; PATH_COMPONENT: foreach $component (File::Spec->path()) { next unless defined($component) && $component; my($abs) = File::Spec->catfile($component,$what); if (MM->maybe_command($abs)) { return $abs; } } return; } sub gzip { my($self,$read) = @_; my $write = $self->{FILE}; if (_zlib_ok) { my($buffer,$fhw); $fhw = FileHandle->new($read) or $CPAN::Frontend->mydie("Could not open $read: $!"); my $cwd = `pwd`; my $gz = Compress::Zlib::gzopen($write, "wb") or $CPAN::Frontend->mydie("Cannot gzopen $write: $! (pwd is $cwd)\n"); binmode($fhw); $gz->gzwrite($buffer) while read($fhw,$buffer,4096) > 0 ; $gz->gzclose() ; $fhw->close; return 1; } else { my $command = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG}); system(qq{$command -c "$read" > "$write"})==0; } } sub gunzip { my($self,$write) = @_; my $read = $self->{FILE}; if (_zlib_ok) { my($buffer,$fhw); $fhw = FileHandle->new(">$write") or $CPAN::Frontend->mydie("Could not open >$write: $!"); my $gz = Compress::Zlib::gzopen($read, "rb") or $CPAN::Frontend->mydie("Cannot gzopen $read: $!\n"); binmode($fhw); $fhw->print($buffer) while $gz->gzread($buffer) > 0 ; $CPAN::Frontend->mydie("Error reading from $read: $!\n") if $gz->gzerror != Compress::Zlib::Z_STREAM_END(); $gz->gzclose() ; $fhw->close; return 1; } else { my $command = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG}); system(qq{$command -d -c "$read" > "$write"})==0; } } sub gtest { my($self) = @_; return $self->{GTEST} if exists $self->{GTEST}; defined $self->{FILE} or $CPAN::Frontend->mydie("gtest called but no FILE specified"); my $read = $self->{FILE}; my $success; if ($read=~/\.(?:bz2|tbz)$/ && $CPAN::META->has_inst("Compress::Bzip2")) { my($buffer,$len); $len = 0; my $gz = Compress::Bzip2::bzopen($read, "rb") or $CPAN::Frontend->mydie(sprintf("Cannot bzopen %s: %s\n", $read, $Compress::Bzip2::bzerrno)); while ($gz->bzread($buffer) > 0 ) { $len += length($buffer); $buffer = ""; } my $err = $gz->bzerror; $success = ! $err || $err == Compress::Bzip2::BZ_STREAM_END(); if ($len == -s $read) { $success = 0; CPAN->debug("hit an uncompressed file") if $CPAN::DEBUG; } $gz->gzclose(); CPAN->debug("err[$err]success[$success]") if $CPAN::DEBUG; } elsif ( $read=~/\.(?:gz|tgz)$/ && _zlib_ok ) { # After I had reread the documentation in zlib.h, I discovered that # uncompressed files do not lead to an gzerror (anymore?). my($buffer,$len); $len = 0; my $gz = Compress::Zlib::gzopen($read, "rb") or $CPAN::Frontend->mydie(sprintf("Cannot gzopen %s: %s\n", $read, $Compress::Zlib::gzerrno)); while ($gz->gzread($buffer) > 0 ) { $len += length($buffer); $buffer = ""; } my $err = $gz->gzerror; $success = ! $err || $err == Compress::Zlib::Z_STREAM_END(); if ($len == -s $read) { $success = 0; CPAN->debug("hit an uncompressed file") if $CPAN::DEBUG; } $gz->gzclose(); CPAN->debug("err[$err]success[$success]") if $CPAN::DEBUG; } elsif (!$self->{ISCOMPRESSED}) { $success = 0; } else { my $command = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG}); $success = 0==system(qq{$command -qdt "$read"}); } return $self->{GTEST} = $success; } sub TIEHANDLE { my($class,$file) = @_; my $ret; $class->debug("file[$file]"); my $self = $class->new($file); if (0) { } elsif (!$self->gtest) { my $fh = FileHandle->new($file) or $CPAN::Frontend->mydie("Could not open file[$file]: $!"); binmode $fh; $self->{FH} = $fh; $class->debug("via uncompressed FH"); } elsif ($file =~ /\.(?:bz2|tbz)$/ && $CPAN::META->has_inst("Compress::Bzip2")) { my $gz = Compress::Bzip2::bzopen($file,"rb") or $CPAN::Frontend->mydie("Could not bzopen $file"); $self->{GZ} = $gz; $class->debug("via Compress::Bzip2"); } elsif ($file =~/\.(?:gz|tgz)$/ && _zlib_ok) { my $gz = Compress::Zlib::gzopen($file,"rb") or $CPAN::Frontend->mydie("Could not gzopen $file"); $self->{GZ} = $gz; $class->debug("via Compress::Zlib"); } else { my $gzip = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG}); my $pipe = "$gzip -d -c $file |"; my $fh = FileHandle->new($pipe) or $CPAN::Frontend->mydie("Could not pipe[$pipe]: $!"); binmode $fh; $self->{FH} = $fh; $class->debug("via external $gzip"); } $self; } sub READLINE { my($self) = @_; if (exists $self->{GZ}) { my $gz = $self->{GZ}; my($line,$bytesread); $bytesread = $gz->gzreadline($line); return undef if $bytesread <= 0; return $line; } else { my $fh = $self->{FH}; return scalar <$fh>; } } sub READ { my($self,$ref,$length,$offset) = @_; $CPAN::Frontend->mydie("read with offset not implemented") if defined $offset; if (exists $self->{GZ}) { my $gz = $self->{GZ}; my $byteread = $gz->gzread($$ref,$length);# 30eaf79e8b446ef52464b5422da328a8 return $byteread; } else { my $fh = $self->{FH}; return read($fh,$$ref,$length); } } sub DESTROY { my($self) = @_; if (exists $self->{GZ}) { my $gz = $self->{GZ}; $gz->gzclose() if defined $gz; # hard to say if it is allowed # to be undef ever. AK, 2000-09 } else { my $fh = $self->{FH}; $fh->close if defined $fh; } undef $self; } sub untar { my($self) = @_; my $file = $self->{FILE}; my($prefer) = 0; my $exttar = $self->{TARPRG} || ""; $exttar = "" if $exttar =~ /^\s+$/; # user refuses to use it my $extgzip = $self->{UNGZIPPRG} || ""; $extgzip = "" if $extgzip =~ /^\s+$/; # user refuses to use it if (0) { # makes changing order easier } elsif ($BUGHUNTING) { $prefer=2; } elsif ($CPAN::Config->{prefer_external_tar}) { $prefer = 1; } elsif ( $CPAN::META->has_usable("Archive::Tar") && _zlib_ok ) { my $prefer_external_tar = $CPAN::Config->{prefer_external_tar}; unless (defined $prefer_external_tar) { if ($^O =~ /(MSWin32|solaris)/) { $prefer_external_tar = 0; } else { $prefer_external_tar = 1; } } $prefer = $prefer_external_tar ? 1 : 2; } elsif ($exttar && $extgzip) { # no modules and not bz2 $prefer = 1; # but solaris binary tar is a problem if ($^O eq 'solaris' && qx($exttar --version 2>/dev/null) !~ /gnu/i) { $CPAN::Frontend->mywarn(<< 'END_WARN'); WARNING: Many CPAN distributions were archived with GNU tar and some of them may be incompatible with Solaris tar. We respectfully suggest you configure CPAN to use a GNU tar instead ("o conf init tar") or install a recent Archive::Tar instead; END_WARN } } else { my $foundtar = $exttar ? "'$exttar'" : "nothing"; my $foundzip = $extgzip ? "'$extgzip'" : $foundtar ? "nothing" : "also nothing"; my $foundAT; if ($CPAN::META->has_usable("Archive::Tar")) { $foundAT = sprintf "'%s'", "Archive::Tar::"->VERSION; } else { $foundAT = "nothing"; } my $foundCZ; if (_zlib_ok) { $foundCZ = sprintf "'%s'", "Compress::Zlib::"->VERSION; } elsif ($foundAT) { $foundCZ = "nothing"; } else { $foundCZ = "also nothing"; } $CPAN::Frontend->mydie(qq{ CPAN.pm needs either the external programs tar and gzip -or- both modules Archive::Tar and Compress::Zlib installed. For tar I found $foundtar, for gzip $foundzip. For Archive::Tar I found $foundAT, for Compress::Zlib $foundCZ; Can't continue cutting file '$file'. }); } my $tar_verb = "v"; if (defined $CPAN::Config->{tar_verbosity}) { $tar_verb = $CPAN::Config->{tar_verbosity} eq "none" ? "" : $CPAN::Config->{tar_verbosity}; } if ($prefer==1) { # 1 => external gzip+tar my($system); my $is_compressed = $self->gtest(); my $tarcommand = CPAN::HandleConfig->safe_quote($exttar); if ($is_compressed) { my $command = CPAN::HandleConfig->safe_quote($extgzip); $system = qq{$command -d -c }. qq{< "$file" | $tarcommand x${tar_verb}f -}; } else { $system = qq{$tarcommand x${tar_verb}f "$file"}; } if (system($system) != 0) { # people find the most curious tar binaries that cannot handle # pipes if ($is_compressed) { (my $ungzf = $file) =~ s/\.gz(?!\n)\Z//; $ungzf = basename $ungzf; my $ct = CPAN::Tarzip->new($file); if ($ct->gunzip($ungzf)) { $CPAN::Frontend->myprint(qq{Uncompressed $file successfully\n}); } else { $CPAN::Frontend->mydie(qq{Couldn\'t uncompress $file\n}); } $file = $ungzf; } $system = qq{$tarcommand x${tar_verb}f "$file"}; $CPAN::Frontend->myprint(qq{Using Tar:$system:\n}); my $ret = system($system); if ($ret==0) { $CPAN::Frontend->myprint(qq{Untarred $file successfully\n}); } else { if ($? == -1) { $CPAN::Frontend->mydie(sprintf qq{Couldn\'t untar %s: '%s'\n}, $file, $!); } elsif ($? & 127) { $CPAN::Frontend->mydie(sprintf qq{Couldn\'t untar %s: child died with signal %d, %s coredump\n}, $file, ($? & 127), ($? & 128) ? 'with' : 'without'); } else { $CPAN::Frontend->mydie(sprintf qq{Couldn\'t untar %s: child exited with value %d\n}, $file, $? >> 8); } } return 1; } else { return 1; } } elsif ($prefer==2) { # 2 => modules unless ($CPAN::META->has_usable("Archive::Tar")) { $CPAN::Frontend->mydie("Archive::Tar not installed, please install it to continue"); } # Make sure AT does not use uid/gid/permissions in the archive # This leaves it to the user's umask instead local $Archive::Tar::CHMOD = 1; local $Archive::Tar::SAME_PERMISSIONS = 0; # Make sure AT leaves current user as owner local $Archive::Tar::CHOWN = 0; my $tar = Archive::Tar->new($file,1); my $af; # archive file my @af; if ($BUGHUNTING) { # RCS 1.337 had this code, it turned out unacceptable slow but # it revealed a bug in Archive::Tar. Code is only here to hunt # the bug again. It should never be enabled in published code. # GDGraph3d-0.53 was an interesting case according to Larry # Virden. warn(">>>Bughunting code enabled<<< " x 20); for $af ($tar->list_files) { if ($af =~ m!^(/|\.\./)!) { $CPAN::Frontend->mydie("ALERT: Archive contains ". "illegal member [$af]"); } $CPAN::Frontend->myprint("$af\n"); $tar->extract($af); # slow but effective for finding the bug return if $CPAN::Signal; } } else { for $af ($tar->list_files) { if ($af =~ m!^(/|\.\./)!) { $CPAN::Frontend->mydie("ALERT: Archive contains ". "illegal member [$af]"); } if ($tar_verb eq "v" || $tar_verb eq "vv") { $CPAN::Frontend->myprint("$af\n"); } push @af, $af; return if $CPAN::Signal; } $tar->extract(@af) or $CPAN::Frontend->mydie("Could not untar with Archive::Tar."); } Mac::BuildTools::convert_files([$tar->list_files], 1) if ($^O eq 'MacOS'); return 1; } } sub unzip { my($self) = @_; my $file = $self->{FILE}; if ($CPAN::META->has_inst("Archive::Zip")) { # blueprint of the code from Archive::Zip::Tree::extractTree(); my $zip = Archive::Zip->new(); my $status; $status = $zip->read($file); $CPAN::Frontend->mydie("Read of file[$file] failed\n") if $status != Archive::Zip::AZ_OK(); $CPAN::META->debug("Successfully read file[$file]") if $CPAN::DEBUG; my @members = $zip->members(); for my $member ( @members ) { my $af = $member->fileName(); if ($af =~ m!^(/|\.\./)!) { $CPAN::Frontend->mydie("ALERT: Archive contains ". "illegal member [$af]"); } $status = $member->extractToFileNamed( $af ); $CPAN::META->debug("af[$af]status[$status]") if $CPAN::DEBUG; $CPAN::Frontend->mydie("Extracting of file[$af] from zipfile[$file] failed\n") if $status != Archive::Zip::AZ_OK(); return if $CPAN::Signal; } return 1; } elsif ( my $unzip = $CPAN::Config->{unzip} ) { my @system = ($unzip, $file); return system(@system) == 0; } else { $CPAN::Frontend->mydie(<<"END"); Can't unzip '$file': You have not configured an 'unzip' program and do not have Archive::Zip installed. Please either install Archive::Zip or else configure 'unzip' by running the command 'o conf init unzip' from the CPAN shell prompt. END } } 1; __END__ =head1 NAME CPAN::Tarzip - internal handling of tar archives for CPAN.pm =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/CPAN/Distrostatus.pm000044400000001714152530123070011361 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Distrostatus; use overload '""' => "as_string", fallback => 1; use vars qw($something_has_failed_at); use vars qw( $VERSION ); $VERSION = "5.5"; sub new { my($class,$arg) = @_; my $failed = substr($arg,0,2) eq "NO"; if ($failed) { $something_has_failed_at = $CPAN::CurrentCommandId; } bless { TEXT => $arg, FAILED => $failed, COMMANDID => $CPAN::CurrentCommandId, TIME => time, }, $class; } sub something_has_just_failed () { defined $something_has_failed_at && $something_has_failed_at == $CPAN::CurrentCommandId; } sub commandid { shift->{COMMANDID} } sub failed { shift->{FAILED} } sub text { my($self,$set) = @_; if (defined $set) { $self->{TEXT} = $set; } $self->{TEXT}; } sub as_string { my($self) = @_; $self->text; } 1; perl5/CPAN/Exception/blocked_urllist.pm000044400000001630152530123070013765 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Exception::blocked_urllist; use strict; use overload '""' => "as_string"; use vars qw( $VERSION ); $VERSION = "1.001"; sub new { my($class) = @_; bless {}, $class; } sub as_string { my($self) = shift; if ($CPAN::Config->{connect_to_internet_ok}) { return qq{ You have not configured a urllist for CPAN mirrors. Configure it with o conf init urllist }; } else { return qq{ You have not configured a urllist and do not allow connections to the internet to get a list of mirrors. If you wish to get a list of CPAN mirrors to pick from, use this command o conf init connect_to_internet_ok urllist If you do not wish to get a list of mirrors and would prefer to set your urllist manually, use just this command instead o conf init urllist }; } } 1; perl5/CPAN/Exception/RecursiveDependency.pm000044400000007456152530123070014566 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Exception::RecursiveDependency; use strict; use overload '""' => "as_string"; use vars qw( $VERSION ); $VERSION = "5.5001"; { package CPAN::Exception::RecursiveDependency::na; use overload '""' => "as_string"; sub new { bless {}, shift }; sub as_string { "N/A" }; } my $NA = CPAN::Exception::RecursiveDependency::na->new; # a module sees its distribution (no version) # a distribution sees its prereqs (which are module names) (usually with versions) # a bundle sees its module names and/or its distributions (no version) sub new { my($class) = shift; my($deps_arg) = shift; my (@deps,%seen,$loop_starts_with); DCHAIN: for my $dep (@$deps_arg) { push @deps, {name => $dep, display_as => $dep}; if ($seen{$dep}++) { $loop_starts_with = $dep; last DCHAIN; } } my $in_loop = 0; my %mark; DWALK: for my $i (0..$#deps) { my $x = $deps[$i]{name}; $in_loop ||= $loop_starts_with && $x eq $loop_starts_with; my $xo = CPAN::Shell->expandany($x) or next; if ($xo->isa("CPAN::Module")) { my $have = $xo->inst_version || $NA; my($want,$d,$want_type); if ($i>0 and $d = $deps[$i-1]{name}) { my $do = CPAN::Shell->expandany($d); $want = $do->{prereq_pm}{requires}{$x}; if (defined $want) { $want_type = "requires: "; } else { $want = $do->{prereq_pm}{build_requires}{$x}; if (defined $want) { $want_type = "build_requires: "; } else { $want_type = "unknown status"; $want = "???"; } } } else { $want = $xo->cpan_version; $want_type = "want: "; } $deps[$i]{have} = $have; $deps[$i]{want_type} = $want_type; $deps[$i]{want} = $want; $deps[$i]{display_as} = "$x (have: $have; $want_type$want)"; if ((! ref $have || !$have->isa('CPAN::Exception::RecursiveDependency::na')) && CPAN::Version->vge($have, $want)) { # https://rt.cpan.org/Ticket/Display.html?id=115340 undef $loop_starts_with; last DWALK; } } elsif ($xo->isa("CPAN::Distribution")) { my $pretty = $deps[$i]{display_as} = $xo->pretty_id; my $mark_as; if ($in_loop) { $mark_as = CPAN::Distrostatus->new("NO cannot resolve circular dependency"); } else { $mark_as = CPAN::Distrostatus->new("NO one dependency ($loop_starts_with) is a circular dependency"); } $mark{$pretty} = { xo => $xo, mark_as => $mark_as }; } } if ($loop_starts_with) { while (my($k,$v) = each %mark) { my $xo = $v->{xo}; $xo->{make} = $v->{mark_as}; $xo->store_persistent_state; # otherwise I will not reach # all involved parties for # the next session } } bless { deps => \@deps, loop_starts_with => $loop_starts_with }, $class; } sub is_resolvable { ! defined shift->{loop_starts_with}; } sub as_string { my($self) = shift; my $deps = $self->{deps}; my $loop_starts_with = $self->{loop_starts_with}; unless ($loop_starts_with) { return "--not a recursive/circular dependency--"; } my $ret = "\nRecursive dependency detected:\n "; $ret .= join("\n => ", map {$_->{display_as}} @$deps); $ret .= ".\nCannot resolve.\n"; $ret; } 1; perl5/CPAN/Exception/yaml_not_installed.pm000044400000000752152530123070014471 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Exception::yaml_not_installed; use strict; use overload '""' => "as_string"; use vars qw( $VERSION ); $VERSION = "5.5"; sub new { my($class,$module,$file,$during) = @_; bless { module => $module, file => $file, during => $during }, $class; } sub as_string { my($self) = shift; "'$self->{module}' not installed, cannot $self->{during} '$self->{file}'\n"; } 1; perl5/CPAN/Exception/yaml_process_error.pm000044400000003247152530123070014523 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Exception::yaml_process_error; use strict; use overload '""' => "as_string"; use vars qw( $VERSION ); $VERSION = "5.5"; sub new { my($class,$module,$file,$during,$error) = @_; # my $at = Carp::longmess(""); # XXX find something more beautiful bless { module => $module, file => $file, during => $during, error => $error, # at => $at, }, $class; } sub as_string { my($self) = shift; if ($self->{during}) { if ($self->{file}) { if ($self->{module}) { if ($self->{error}) { return "Alert: While trying to '$self->{during}' YAML file\n". " '$self->{file}'\n". "with '$self->{module}' the following error was encountered:\n". " $self->{error}\n"; } else { return "Alert: While trying to '$self->{during}' YAML file\n". " '$self->{file}'\n". "with '$self->{module}' some unknown error was encountered\n"; } } else { return "Alert: While trying to '$self->{during}' YAML file\n". " '$self->{file}'\n". "some unknown error was encountered\n"; } } else { return "Alert: While trying to '$self->{during}' some YAML file\n". "some unknown error was encountered\n"; } } else { return "Alert: unknown error encountered\n"; } } 1; perl5/CPAN/URL.pm000044400000001114152530123070007305 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::URL; use overload '""' => "as_string", fallback => 1; # accessors: TEXT(the url string), FROM(DEF=>defaultlist,USER=>urllist), # planned are things like age or quality use vars qw( $VERSION ); $VERSION = "5.5"; sub new { my($class,%args) = @_; bless { %args }, $class; } sub as_string { my($self) = @_; $self->text; } sub text { my($self,$set) = @_; if (defined $set) { $self->{TEXT} = $set; } $self->{TEXT}; } 1; perl5/CPAN/LWP/UserAgent.pm000044400000003762152530123070011215 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::LWP::UserAgent; use strict; use vars qw(@ISA $USER $PASSWD $SETUPDONE); use CPAN::HTTP::Credentials; # we delay requiring LWP::UserAgent and setting up inheritance until we need it $CPAN::LWP::UserAgent::VERSION = $CPAN::LWP::UserAgent::VERSION = "1.9601"; sub config { return if $SETUPDONE; if ($CPAN::META->has_usable('LWP::UserAgent')) { require LWP::UserAgent; @ISA = qw(Exporter LWP::UserAgent); ## no critic $SETUPDONE++; } else { $CPAN::Frontend->mywarn(" LWP::UserAgent not available\n"); } } sub get_basic_credentials { my($self, $realm, $uri, $proxy) = @_; if ( $proxy ) { return CPAN::HTTP::Credentials->get_proxy_credentials(); } else { return CPAN::HTTP::Credentials->get_non_proxy_credentials(); } } sub no_proxy { my ( $self, $no_proxy ) = @_; return $self->SUPER::no_proxy( split(',',$no_proxy) ); } # mirror(): Its purpose is to deal with proxy authentication. When we # call SUPER::mirror, we really call the mirror method in # LWP::UserAgent. LWP::UserAgent will then call # $self->get_basic_credentials or some equivalent and this will be # $self->dispatched to our own get_basic_credentials method. # Our own get_basic_credentials sets $USER and $PASSWD, two globals. # 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means # although we have gone through our get_basic_credentials, the proxy # server refuses to connect. This could be a case where the username or # password has changed in the meantime, so I'm trying once again without # $USER and $PASSWD to give the get_basic_credentials routine another # chance to set $USER and $PASSWD. sub mirror { my($self,$url,$aslocal) = @_; my $result = $self->SUPER::mirror($url,$aslocal); if ($result->code == 407) { CPAN::HTTP::Credentials->clear_credentials; $result = $self->SUPER::mirror($url,$aslocal); } $result; } 1; perl5/CPAN/Meta/Requirements.pm000044400000052506152530123070012227 0ustar00use v5.10; use strict; use warnings; package CPAN::Meta::Requirements; # ABSTRACT: a set of version requirements for a CPAN dist our $VERSION = '2.143'; use CPAN::Meta::Requirements::Range; #pod =head1 SYNOPSIS #pod #pod use CPAN::Meta::Requirements; #pod #pod my $build_requires = CPAN::Meta::Requirements->new; #pod #pod $build_requires->add_minimum('Library::Foo' => 1.208); #pod #pod $build_requires->add_minimum('Library::Foo' => 2.602); #pod #pod $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); #pod #pod $METAyml->{build_requires} = $build_requires->as_string_hash; #pod #pod =head1 DESCRIPTION #pod #pod A CPAN::Meta::Requirements object models a set of version constraints like #pod those specified in the F or F files in CPAN distributions, #pod and as defined by L. #pod It can be built up by adding more and more constraints, and it will reduce them #pod to the simplest representation. #pod #pod Logically impossible constraints will be identified immediately by thrown #pod exceptions. #pod #pod =cut use Carp (); #pod =method new #pod #pod my $req = CPAN::Meta::Requirements->new; #pod #pod This returns a new CPAN::Meta::Requirements object. It takes an optional #pod hash reference argument. Currently, only one key is supported: #pod #pod =for :list #pod * C -- if provided, when a version cannot be parsed into #pod a version object, this code reference will be called with the invalid #pod version string as first argument, and the module name as second #pod argument. It must return a valid version object. #pod #pod All other keys are ignored. #pod #pod =cut my @valid_options = qw( bad_version_hook ); sub new { my ($class, $options) = @_; $options ||= {}; Carp::croak "Argument to $class\->new() must be a hash reference" unless ref $options eq 'HASH'; my %self = map {; $_ => $options->{$_}} @valid_options; return bless \%self => $class; } #pod =method add_minimum #pod #pod $req->add_minimum( $module => $version ); #pod #pod This adds a new minimum version requirement. If the new requirement is #pod redundant to the existing specification, this has no effect. #pod #pod Minimum requirements are inclusive. C<$version> is required, along with any #pod greater version number. #pod #pod This method returns the requirements object. #pod #pod =method add_maximum #pod #pod $req->add_maximum( $module => $version ); #pod #pod This adds a new maximum version requirement. If the new requirement is #pod redundant to the existing specification, this has no effect. #pod #pod Maximum requirements are inclusive. No version strictly greater than the given #pod version is allowed. #pod #pod This method returns the requirements object. #pod #pod =method add_exclusion #pod #pod $req->add_exclusion( $module => $version ); #pod #pod This adds a new excluded version. For example, you might use these three #pod method calls: #pod #pod $req->add_minimum( $module => '1.00' ); #pod $req->add_maximum( $module => '1.82' ); #pod #pod $req->add_exclusion( $module => '1.75' ); #pod #pod Any version between 1.00 and 1.82 inclusive would be acceptable, except for #pod 1.75. #pod #pod This method returns the requirements object. #pod #pod =method exact_version #pod #pod $req->exact_version( $module => $version ); #pod #pod This sets the version required for the given module to I the given #pod version. No other version would be considered acceptable. #pod #pod This method returns the requirements object. #pod #pod =cut BEGIN { for my $type (qw(maximum exclusion exact_version)) { my $method = "with_$type"; my $to_add = $type eq 'exact_version' ? $type : "add_$type"; my $code = sub { my ($self, $name, $version) = @_; $self->__modify_entry_for($name, $method, $version); return $self; }; no strict 'refs'; *$to_add = $code; } } # add_minimum is optimized compared to generated subs above because # it is called frequently and with "0" or equivalent input sub add_minimum { my ($self, $name, $version) = @_; # stringify $version so that version->new("0.00")->stringify ne "0" # which preserves the user's choice of "0.00" as the requirement if (not defined $version or "$version" eq '0') { return $self if $self->__entry_for($name); Carp::croak("can't add new requirements to finalized requirements") if $self->is_finalized; $self->{requirements}{ $name } = CPAN::Meta::Requirements::Range->with_minimum('0', $name); } else { $self->__modify_entry_for($name, 'with_minimum', $version); } return $self; } #pod =method version_range_for_module #pod #pod $req->version_range_for_module( $another_req_object ); #pod #pod =cut sub version_range_for_module { my ($self, $module) = @_; return $self->{requirements}{$module}; } #pod =method add_requirements #pod #pod $req->add_requirements( $another_req_object ); #pod #pod This method adds all the requirements in the given CPAN::Meta::Requirements #pod object to the requirements object on which it was called. If there are any #pod conflicts, an exception is thrown. #pod #pod This method returns the requirements object. #pod #pod =cut sub add_requirements { my ($self, $req) = @_; for my $module ($req->required_modules) { my $new_range = $req->version_range_for_module($module); $self->__modify_entry_for($module, 'with_range', $new_range); } return $self; } #pod =method accepts_module #pod #pod my $bool = $req->accepts_module($module => $version); #pod #pod Given an module and version, this method returns true if the version #pod specification for the module accepts the provided version. In other words, #pod given: #pod #pod Module => '>= 1.00, < 2.00' #pod #pod We will accept 1.00 and 1.75 but not 0.50 or 2.00. #pod #pod For modules that do not appear in the requirements, this method will return #pod true. #pod #pod =cut sub accepts_module { my ($self, $module, $version) = @_; return 1 unless my $range = $self->__entry_for($module); return $range->accepts($version); } #pod =method clear_requirement #pod #pod $req->clear_requirement( $module ); #pod #pod This removes the requirement for a given module from the object. #pod #pod This method returns the requirements object. #pod #pod =cut sub clear_requirement { my ($self, $module) = @_; return $self unless $self->__entry_for($module); Carp::croak("can't clear requirements on finalized requirements") if $self->is_finalized; delete $self->{requirements}{ $module }; return $self; } #pod =method requirements_for_module #pod #pod $req->requirements_for_module( $module ); #pod #pod This returns a string containing the version requirements for a given module in #pod the format described in L or undef if the given module has no #pod requirements. This should only be used for informational purposes such as error #pod messages and should not be interpreted or used for comparison (see #pod L instead). #pod #pod =cut sub requirements_for_module { my ($self, $module) = @_; my $entry = $self->__entry_for($module); return unless $entry; return $entry->as_string; } #pod =method structured_requirements_for_module #pod #pod $req->structured_requirements_for_module( $module ); #pod #pod This returns a data structure containing the version requirements for a given #pod module or undef if the given module has no requirements. This should #pod not be used for version checks (see L instead). #pod #pod Added in version 2.134. #pod #pod =cut sub structured_requirements_for_module { my ($self, $module) = @_; my $entry = $self->__entry_for($module); return unless $entry; return $entry->as_struct; } #pod =method required_modules #pod #pod This method returns a list of all the modules for which requirements have been #pod specified. #pod #pod =cut sub required_modules { keys %{ $_[0]{requirements} } } #pod =method clone #pod #pod $req->clone; #pod #pod This method returns a clone of the invocant. The clone and the original object #pod can then be changed independent of one another. #pod #pod =cut sub clone { my ($self) = @_; my $new = (ref $self)->new; return $new->add_requirements($self); } sub __entry_for { $_[0]{requirements}{ $_[1] } } sub __modify_entry_for { my ($self, $name, $method, $version) = @_; my $fin = $self->is_finalized; my $old = $self->__entry_for($name); Carp::croak("can't add new requirements to finalized requirements") if $fin and not $old; my $new = ($old || 'CPAN::Meta::Requirements::Range') ->$method($version, $name, $self->{bad_version_hook}); Carp::croak("can't modify finalized requirements") if $fin and $old->as_string ne $new->as_string; $self->{requirements}{ $name } = $new; } #pod =method is_simple #pod #pod This method returns true if and only if all requirements are inclusive minimums #pod -- that is, if their string expression is just the version number. #pod #pod =cut sub is_simple { my ($self) = @_; for my $module ($self->required_modules) { # XXX: This is a complete hack, but also entirely correct. return if not $self->__entry_for($module)->is_simple; } return 1; } #pod =method is_finalized #pod #pod This method returns true if the requirements have been finalized by having the #pod C method called on them. #pod #pod =cut sub is_finalized { $_[0]{finalized} } #pod =method finalize #pod #pod This method marks the requirements finalized. Subsequent attempts to change #pod the requirements will be fatal, I they would result in a change. If they #pod would not alter the requirements, they have no effect. #pod #pod If a finalized set of requirements is cloned, the cloned requirements are not #pod also finalized. #pod #pod =cut sub finalize { $_[0]{finalized} = 1 } #pod =method as_string_hash #pod #pod This returns a reference to a hash describing the requirements using the #pod strings in the L specification. #pod #pod For example after the following program: #pod #pod my $req = CPAN::Meta::Requirements->new; #pod #pod $req->add_minimum('CPAN::Meta::Requirements' => 0.102); #pod #pod $req->add_minimum('Library::Foo' => 1.208); #pod #pod $req->add_maximum('Library::Foo' => 2.602); #pod #pod $req->add_minimum('Module::Bar' => 'v1.2.3'); #pod #pod $req->add_exclusion('Module::Bar' => 'v1.2.8'); #pod #pod $req->exact_version('Xyzzy' => '6.01'); #pod #pod my $hashref = $req->as_string_hash; #pod #pod C<$hashref> would contain: #pod #pod { #pod 'CPAN::Meta::Requirements' => '0.102', #pod 'Library::Foo' => '>= 1.208, <= 2.206', #pod 'Module::Bar' => '>= v1.2.3, != v1.2.8', #pod 'Xyzzy' => '== 6.01', #pod } #pod #pod =cut sub as_string_hash { my ($self) = @_; my %hash = map {; $_ => $self->{requirements}{$_}->as_string } $self->required_modules; return \%hash; } #pod =method add_string_requirement #pod #pod $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206'); #pod $req->add_string_requirement('Library::Foo' => v1.208); #pod #pod This method parses the passed in string and adds the appropriate requirement #pod for the given module. A version can be a Perl "v-string". It understands #pod version ranges as described in the L. For #pod example: #pod #pod =over 4 #pod #pod =item 1.3 #pod #pod =item >= 1.3 #pod #pod =item <= 1.3 #pod #pod =item == 1.3 #pod #pod =item != 1.3 #pod #pod =item > 1.3 #pod #pod =item < 1.3 #pod #pod =item >= 1.3, != 1.5, <= 2.0 #pod #pod A version number without an operator is equivalent to specifying a minimum #pod (C=>). Extra whitespace is allowed. #pod #pod =back #pod #pod =cut sub add_string_requirement { my ($self, $module, $req) = @_; $self->__modify_entry_for($module, 'with_string_requirement', $req); } #pod =method from_string_hash #pod #pod my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); #pod my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts ); #pod #pod This is an alternate constructor for a CPAN::Meta::Requirements #pod object. It takes a hash of module names and version requirement #pod strings and returns a new CPAN::Meta::Requirements object. As with #pod add_string_requirement, a version can be a Perl "v-string". Optionally, #pod you can supply a hash-reference of options, exactly as with the L #pod method. #pod #pod =cut sub from_string_hash { my ($class, $hash, $options) = @_; my $self = $class->new($options); for my $module (keys %$hash) { my $req = $hash->{$module}; $self->add_string_requirement($module, $req); } return $self; } 1; # vim: ts=2 sts=2 sw=2 et: __END__ =pod =encoding UTF-8 =head1 NAME CPAN::Meta::Requirements - a set of version requirements for a CPAN dist =head1 VERSION version 2.143 =head1 SYNOPSIS use CPAN::Meta::Requirements; my $build_requires = CPAN::Meta::Requirements->new; $build_requires->add_minimum('Library::Foo' => 1.208); $build_requires->add_minimum('Library::Foo' => 2.602); $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); $METAyml->{build_requires} = $build_requires->as_string_hash; =head1 DESCRIPTION A CPAN::Meta::Requirements object models a set of version constraints like those specified in the F or F files in CPAN distributions, and as defined by L. It can be built up by adding more and more constraints, and it will reduce them to the simplest representation. Logically impossible constraints will be identified immediately by thrown exceptions. =head1 METHODS =head2 new my $req = CPAN::Meta::Requirements->new; This returns a new CPAN::Meta::Requirements object. It takes an optional hash reference argument. Currently, only one key is supported: =over 4 =item * C -- if provided, when a version cannot be parsed into a version object, this code reference will be called with the invalid version string as first argument, and the module name as second argument. It must return a valid version object. =back All other keys are ignored. =head2 add_minimum $req->add_minimum( $module => $version ); This adds a new minimum version requirement. If the new requirement is redundant to the existing specification, this has no effect. Minimum requirements are inclusive. C<$version> is required, along with any greater version number. This method returns the requirements object. =head2 add_maximum $req->add_maximum( $module => $version ); This adds a new maximum version requirement. If the new requirement is redundant to the existing specification, this has no effect. Maximum requirements are inclusive. No version strictly greater than the given version is allowed. This method returns the requirements object. =head2 add_exclusion $req->add_exclusion( $module => $version ); This adds a new excluded version. For example, you might use these three method calls: $req->add_minimum( $module => '1.00' ); $req->add_maximum( $module => '1.82' ); $req->add_exclusion( $module => '1.75' ); Any version between 1.00 and 1.82 inclusive would be acceptable, except for 1.75. This method returns the requirements object. =head2 exact_version $req->exact_version( $module => $version ); This sets the version required for the given module to I the given version. No other version would be considered acceptable. This method returns the requirements object. =head2 version_range_for_module $req->version_range_for_module( $another_req_object ); =head2 add_requirements $req->add_requirements( $another_req_object ); This method adds all the requirements in the given CPAN::Meta::Requirements object to the requirements object on which it was called. If there are any conflicts, an exception is thrown. This method returns the requirements object. =head2 accepts_module my $bool = $req->accepts_module($module => $version); Given an module and version, this method returns true if the version specification for the module accepts the provided version. In other words, given: Module => '>= 1.00, < 2.00' We will accept 1.00 and 1.75 but not 0.50 or 2.00. For modules that do not appear in the requirements, this method will return true. =head2 clear_requirement $req->clear_requirement( $module ); This removes the requirement for a given module from the object. This method returns the requirements object. =head2 requirements_for_module $req->requirements_for_module( $module ); This returns a string containing the version requirements for a given module in the format described in L or undef if the given module has no requirements. This should only be used for informational purposes such as error messages and should not be interpreted or used for comparison (see L instead). =head2 structured_requirements_for_module $req->structured_requirements_for_module( $module ); This returns a data structure containing the version requirements for a given module or undef if the given module has no requirements. This should not be used for version checks (see L instead). Added in version 2.134. =head2 required_modules This method returns a list of all the modules for which requirements have been specified. =head2 clone $req->clone; This method returns a clone of the invocant. The clone and the original object can then be changed independent of one another. =head2 is_simple This method returns true if and only if all requirements are inclusive minimums -- that is, if their string expression is just the version number. =head2 is_finalized This method returns true if the requirements have been finalized by having the C method called on them. =head2 finalize This method marks the requirements finalized. Subsequent attempts to change the requirements will be fatal, I they would result in a change. If they would not alter the requirements, they have no effect. If a finalized set of requirements is cloned, the cloned requirements are not also finalized. =head2 as_string_hash This returns a reference to a hash describing the requirements using the strings in the L specification. For example after the following program: my $req = CPAN::Meta::Requirements->new; $req->add_minimum('CPAN::Meta::Requirements' => 0.102); $req->add_minimum('Library::Foo' => 1.208); $req->add_maximum('Library::Foo' => 2.602); $req->add_minimum('Module::Bar' => 'v1.2.3'); $req->add_exclusion('Module::Bar' => 'v1.2.8'); $req->exact_version('Xyzzy' => '6.01'); my $hashref = $req->as_string_hash; C<$hashref> would contain: { 'CPAN::Meta::Requirements' => '0.102', 'Library::Foo' => '>= 1.208, <= 2.206', 'Module::Bar' => '>= v1.2.3, != v1.2.8', 'Xyzzy' => '== 6.01', } =head2 add_string_requirement $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206'); $req->add_string_requirement('Library::Foo' => v1.208); This method parses the passed in string and adds the appropriate requirement for the given module. A version can be a Perl "v-string". It understands version ranges as described in the L. For example: =over 4 =item 1.3 =item >= 1.3 =item <= 1.3 =item == 1.3 =item != 1.3 =item > 1.3 =item < 1.3 =item >= 1.3, != 1.5, <= 2.0 A version number without an operator is equivalent to specifying a minimum (C=>). Extra whitespace is allowed. =back =head2 from_string_hash my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts ); This is an alternate constructor for a CPAN::Meta::Requirements object. It takes a hash of module names and version requirement strings and returns a new CPAN::Meta::Requirements object. As with add_string_requirement, a version can be a Perl "v-string". Optionally, you can supply a hash-reference of options, exactly as with the L method. =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/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git =head1 AUTHORS =over 4 =item * David Golden =item * Ricardo Signes =back =head1 CONTRIBUTORS =for stopwords Ed J Graham Knop Karen Etheridge Leon Timmermans Paul Howarth Ricardo Signes robario Tatsuhiko Miyagawa =over 4 =item * Ed J =item * Graham Knop =item * Karen Etheridge =item * Leon Timmermans =item * Paul Howarth =item * Ricardo Signes =item * robario =item * Tatsuhiko Miyagawa =item * Tatsuhiko Miyagawa =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2010 by David Golden and Ricardo Signes. 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/CPAN/Meta/Requirements/Range.pm000044400000046472152530123070013270 0ustar00use v5.10; use strict; use warnings; package CPAN::Meta::Requirements::Range; # ABSTRACT: a set of version requirements for a CPAN dist our $VERSION = '2.143'; use Carp (); #pod =head1 SYNOPSIS #pod #pod use CPAN::Meta::Requirements::Range; #pod #pod my $range = CPAN::Meta::Requirements::Range->with_minimum(1); #pod #pod $range = $range->with_maximum('v2.2'); #pod #pod my $stringified = $range->as_string; #pod #pod =head1 DESCRIPTION #pod #pod A CPAN::Meta::Requirements::Range object models a set of version constraints like #pod those specified in the F or F files in CPAN distributions, #pod and as defined by L; #pod It can be built up by adding more and more constraints, and it will reduce them #pod to the simplest representation. #pod #pod Logically impossible constraints will be identified immediately by thrown #pod exceptions. #pod #pod =cut use Carp (); package CPAN::Meta::Requirements::Range::_Base; # To help ExtUtils::MakeMaker bootstrap CPAN::Meta::Requirements on perls # before 5.10, we fall back to the EUMM bundled compatibility version module if # that's the only thing available. This shouldn't ever happen in a normal CPAN # install of CPAN::Meta::Requirements, as version.pm will be picked up from # prereqs and be available at runtime. BEGIN { eval "use version ()"; ## no critic if ( my $err = $@ ) { eval "use ExtUtils::MakeMaker::version" or die $err; ## no critic } } # from version::vpp sub _find_magic_vstring { my $value = shift; my $tvalue = ''; require B; my $sv = B::svref_2object(\$value); my $magic = ref($sv) eq 'B::PVMG' ? $sv->MAGIC : undef; while ( $magic ) { if ( $magic->TYPE eq 'V' ) { $tvalue = $magic->PTR; $tvalue =~ s/^v?(.+)$/v$1/; last; } else { $magic = $magic->MOREMAGIC; } } return $tvalue; } # Perl 5.10.0 didn't have "is_qv" in version.pm *_is_qv = version->can('is_qv') ? sub { $_[0]->is_qv } : sub { exists $_[0]->{qv} }; # construct once, reuse many times my $V0 = version->new(0); # safe if given an unblessed reference sub _isa_version { UNIVERSAL::isa( $_[0], 'UNIVERSAL' ) && $_[0]->isa('version') } sub _version_object { my ($self, $version, $module, $bad_version_hook) = @_; my ($vobj, $err); if (not defined $version or (!ref($version) && $version eq '0')) { return $V0; } elsif ( ref($version) eq 'version' || ( ref($version) && _isa_version($version) ) ) { $vobj = $version; } else { # hack around version::vpp not handling <3 character vstring literals if ( $INC{'version/vpp.pm'} || $INC{'ExtUtils/MakeMaker/version/vpp.pm'} ) { my $magic = _find_magic_vstring( $version ); $version = $magic if length $magic; } # pad to 3 characters if before 5.8.1 and appears to be a v-string if ( $] < 5.008001 && $version !~ /\A[0-9]/ && substr($version,0,1) ne 'v' && length($version) < 3 ) { $version .= "\0" x (3 - length($version)); } eval { local $SIG{__WARN__} = sub { die "Invalid version: $_[0]" }; # avoid specific segfault on some older version.pm versions die "Invalid version: $version" if $version eq 'version'; $vobj = version->new($version); }; if ( my $err = $@ ) { $vobj = eval { $bad_version_hook->($version, $module) } if ref $bad_version_hook eq 'CODE'; unless (eval { $vobj->isa("version") }) { $err =~ s{ at .* line \d+.*$}{}; die "Can't convert '$version': $err"; } } } # ensure no leading '.' if ( $vobj =~ m{\A\.} ) { $vobj = version->new("0$vobj"); } # ensure normal v-string form if ( _is_qv($vobj) ) { $vobj = version->new($vobj->normal); } return $vobj; } #pod =method with_string_requirement #pod #pod $req->with_string_requirement('>= 1.208, <= 2.206'); #pod $req->with_string_requirement(v1.208); #pod #pod This method parses the passed in string and adds the appropriate requirement. #pod A version can be a Perl "v-string". It understands version ranges as described #pod in the L. For example: #pod #pod =over 4 #pod #pod =item 1.3 #pod #pod =item >= 1.3 #pod #pod =item <= 1.3 #pod #pod =item == 1.3 #pod #pod =item != 1.3 #pod #pod =item > 1.3 #pod #pod =item < 1.3 #pod #pod =item >= 1.3, != 1.5, <= 2.0 #pod #pod A version number without an operator is equivalent to specifying a minimum #pod (C=>). Extra whitespace is allowed. #pod #pod =back #pod #pod =cut my %methods_for_op = ( '==' => [ qw(with_exact_version) ], '!=' => [ qw(with_exclusion) ], '>=' => [ qw(with_minimum) ], '<=' => [ qw(with_maximum) ], '>' => [ qw(with_minimum with_exclusion) ], '<' => [ qw(with_maximum with_exclusion) ], ); sub with_string_requirement { my ($self, $req, $module, $bad_version_hook) = @_; $module //= 'module'; unless ( defined $req && length $req ) { $req = 0; Carp::carp("Undefined requirement for $module treated as '0'"); } my $magic = _find_magic_vstring( $req ); if (length $magic) { return $self->with_minimum($magic, $module, $bad_version_hook); } my @parts = split qr{\s*,\s*}, $req; for my $part (@parts) { my ($op, $ver) = $part =~ m{\A\s*(==|>=|>|<=|<|!=)\s*(.*)\z}; if (! defined $op) { $self = $self->with_minimum($part, $module, $bad_version_hook); } else { Carp::croak("illegal requirement string: $req") unless my $methods = $methods_for_op{ $op }; $self = $self->$_($ver, $module, $bad_version_hook) for @$methods; } } return $self; } #pod =method with_range #pod #pod $range->with_range($other_range) #pod #pod This creates a new range object that is a merge two others. #pod #pod =cut sub with_range { my ($self, $other, $module, $bad_version_hook) = @_; for my $modifier($other->_as_modifiers) { my ($method, $arg) = @$modifier; $self = $self->$method($arg, $module, $bad_version_hook); } return $self; } package CPAN::Meta::Requirements::Range; our @ISA = 'CPAN::Meta::Requirements::Range::_Base'; sub _clone { return (bless { } => $_[0]) unless ref $_[0]; my ($s) = @_; my %guts = ( (exists $s->{minimum} ? (minimum => version->new($s->{minimum})) : ()), (exists $s->{maximum} ? (maximum => version->new($s->{maximum})) : ()), (exists $s->{exclusions} ? (exclusions => [ map { version->new($_) } @{ $s->{exclusions} } ]) : ()), ); bless \%guts => ref($s); } #pod =method with_exact_version #pod #pod $range->with_exact_version( $version ); #pod #pod This sets the version required to I the given #pod version. No other version would be considered acceptable. #pod #pod This method returns the version range object. #pod #pod =cut sub with_exact_version { my ($self, $version, $module, $bad_version_hook) = @_; $module //= 'module'; $self = $self->_clone; $version = $self->_version_object($version, $module, $bad_version_hook); unless ($self->accepts($version)) { $self->_reject_requirements( $module, "exact specification $version outside of range " . $self->as_string ); } return CPAN::Meta::Requirements::Range::_Exact->_new($version); } sub _simplify { my ($self, $module) = @_; if (defined $self->{minimum} and defined $self->{maximum}) { if ($self->{minimum} == $self->{maximum}) { if (grep { $_ == $self->{minimum} } @{ $self->{exclusions} || [] }) { $self->_reject_requirements( $module, "minimum and maximum are both $self->{minimum}, which is excluded", ); } return CPAN::Meta::Requirements::Range::_Exact->_new($self->{minimum}); } if ($self->{minimum} > $self->{maximum}) { $self->_reject_requirements( $module, "minimum $self->{minimum} exceeds maximum $self->{maximum}", ); } } # eliminate irrelevant exclusions if ($self->{exclusions}) { my %seen; @{ $self->{exclusions} } = grep { (! defined $self->{minimum} or $_ >= $self->{minimum}) and (! defined $self->{maximum} or $_ <= $self->{maximum}) and ! $seen{$_}++ } @{ $self->{exclusions} }; } return $self; } #pod =method with_minimum #pod #pod $range->with_minimum( $version ); #pod #pod This adds a new minimum version requirement. If the new requirement is #pod redundant to the existing specification, this has no effect. #pod #pod Minimum requirements are inclusive. C<$version> is required, along with any #pod greater version number. #pod #pod This method returns the version range object. #pod #pod =cut sub with_minimum { my ($self, $minimum, $module, $bad_version_hook) = @_; $module //= 'module'; $self = $self->_clone; $minimum = $self->_version_object( $minimum, $module, $bad_version_hook ); if (defined (my $old_min = $self->{minimum})) { $self->{minimum} = (sort { $b cmp $a } ($minimum, $old_min))[0]; } else { $self->{minimum} = $minimum; } return $self->_simplify($module); } #pod =method with_maximum #pod #pod $range->with_maximum( $version ); #pod #pod This adds a new maximum version requirement. If the new requirement is #pod redundant to the existing specification, this has no effect. #pod #pod Maximum requirements are inclusive. No version strictly greater than the given #pod version is allowed. #pod #pod This method returns the version range object. #pod #pod =cut sub with_maximum { my ($self, $maximum, $module, $bad_version_hook) = @_; $module //= 'module'; $self = $self->_clone; $maximum = $self->_version_object( $maximum, $module, $bad_version_hook ); if (defined (my $old_max = $self->{maximum})) { $self->{maximum} = (sort { $a cmp $b } ($maximum, $old_max))[0]; } else { $self->{maximum} = $maximum; } return $self->_simplify($module); } #pod =method with_exclusion #pod #pod $range->with_exclusion( $version ); #pod #pod This adds a new excluded version. For example, you might use these three #pod method calls: #pod #pod $range->with_minimum( '1.00' ); #pod $range->with_maximum( '1.82' ); #pod #pod $range->with_exclusion( '1.75' ); #pod #pod Any version between 1.00 and 1.82 inclusive would be acceptable, except for #pod 1.75. #pod #pod This method returns the requirements object. #pod #pod =cut sub with_exclusion { my ($self, $exclusion, $module, $bad_version_hook) = @_; $module //= 'module'; $self = $self->_clone; $exclusion = $self->_version_object( $exclusion, $module, $bad_version_hook ); push @{ $self->{exclusions} ||= [] }, $exclusion; return $self->_simplify($module); } sub _as_modifiers { my ($self) = @_; my @mods; push @mods, [ with_minimum => $self->{minimum} ] if exists $self->{minimum}; push @mods, [ with_maximum => $self->{maximum} ] if exists $self->{maximum}; push @mods, map {; [ with_exclusion => $_ ] } @{$self->{exclusions} || []}; return @mods; } #pod =method as_struct #pod #pod $range->as_struct( $module ); #pod #pod This returns a data structure containing the version requirements. This should #pod not be used for version checks (see L instead). #pod #pod =cut sub as_struct { my ($self) = @_; return 0 if ! keys %$self; my @exclusions = @{ $self->{exclusions} || [] }; my @parts; for my $tuple ( [ qw( >= > minimum ) ], [ qw( <= < maximum ) ], ) { my ($op, $e_op, $k) = @$tuple; if (exists $self->{$k}) { my @new_exclusions = grep { $_ != $self->{ $k } } @exclusions; if (@new_exclusions == @exclusions) { push @parts, [ $op, "$self->{ $k }" ]; } else { push @parts, [ $e_op, "$self->{ $k }" ]; @exclusions = @new_exclusions; } } } push @parts, map {; [ "!=", "$_" ] } @exclusions; return \@parts; } #pod =method as_string #pod #pod $range->as_string; #pod #pod This returns a string containing the version requirements in the format #pod described in L. This should only be used for informational #pod purposes such as error messages and should not be interpreted or used for #pod comparison (see L instead). #pod #pod =cut sub as_string { my ($self) = @_; my @parts = @{ $self->as_struct }; return $parts[0][1] if @parts == 1 and $parts[0][0] eq '>='; return join q{, }, map {; join q{ }, @$_ } @parts; } sub _reject_requirements { my ($self, $module, $error) = @_; Carp::croak("illegal requirements for $module: $error") } #pod =method accepts #pod #pod my $bool = $range->accepts($version); #pod #pod Given a version, this method returns true if the version specification #pod accepts the provided version. In other words, given: #pod #pod '>= 1.00, < 2.00' #pod #pod We will accept 1.00 and 1.75 but not 0.50 or 2.00. #pod #pod =cut sub accepts { my ($self, $version) = @_; return if defined $self->{minimum} and $version < $self->{minimum}; return if defined $self->{maximum} and $version > $self->{maximum}; return if defined $self->{exclusions} and grep { $version == $_ } @{ $self->{exclusions} }; return 1; } #pod =method is_simple #pod #pod This method returns true if and only if the range is an inclusive minimum #pod -- that is, if their string expression is just the version number. #pod #pod =cut sub is_simple { my ($self) = @_; # XXX: This is a complete hack, but also entirely correct. return if $self->as_string =~ /\s/; return 1; } package CPAN::Meta::Requirements::Range::_Exact; our @ISA = 'CPAN::Meta::Requirements::Range::_Base'; our $VERSION = '2.141'; BEGIN { eval "use version ()"; ## no critic if ( my $err = $@ ) { eval "use ExtUtils::MakeMaker::version" or die $err; ## no critic } } sub _new { bless { version => $_[1] } => $_[0] } sub accepts { return $_[0]{version} == $_[1] } sub _reject_requirements { my ($self, $module, $error) = @_; Carp::croak("illegal requirements for $module: $error") } sub _clone { (ref $_[0])->_new( version->new( $_[0]{version} ) ) } sub with_exact_version { my ($self, $version, $module, $bad_version_hook) = @_; $module //= 'module'; $version = $self->_version_object($version, $module, $bad_version_hook); return $self->_clone if $self->accepts($version); $self->_reject_requirements( $module, "can't be exactly $version when exact requirement is already $self->{version}", ); } sub with_minimum { my ($self, $minimum, $module, $bad_version_hook) = @_; $module //= 'module'; $minimum = $self->_version_object( $minimum, $module, $bad_version_hook ); return $self->_clone if $self->{version} >= $minimum; $self->_reject_requirements( $module, "minimum $minimum exceeds exact specification $self->{version}", ); } sub with_maximum { my ($self, $maximum, $module, $bad_version_hook) = @_; $module //= 'module'; $maximum = $self->_version_object( $maximum, $module, $bad_version_hook ); return $self->_clone if $self->{version} <= $maximum; $self->_reject_requirements( $module, "maximum $maximum below exact specification $self->{version}", ); } sub with_exclusion { my ($self, $exclusion, $module, $bad_version_hook) = @_; $module //= 'module'; $exclusion = $self->_version_object( $exclusion, $module, $bad_version_hook ); return $self->_clone unless $exclusion == $self->{version}; $self->_reject_requirements( $module, "tried to exclude $exclusion, which is already exactly specified", ); } sub as_string { return "== $_[0]{version}" } sub as_struct { return [ [ '==', "$_[0]{version}" ] ] } sub _as_modifiers { return [ with_exact_version => $_[0]{version} ] } 1; # vim: ts=2 sts=2 sw=2 et: __END__ =pod =encoding UTF-8 =head1 NAME CPAN::Meta::Requirements::Range - a set of version requirements for a CPAN dist =head1 VERSION version 2.143 =head1 SYNOPSIS use CPAN::Meta::Requirements::Range; my $range = CPAN::Meta::Requirements::Range->with_minimum(1); $range = $range->with_maximum('v2.2'); my $stringified = $range->as_string; =head1 DESCRIPTION A CPAN::Meta::Requirements::Range object models a set of version constraints like those specified in the F or F files in CPAN distributions, and as defined by L; It can be built up by adding more and more constraints, and it will reduce them to the simplest representation. Logically impossible constraints will be identified immediately by thrown exceptions. =head1 METHODS =head2 with_string_requirement $req->with_string_requirement('>= 1.208, <= 2.206'); $req->with_string_requirement(v1.208); This method parses the passed in string and adds the appropriate requirement. A version can be a Perl "v-string". It understands version ranges as described in the L. For example: =over 4 =item 1.3 =item >= 1.3 =item <= 1.3 =item == 1.3 =item != 1.3 =item > 1.3 =item < 1.3 =item >= 1.3, != 1.5, <= 2.0 A version number without an operator is equivalent to specifying a minimum (C=>). Extra whitespace is allowed. =back =head2 with_range $range->with_range($other_range) This creates a new range object that is a merge two others. =head2 with_exact_version $range->with_exact_version( $version ); This sets the version required to I the given version. No other version would be considered acceptable. This method returns the version range object. =head2 with_minimum $range->with_minimum( $version ); This adds a new minimum version requirement. If the new requirement is redundant to the existing specification, this has no effect. Minimum requirements are inclusive. C<$version> is required, along with any greater version number. This method returns the version range object. =head2 with_maximum $range->with_maximum( $version ); This adds a new maximum version requirement. If the new requirement is redundant to the existing specification, this has no effect. Maximum requirements are inclusive. No version strictly greater than the given version is allowed. This method returns the version range object. =head2 with_exclusion $range->with_exclusion( $version ); This adds a new excluded version. For example, you might use these three method calls: $range->with_minimum( '1.00' ); $range->with_maximum( '1.82' ); $range->with_exclusion( '1.75' ); Any version between 1.00 and 1.82 inclusive would be acceptable, except for 1.75. This method returns the requirements object. =head2 as_struct $range->as_struct( $module ); This returns a data structure containing the version requirements. This should not be used for version checks (see L instead). =head2 as_string $range->as_string; This returns a string containing the version requirements in the format described in L. This should only be used for informational purposes such as error messages and should not be interpreted or used for comparison (see L instead). =head2 accepts my $bool = $range->accepts($version); Given a version, this method returns true if the version specification accepts the provided version. In other words, given: '>= 1.00, < 2.00' We will accept 1.00 and 1.75 but not 0.50 or 2.00. =head2 is_simple This method returns true if and only if the range is an inclusive minimum -- that is, if their string expression is just the version number. =head1 AUTHORS =over 4 =item * David Golden =item * Ricardo Signes =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2010 by David Golden and Ricardo Signes. 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/CPAN/Kwalify.pm000044400000006544152530123070010265 0ustar00=head1 NAME CPAN::Kwalify - Interface between CPAN.pm and Kwalify.pm =head1 SYNOPSIS use CPAN::Kwalify; validate($schema_name, $data, $file, $doc); =head1 DESCRIPTION =over =item _validate($schema_name, $data, $file, $doc) $schema_name is the name of a supported schema. Currently only C is supported. $data is the data to be validated. $file is the absolute path to the file the data are coming from. $doc is the index of the document within $doc that is to be validated. The last two arguments are only there for better error reporting. Relies on being called from within CPAN.pm. Dies if something fails. Does not return anything useful. =item yaml($schema_name) Returns the YAML text of that schema. Dies if something fails. =back =head1 AUTHOR Andreas Koenig C<< >> =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L =cut use strict; package CPAN::Kwalify; use vars qw($VERSION $VAR1); $VERSION = "5.50"; use File::Spec (); my %vcache = (); my $schema_loaded = {}; sub _validate { my($schema_name,$data,$abs,$y) = @_; my $yaml_module = CPAN->_yaml_module; if ( $CPAN::META->has_inst($yaml_module) && $CPAN::META->has_inst("Kwalify") ) { my $load = UNIVERSAL::can($yaml_module,"Load"); unless ($schema_loaded->{$schema_name}) { eval { my $schema_yaml = yaml($schema_name); $schema_loaded->{$schema_name} = $load->($schema_yaml); }; if ($@) { # we know that YAML.pm 0.62 cannot parse the schema, # so we try a fallback my $content = do { my $path = __FILE__; $path =~ s/\.pm$//; $path = File::Spec->catfile($path, "$schema_name.dd"); local *FH; open FH, $path or die "Could not open '$path': $!"; local $/; ; }; $VAR1 = undef; eval $content; if (my $err = $@) { die "parsing of '$schema_name.dd' failed: $err"; } $schema_loaded->{$schema_name} = $VAR1; } } } if (my $schema = $schema_loaded->{$schema_name}) { my $mtime = (stat $abs)[9]; for my $k (keys %{$vcache{$abs}}) { delete $vcache{$abs}{$k} unless $k eq $mtime; } return if $vcache{$abs}{$mtime}{$y}++; eval { Kwalify::validate($schema, $data) }; if (my $err = $@) { my $info = {}; yaml($schema_name, info => $info); die "validation of distropref '$abs'[$y] against schema '$info->{path}' failed: $err"; } } } sub _clear_cache { %vcache = (); } sub yaml { my($schema_name, %opt) = @_; my $content = do { my $path = __FILE__; $path =~ s/\.pm$//; $path = File::Spec->catfile($path, "$schema_name.yml"); if ($opt{info}) { $opt{info}{path} = $path; } local *FH; open FH, $path or die "Could not open '$path': $!"; local $/; ; }; return $content; } 1; # Local Variables: # mode: cperl # cperl-indent-level: 4 # End: perl5/CPAN/InfoObj.pm000044400000015375152530123070010207 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::InfoObj; use strict; use CPAN::Debug; @CPAN::InfoObj::ISA = qw(CPAN::Debug); use Cwd qw(chdir); use vars qw( $VERSION ); $VERSION = "5.5"; sub ro { my $self = shift; exists $self->{RO} and return $self->{RO}; } #-> sub CPAN::InfoObj::cpan_userid sub cpan_userid { my $self = shift; my $ro = $self->ro; if ($ro) { return $ro->{CPAN_USERID} || "N/A"; } else { $self->debug("ID[$self->{ID}]"); # N/A for bundles found locally return "N/A"; } } sub id { shift->{ID}; } #-> sub CPAN::InfoObj::new ; sub new { my $this = bless {}, shift; %$this = @_; $this } # The set method may only be used by code that reads index data or # otherwise "objective" data from the outside world. All session # related material may do anything else with instance variables but # must not touch the hash under the RO attribute. The reason is that # the RO hash gets written to Metadata file and is thus persistent. #-> sub CPAN::InfoObj::safe_chdir ; sub safe_chdir { my($self,$todir) = @_; # we die if we cannot chdir and we are debuggable Carp::confess("safe_chdir called without todir argument") unless defined $todir and length $todir; if (chdir $todir) { $self->debug(sprintf "changed directory to %s", CPAN::anycwd()) if $CPAN::DEBUG; } else { if (-e $todir) { unless (-x $todir) { unless (chmod 0755, $todir) { my $cwd = CPAN::anycwd(); $CPAN::Frontend->mywarn("I have neither the -x permission nor the ". "permission to change the permission; cannot ". "chdir to '$todir'\n"); $CPAN::Frontend->mysleep(5); $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }. qq{to todir[$todir]: $!}); } } } else { $CPAN::Frontend->mydie("Directory '$todir' has gone. Cannot continue.\n"); } if (chdir $todir) { $self->debug(sprintf "changed directory to %s", CPAN::anycwd()) if $CPAN::DEBUG; } else { my $cwd = CPAN::anycwd(); $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }. qq{to todir[$todir] (a chmod has been issued): $!}); } } } #-> sub CPAN::InfoObj::set ; sub set { my($self,%att) = @_; my $class = ref $self; # This must be ||=, not ||, because only if we write an empty # reference, only then the set method will write into the readonly # area. But for Distributions that spring into existence, maybe # because of a typo, we do not like it that they are written into # the readonly area and made permanent (at least for a while) and # that is why we do not "allow" other places to call ->set. unless ($self->id) { CPAN->debug("Bug? Empty ID, rejecting"); return; } my $ro = $self->{RO} = $CPAN::META->{readonly}{$class}{$self->id} ||= {}; while (my($k,$v) = each %att) { $ro->{$k} = $v; } } #-> sub CPAN::InfoObj::as_glimpse ; sub as_glimpse { my($self) = @_; my(@m); my $class = ref($self); $class =~ s/^CPAN:://; my $id = $self->can("pretty_id") ? $self->pretty_id : $self->{ID}; push @m, sprintf "%-15s %s\n", $class, $id; join "", @m; } #-> sub CPAN::InfoObj::as_string ; sub as_string { my($self) = @_; my(@m); my $class = ref($self); $class =~ s/^CPAN:://; push @m, $class, " id = $self->{ID}\n"; my $ro; unless ($ro = $self->ro) { if (substr($self->{ID},-1,1) eq ".") { # directory $ro = +{}; } else { $CPAN::Frontend->mywarn("Unknown object $self->{ID}\n"); $CPAN::Frontend->mysleep(5); return; } } for (sort keys %$ro) { # next if m/^(ID|RO)$/; my $extra = ""; if ($_ eq "CPAN_USERID") { $extra .= " ("; $extra .= $self->fullname; my $email; # old perls! if ($email = $CPAN::META->instance("CPAN::Author", $self->cpan_userid )->email) { $extra .= " <$email>"; } else { $extra .= " "; } $extra .= ")"; } elsif ($_ eq "FULLNAME") { # potential UTF-8 conversion push @m, sprintf " %-12s %s\n", $_, $self->fullname; next; } next unless defined $ro->{$_}; push @m, sprintf " %-12s %s%s\n", $_, $ro->{$_}, $extra; } KEY: for (sort keys %$self) { next if m/^(ID|RO)$/; unless (defined $self->{$_}) { delete $self->{$_}; next KEY; } if (ref($self->{$_}) eq "ARRAY") { push @m, sprintf " %-12s %s\n", $_, "@{$self->{$_}}"; } elsif (ref($self->{$_}) eq "HASH") { my $value; if (/^CONTAINSMODS$/) { $value = join(" ",sort keys %{$self->{$_}}); } elsif (/^prereq_pm$/) { my @value; my $v = $self->{$_}; for my $x (sort keys %$v) { my @svalue; for my $y (sort keys %{$v->{$x}}) { push @svalue, "$y=>$v->{$x}{$y}"; } push @value, "$x\:" . join ",", @svalue if @svalue; } $value = join ";", @value; } else { $value = $self->{$_}; } push @m, sprintf( " %-12s %s\n", $_, $value, ); } else { push @m, sprintf " %-12s %s\n", $_, $self->{$_}; } } join "", @m, "\n"; } #-> sub CPAN::InfoObj::fullname ; sub fullname { my($self) = @_; $CPAN::META->instance("CPAN::Author",$self->cpan_userid)->fullname; } #-> sub CPAN::InfoObj::dump ; sub dump { my($self, $what) = @_; unless ($CPAN::META->has_inst("Data::Dumper")) { $CPAN::Frontend->mydie("dump command requires Data::Dumper installed"); } local $Data::Dumper::Sortkeys; $Data::Dumper::Sortkeys = 1; my $out = Data::Dumper::Dumper($what ? eval $what : $self); if (length $out > 100000) { my $fh_pager = FileHandle->new; local($SIG{PIPE}) = "IGNORE"; my $pager = $CPAN::Config->{'pager'} || "cat"; $fh_pager->open("|$pager") or die "Could not open pager $pager\: $!"; $fh_pager->print($out); close $fh_pager; } else { $CPAN::Frontend->myprint($out); } } 1; perl5/CPAN/FTP/netrc.pm000044400000003032152530123070010410 0ustar00package CPAN::FTP::netrc; use strict; $CPAN::FTP::netrc::VERSION = $CPAN::FTP::netrc::VERSION = "1.01"; # package CPAN::FTP::netrc; sub new { my($class) = @_; my $file = File::Spec->catfile($ENV{HOME},".netrc"); my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($file); $mode ||= 0; my $protected = 0; my($fh,@machines,$hasdefault); $hasdefault = 0; $fh = FileHandle->new or die "Could not create a filehandle"; if($fh->open($file)) { $protected = ($mode & 077) == 0; local($/) = ""; NETRC: while (<$fh>) { my(@tokens) = split " ", $_; TOKEN: while (@tokens) { my($t) = shift @tokens; if ($t eq "default") { $hasdefault++; last NETRC; } last TOKEN if $t eq "macdef"; if ($t eq "machine") { push @machines, shift @tokens; } } } } else { $file = $hasdefault = $protected = ""; } bless { 'mach' => [@machines], 'netrc' => $file, 'hasdefault' => $hasdefault, 'protected' => $protected, }, $class; } # CPAN::FTP::netrc::hasdefault; sub hasdefault { shift->{'hasdefault'} } sub netrc { shift->{'netrc'} } sub protected { shift->{'protected'} } sub contains { my($self,$mach) = @_; for ( @{$self->{'mach'}} ) { return 1 if $_ eq $mach; } return 0; } 1; perl5/CPAN/Bundle.pm000044400000023640152530123070010064 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Bundle; use strict; use CPAN::Module; @CPAN::Bundle::ISA = qw(CPAN::Module); use vars qw( $VERSION ); $VERSION = "5.5005"; sub look { my $self = shift; $CPAN::Frontend->myprint($self->as_string); } #-> CPAN::Bundle::undelay sub undelay { my $self = shift; delete $self->{later}; for my $c ( $self->contains ) { my $obj = CPAN::Shell->expandany($c) or next; if ($obj->id eq $self->id){ my $id = $obj->id; $CPAN::Frontend->mywarn("$id seems to contain itself, skipping\n"); next; } $obj->undelay; } } # mark as dirty/clean #-> sub CPAN::Bundle::color_cmd_tmps ; sub color_cmd_tmps { my($self) = shift; my($depth) = shift || 0; my($color) = shift || 0; my($ancestors) = shift || []; # a module needs to recurse to its cpan_file, a distribution needs # to recurse into its prereq_pms, a bundle needs to recurse into its modules return if exists $self->{incommandcolor} && $color==1 && $self->{incommandcolor}==$color; if ($depth>=$CPAN::MAX_RECURSION) { my $e = CPAN::Exception::RecursiveDependency->new($ancestors); if ($e->is_resolvable) { return $self->{incommandcolor}=2; } else { die $e; } } # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; for my $c ( $self->contains ) { my $obj = CPAN::Shell->expandany($c) or next; CPAN->debug("c[$c]obj[$obj]") if $CPAN::DEBUG; $obj->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); } # never reached code? #if ($color==0) { #delete $self->{badtestcnt}; #} $self->{incommandcolor} = $color; } #-> sub CPAN::Bundle::as_string ; sub as_string { my($self) = @_; $self->contains; # following line must be "=", not "||=" because we have a moving target $self->{INST_VERSION} = $self->inst_version; return $self->SUPER::as_string; } #-> sub CPAN::Bundle::contains ; sub contains { my($self) = @_; my($inst_file) = $self->inst_file || ""; my($id) = $self->id; $self->debug("inst_file[$inst_file]id[$id]") if $CPAN::DEBUG; if ($inst_file && CPAN::Version->vlt($self->inst_version,$self->cpan_version)) { undef $inst_file; } unless ($inst_file) { # Try to get at it in the cpan directory $self->debug("no inst_file") if $CPAN::DEBUG; my $cpan_file; $CPAN::Frontend->mydie("I don't know a bundle with ID '$id'\n") unless $cpan_file = $self->cpan_file; if ($cpan_file eq "N/A") { $CPAN::Frontend->mywarn("Bundle '$id' not found on disk and not on CPAN. Maybe stale symlink? Maybe removed during session?\n"); return; } my $dist = $CPAN::META->instance('CPAN::Distribution', $self->cpan_file); $self->debug("before get id[$dist->{ID}]") if $CPAN::DEBUG; $dist->get; $self->debug("after get id[$dist->{ID}]") if $CPAN::DEBUG; my($todir) = $CPAN::Config->{'cpan_home'}; my(@me,$from,$to,$me); @me = split /::/, $self->id; $me[-1] .= ".pm"; $me = File::Spec->catfile(@me); my $build_dir; unless ($build_dir = $dist->{build_dir}) { $CPAN::Frontend->mywarn("Warning: cannot determine bundle content without a build_dir.\n"); return; } $from = $self->find_bundle_file($build_dir,join('/',@me)); $to = File::Spec->catfile($todir,$me); File::Path::mkpath(File::Basename::dirname($to)); File::Copy::copy($from, $to) or Carp::confess("Couldn't copy $from to $to: $!"); $inst_file = $to; } my @result; my $fh = FileHandle->new; local $/ = "\n"; open($fh,$inst_file) or die "Could not open '$inst_file': $!"; my $in_cont = 0; $self->debug("inst_file[$inst_file]") if $CPAN::DEBUG; while (<$fh>) { $in_cont = m/^=(?!head1\s+(?i-xsm:CONTENTS))/ ? 0 : m/^=head1\s+(?i-xsm:CONTENTS)/ ? 1 : $in_cont; next unless $in_cont; next if /^=/; s/\#.*//; next if /^\s+$/; chomp; push @result, (split " ", $_, 2)[0]; } close $fh; delete $self->{STATUS}; $self->{CONTAINS} = \@result; $self->debug("CONTAINS[@result]") if $CPAN::DEBUG; unless (@result) { $CPAN::Frontend->mywarn(qq{ The bundle file "$inst_file" may be a broken bundlefile. It seems not to contain any bundle definition. Please check the file and if it is bogus, please delete it. Sorry for the inconvenience. }); } @result; } #-> sub CPAN::Bundle::find_bundle_file # $where is in local format, $what is in unix format sub find_bundle_file { my($self,$where,$what) = @_; $self->debug("where[$where]what[$what]") if $CPAN::DEBUG; ### The following two lines let CPAN.pm become Bundle/CPAN.pm :-( ### my $bu = File::Spec->catfile($where,$what); ### return $bu if -f $bu; my $manifest = File::Spec->catfile($where,"MANIFEST"); unless (-f $manifest) { require ExtUtils::Manifest; my $cwd = CPAN::anycwd(); $self->safe_chdir($where); ExtUtils::Manifest::mkmanifest(); $self->safe_chdir($cwd); } my $fh = FileHandle->new($manifest) or Carp::croak("Couldn't open $manifest: $!"); local($/) = "\n"; my $bundle_filename = $what; $bundle_filename =~ s|Bundle.*/||; my $bundle_unixpath; while (<$fh>) { next if /^\s*\#/; my($file) = /(\S+)/; if ($file =~ m|\Q$what\E$|) { $bundle_unixpath = $file; # return File::Spec->catfile($where,$bundle_unixpath); # bad last; } # retry if she managed to have no Bundle directory $bundle_unixpath = $file if $file =~ m|\Q$bundle_filename\E$|; } return File::Spec->catfile($where, split /\//, $bundle_unixpath) if $bundle_unixpath; Carp::croak("Couldn't find a Bundle file in $where"); } # needs to work quite differently from Module::inst_file because of # cpan_home/Bundle/ directory and the possibility that we have # shadowing effect. As it makes no sense to take the first in @INC for # Bundles, we parse them all for $VERSION and take the newest. #-> sub CPAN::Bundle::inst_file ; sub inst_file { my($self) = @_; my($inst_file); my(@me); @me = split /::/, $self->id; $me[-1] .= ".pm"; my($incdir,$bestv); foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) { my $parsefile = File::Spec->catfile($incdir, @me); CPAN->debug("parsefile[$parsefile]") if $CPAN::DEBUG; next unless -f $parsefile; my $have = eval { MM->parse_version($parsefile); }; if ($@) { $CPAN::Frontend->mywarn("Error while parsing version number in file '$parsefile'\n"); } if (!$bestv || CPAN::Version->vgt($have,$bestv)) { $self->{INST_FILE} = $parsefile; $self->{INST_VERSION} = $bestv = $have; } } $self->{INST_FILE}; } #-> sub CPAN::Bundle::inst_version ; sub inst_version { my($self) = @_; $self->inst_file; # finds INST_VERSION as side effect $self->{INST_VERSION}; } #-> sub CPAN::Bundle::rematein ; sub rematein { my($self,$meth) = @_; $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG; my($id) = $self->id; Carp::croak( "Can't $meth $id, don't have an associated bundle file. :-(\n" ) unless $self->inst_file || $self->cpan_file; my($s,%fail); for $s ($self->contains) { my($type) = $s =~ m|/| ? 'CPAN::Distribution' : $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module'; if ($type eq 'CPAN::Distribution') { $CPAN::Frontend->mywarn(qq{ The Bundle }.$self->id.qq{ contains explicitly a file '$s'. Going to $meth that. }); $CPAN::Frontend->mysleep(5); } # possibly noisy action: $self->debug("type[$type] s[$s]") if $CPAN::DEBUG; my $obj = $CPAN::META->instance($type,$s); $obj->{reqtype} = $self->{reqtype}; $obj->{viabundle} ||= { id => $id, reqtype => $self->{reqtype}, optional => !$self->{mandatory}}; # $obj->$meth(); # XXX should optional be based on whether bundle was optional? -- xdg, 2012-04-01 # A: Sure, what could demand otherwise? --andk, 2013-11-25 CPAN::Queue->queue_item(qmod => $obj->id, reqtype => $self->{reqtype}, optional => !$self->{mandatory}); } } # If a bundle contains another that contains an xs_file we have here, # we just don't bother I suppose #-> sub CPAN::Bundle::xs_file sub xs_file { return 0; } #-> sub CPAN::Bundle::force ; sub fforce { shift->rematein('fforce',@_); } #-> sub CPAN::Bundle::force ; sub force { shift->rematein('force',@_); } #-> sub CPAN::Bundle::notest ; sub notest { shift->rematein('notest',@_); } #-> sub CPAN::Bundle::get ; sub get { shift->rematein('get',@_); } #-> sub CPAN::Bundle::make ; sub make { shift->rematein('make',@_); } #-> sub CPAN::Bundle::test ; sub test { my $self = shift; # $self->{badtestcnt} ||= 0; $self->rematein('test',@_); } #-> sub CPAN::Bundle::install ; sub install { my $self = shift; $self->rematein('install',@_); } #-> sub CPAN::Bundle::clean ; sub clean { shift->rematein('clean',@_); } #-> sub CPAN::Bundle::uptodate ; sub uptodate { my($self) = @_; return 0 unless $self->SUPER::uptodate; # we must have the current Bundle def my $c; foreach $c ($self->contains) { my $obj = CPAN::Shell->expandany($c); return 0 unless $obj->uptodate; } return 1; } #-> sub CPAN::Bundle::readme ; sub readme { my($self) = @_; my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{ No File found for bundle } . $self->id . qq{\n}), return; $self->debug("self[$self] file[$file]") if $CPAN::DEBUG; $CPAN::META->instance('CPAN::Distribution',$file)->readme; } 1; perl5/CPAN/FirstTime.pm000044400000222025152530123070010557 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::FirstTime; use strict; use ExtUtils::MakeMaker (); use FileHandle (); use File::Basename (); use File::Path (); use File::Spec (); use CPAN::Mirrors (); use CPAN::Version (); use vars qw($VERSION $auto_config); $VERSION = "5.5317"; =head1 NAME CPAN::FirstTime - Utility for CPAN::Config file Initialization =head1 SYNOPSIS CPAN::FirstTime::init() =head1 DESCRIPTION The init routine asks a few questions and writes a CPAN/Config.pm or CPAN/MyConfig.pm file (depending on what it is currently using). In the following all questions and explanations regarding config variables are collected. =cut # down until the next =back the manpage must be parsed by the program # because the text is used in the init dialogues. my @podpara = split /\n\n/, <<'=back'; =over 2 =item allow_installing_module_downgrades The CPAN shell can watch the C directories that are built up before running C to determine whether the current distribution will end up with modules being overwritten with decreasing module version numbers. It can then let the build of this distro fail when it discovers a downgrade. Do you want to allow installing distros with decreasing module versions compared to what you have installed (yes, no, ask/yes, ask/no)? =item allow_installing_outdated_dists The CPAN shell can watch the C directories that are built up before running C to determine whether the current distribution contains modules that are indexed with a distro with a higher distro-version number than the current one. It can then let the build of this distro fail when it would not represent the most up-to-date version of the distro. Note: choosing anything but 'yes' for this option will need CPAN::DistnameInfo being installed for taking effect. Do you want to allow installing distros that are not indexed as the highest distro-version for all contained modules (yes, no, ask/yes, ask/no)? =item auto_commit Normally CPAN.pm keeps config variables in memory and changes need to be saved in a separate 'o conf commit' command to make them permanent between sessions. If you set the 'auto_commit' option to true, changes to a config variable are always automatically committed to disk. Always commit changes to config variables to disk? =item build_cache CPAN.pm can limit the size of the disk area for keeping the build directories with all the intermediate files. Cache size for build directory (in MB)? =item build_dir Directory where the build process takes place? =item build_dir_reuse Until version 1.88 CPAN.pm never trusted the contents of the build_dir directory between sessions. Since 1.88_58 CPAN.pm has a YAML-based mechanism that makes it possible to share the contents of the build_dir/ directory between different sessions with the same version of perl. People who prefer to test things several days before installing will like this feature because it saves a lot of time. If you say yes to the following question, CPAN will try to store enough information about the build process so that it can pick up in future sessions at the same state of affairs as it left a previous session. Store and re-use state information about distributions between CPAN.pm sessions? =item build_requires_install_policy When a module declares another one as a 'build_requires' prerequisite this means that the other module is only needed for building or testing the module but need not be installed permanently. In this case you may wish to install that other module nonetheless or just keep it in the 'build_dir' directory to have it available only temporarily. Installing saves time on future installations but makes the perl installation bigger. You can choose if you want to always install (yes), never install (no) or be always asked. In the latter case you can set the default answer for the question to yes (ask/yes) or no (ask/no). Policy on installing 'build_requires' modules (yes, no, ask/yes, ask/no)? =item cache_metadata To considerably speed up the initial CPAN shell startup, it is possible to use Storable to create a cache of metadata. If Storable is not available, the normal index mechanism will be used. Note: this mechanism is not used when use_sqlite is on and SQLite is running. Cache metadata (yes/no)? =item check_sigs CPAN packages can be digitally signed by authors and thus verified with the security provided by strong cryptography. The exact mechanism is defined in the Module::Signature module. While this is generally considered a good thing, it is not always convenient to the end user to install modules that are signed incorrectly or where the key of the author is not available or where some prerequisite for Module::Signature has a bug and so on. With the check_sigs parameter you can turn signature checking on and off. The default is off for now because the whole tool chain for the functionality is not yet considered mature by some. The author of CPAN.pm would recommend setting it to true most of the time and turning it off only if it turns out to be annoying. Note that if you do not have Module::Signature installed, no signature checks will be performed at all. Always try to check and verify signatures if a SIGNATURE file is in the package and Module::Signature is installed (yes/no)? =item cleanup_after_install Users who install modules and do not intend to look back, can free occupied disk space quickly by letting CPAN.pm cleanup each build directory immediately after a successful install. Remove build directory after a successful install? (yes/no)? =item colorize_output When you have Term::ANSIColor installed, you can turn on colorized output to have some visual differences between normal CPAN.pm output, warnings, debugging output, and the output of the modules being installed. Set your favorite colors after some experimenting with the Term::ANSIColor module. Please note that on Windows platforms colorized output also requires the Win32::Console::ANSI module. Do you want to turn on colored output? =item colorize_print Color for normal output? =item colorize_warn Color for warnings? =item colorize_debug Color for debugging messages? =item commandnumber_in_prompt The prompt of the cpan shell can contain the current command number for easier tracking of the session or be a plain string. Do you want the command number in the prompt (yes/no)? =item connect_to_internet_ok If you have never defined your own C in your configuration then C will be hesitant to use the built in default sites for downloading. It will ask you once per session if a connection to the internet is OK and only if you say yes, it will try to connect. But to avoid this question, you can choose your favorite download sites once and get away with it. Or, if you have no favorite download sites answer yes to the following question. If no urllist has been chosen yet, would you prefer CPAN.pm to connect to the built-in default sites without asking? (yes/no)? =item ftp_passive Shall we always set the FTP_PASSIVE environment variable when dealing with ftp download (yes/no)? =item ftpstats_period Statistics about downloads are truncated by size and period simultaneously. How many days shall we keep statistics about downloads? =item ftpstats_size Statistics about downloads are truncated by size and period simultaneously. Setting this to zero or negative disables download statistics. How many items shall we keep in the statistics about downloads? =item getcwd CPAN.pm changes the current working directory often and needs to determine its own current working directory. Per default it uses Cwd::cwd but if this doesn't work on your system for some reason, alternatives can be configured according to the following table: cwd Cwd::cwd getcwd Cwd::getcwd fastcwd Cwd::fastcwd getdcwd Cwd::getdcwd backtickcwd external command cwd Preferred method for determining the current working directory? =item halt_on_failure Normally, CPAN.pm continues processing the full list of targets and dependencies, even if one of them fails. However, you can specify that CPAN should halt after the first failure. (Note that optional recommended or suggested modules that fail will not cause a halt.) Do you want to halt on failure (yes/no)? =item histfile If you have one of the readline packages (Term::ReadLine::Perl, Term::ReadLine::Gnu, possibly others) installed, the interactive CPAN shell will have history support. The next two questions deal with the filename of the history file and with its size. If you do not want to set this variable, please hit SPACE ENTER to the following question. File to save your history? =item histsize Number of lines to save? =item inactivity_timeout Sometimes you may wish to leave the processes run by CPAN alone without caring about them. Because the Makefile.PL or the Build.PL sometimes contains question you're expected to answer, you can set a timer that will kill a 'perl Makefile.PL' process after the specified time in seconds. If you set this value to 0, these processes will wait forever. This is the default and recommended setting. Timeout for inactivity during {Makefile,Build}.PL? =item index_expire The CPAN indexes are usually rebuilt once or twice per hour, but the typical CPAN mirror mirrors only once or twice per day. Depending on the quality of your mirror and your desire to be on the bleeding edge, you may want to set the following value to more or less than one day (which is the default). It determines after how many days CPAN.pm downloads new indexes. Let the index expire after how many days? =item inhibit_startup_message When the CPAN shell is started it normally displays a greeting message that contains the running version and the status of readline support. Do you want to turn this message off? =item keep_source_where Unless you are accessing the CPAN on your filesystem via a file: URL, CPAN.pm needs to keep the source files it downloads somewhere. Please supply a directory where the downloaded files are to be kept. Download target directory? =item load_module_verbosity When CPAN.pm loads a module it needs for some optional feature, it usually reports about module name and version. Choose 'v' to get this message, 'none' to suppress it. Verbosity level for loading modules (none or v)? =item makepl_arg Every Makefile.PL is run by perl in a separate process. Likewise we run 'make' and 'make install' in separate processes. If you have any parameters (e.g. PREFIX, UNINST or the like) you want to pass to the calls, please specify them here. If you don't understand this question, just press ENTER. Typical frequently used settings: PREFIX=~/perl # non-root users (please see manual for more hints) Parameters for the 'perl Makefile.PL' command? =item make_arg Parameters for the 'make' command? Typical frequently used setting: -j3 # dual processor system (on GNU make) Your choice: =item make_install_arg Parameters for the 'make install' command? Typical frequently used setting: UNINST=1 # to always uninstall potentially conflicting files # (but do NOT use with local::lib or INSTALL_BASE) Your choice: =item make_install_make_command Do you want to use a different make command for 'make install'? Cautious people will probably prefer: su root -c make or sudo make or /path1/to/sudo -u admin_account /path2/to/make or some such. Your choice: =item mbuildpl_arg A Build.PL is run by perl in a separate process. Likewise we run './Build' and './Build install' in separate processes. If you have any parameters you want to pass to the calls, please specify them here. Typical frequently used settings: --install_base /home/xxx # different installation directory Parameters for the 'perl Build.PL' command? =item mbuild_arg Parameters for the './Build' command? Setting might be: --extra_linker_flags -L/usr/foo/lib # non-standard library location Your choice: =item mbuild_install_arg Parameters for the './Build install' command? Typical frequently used setting: --uninst 1 # uninstall conflicting files # (but do NOT use with local::lib or INSTALL_BASE) Your choice: =item mbuild_install_build_command Do you want to use a different command for './Build install'? Sudo users will probably prefer: su root -c ./Build or sudo ./Build or /path1/to/sudo -u admin_account ./Build or some such. Your choice: =item pager What is your favorite pager program? =item prefer_installer When you have Module::Build installed and a module comes with both a Makefile.PL and a Build.PL, which shall have precedence? The main two standard installer modules are the old and well established ExtUtils::MakeMaker (for short: EUMM) which uses the Makefile.PL. And the next generation installer Module::Build (MB) which works with the Build.PL (and often comes with a Makefile.PL too). If a module comes only with one of the two we will use that one but if both are supplied then a decision must be made between EUMM and MB. See also http://rt.cpan.org/Ticket/Display.html?id=29235 for a discussion about the right default. Or, as a third option you can choose RAND which will make a random decision (something regular CPAN testers will enjoy). In case you can choose between running a Makefile.PL or a Build.PL, which installer would you prefer (EUMM or MB or RAND)? =item prefs_dir CPAN.pm can store customized build environments based on regular expressions for distribution names. These are YAML files where the default options for CPAN.pm and the environment can be overridden and dialog sequences can be stored that can later be executed by an Expect.pm object. The CPAN.pm distribution comes with some prefab YAML files that cover sample distributions that can be used as blueprints to store your own prefs. Please check out the distroprefs/ directory of the CPAN.pm distribution to get a quick start into the prefs system. Directory where to store default options/environment/dialogs for building modules that need some customization? =item prerequisites_policy The CPAN module can detect when a module which you are trying to build depends on prerequisites. If this happens, it can build the prerequisites for you automatically ('follow'), ask you for confirmation ('ask'), or just ignore them ('ignore'). Choosing 'follow' also sets PERL_AUTOINSTALL and PERL_EXTUTILS_AUTOINSTALL for "--defaultdeps" if not already set. Please set your policy to one of the three values. Policy on building prerequisites (follow, ask or ignore)? =item pushy_https Boolean. Defaults to true. If this option is true, the cpan shell will use https://cpan.org/ to download stuff from the CPAN. It will fall back to http://cpan.org/ if it can't handle https for some reason (missing modules, missing programs). Whenever it falls back to the http protocol, it will issue a warning. If this option is true, the option C will be ignored. Consequently, if you want to work with local mirrors via your own configured list of URLs, you will have to choose no below. Do you want to turn the pushy_https behaviour on? =item randomize_urllist CPAN.pm can introduce some randomness when using hosts for download that are configured in the urllist parameter. Enter a numeric value between 0 and 1 to indicate how often you want to let CPAN.pm try a random host from the urllist. A value of one specifies to always use a random host as the first try. A value of zero means no randomness at all. Anything in between specifies how often, on average, a random host should be tried first. Randomize parameter =item recommends_policy (Experimental feature!) Some CPAN modules recommend additional, optional dependencies. These should generally be installed except in resource constrained environments. When this policy is true, recommended modules will be included with required modules. Include recommended modules? =item scan_cache By default, each time the CPAN module is started, cache scanning is performed to keep the cache size in sync ('atstart'). Alternatively, scanning and cleanup can happen when CPAN exits ('atexit'). To prevent any cache cleanup, answer 'never'. Perform cache scanning ('atstart', 'atexit' or 'never')? =item shell What is your favorite shell? =item show_unparsable_versions During the 'r' command CPAN.pm finds modules without version number. When the command finishes, it prints a report about this. If you want this report to be very verbose, say yes to the following variable. Show all individual modules that have no $VERSION? =item show_upload_date The 'd' and the 'm' command normally only show you information they have in their in-memory database and thus will never connect to the internet. If you set the 'show_upload_date' variable to true, 'm' and 'd' will additionally show you the upload date of the module or distribution. Per default this feature is off because it may require a net connection to get at the upload date. Always try to show upload date with 'd' and 'm' command (yes/no)? =item show_zero_versions During the 'r' command CPAN.pm finds modules with a version number of zero. When the command finishes, it prints a report about this. If you want this report to be very verbose, say yes to the following variable. Show all individual modules that have a $VERSION of zero? =item suggests_policy (Experimental feature!) Some CPAN modules suggest additional, optional dependencies. These 'suggest' dependencies provide enhanced operation. When this policy is true, suggested modules will be included with required modules. Include suggested modules? =item tar_verbosity When CPAN.pm uses the tar command, which switch for the verbosity shall be used? Choose 'none' for quiet operation, 'v' for file name listing, 'vv' for full listing. Tar command verbosity level (none or v or vv)? =item term_is_latin The next option deals with the charset (a.k.a. character set) your terminal supports. In general, CPAN is English speaking territory, so the charset does not matter much but some CPAN have names that are outside the ASCII range. If your terminal supports UTF-8, you should say no to the next question. If it expects ISO-8859-1 (also known as LATIN1) then you should say yes. If it supports neither, your answer does not matter because you will not be able to read the names of some authors anyway. If you answer no, names will be output in UTF-8. Your terminal expects ISO-8859-1 (yes/no)? =item term_ornaments When using Term::ReadLine, you can turn ornaments on so that your input stands out against the output from CPAN.pm. Do you want to turn ornaments on? =item test_report The goal of the CPAN Testers project (http://testers.cpan.org/) is to test as many CPAN packages as possible on as many platforms as possible. This provides valuable feedback to module authors and potential users to identify bugs or platform compatibility issues and improves the overall quality and value of CPAN. One way you can contribute is to send test results for each module that you install. If you install the CPAN::Reporter module, you have the option to automatically generate and deliver test reports to CPAN Testers whenever you run tests on a CPAN package. See the CPAN::Reporter documentation for additional details and configuration settings. If your firewall blocks outgoing traffic, you may need to configure CPAN::Reporter before sending reports. Generate test reports if CPAN::Reporter is installed (yes/no)? =item perl5lib_verbosity When CPAN.pm extends @INC via PERL5LIB, it prints a list of directories added (or a summary of how many directories are added). Choose 'v' to get this message, 'none' to suppress it. Verbosity level for PERL5LIB changes (none or v)? =item prefer_external_tar Per default all untar operations are done with the perl module Archive::Tar; by setting this variable to true the external tar command is used if available; on Unix this is usually preferred because they have a reliable and fast gnutar implementation. Use the external tar program instead of Archive::Tar? =item trust_test_report_history When a distribution has already been tested by CPAN::Reporter on this machine, CPAN can skip the test phase and just rely on the test report history instead. Note that this will not apply to distributions that failed tests because of missing dependencies. Also, tests can be run regardless of the history using "force". Do you want to rely on the test report history (yes/no)? =item urllist_ping_external When automatic selection of the nearest cpan mirrors is performed, turn on the use of the external ping via Net::Ping::External. This is recommended in the case the local network has a transparent proxy. Do you want to use the external ping command when autoselecting mirrors? =item urllist_ping_verbose When automatic selection of the nearest cpan mirrors is performed, this option can be used to turn on verbosity during the selection process. Do you want to see verbosity turned on when autoselecting mirrors? =item use_prompt_default When this is true, CPAN will set PERL_MM_USE_DEFAULT to a true value. This causes ExtUtils::MakeMaker (and compatible) prompts to use default values instead of stopping to prompt you to answer questions. It also sets NONINTERACTIVE_TESTING to a true value to signal more generally that distributions should not try to interact with you. Do you want to use prompt defaults (yes/no)? =item use_sqlite CPAN::SQLite is a layer between the index files that are downloaded from the CPAN and CPAN.pm that speeds up metadata queries and reduces memory consumption of CPAN.pm considerably. Use CPAN::SQLite if available? (yes/no)? =item version_timeout This timeout prevents CPAN from hanging when trying to parse a pathologically coded $VERSION from a module. The default is 15 seconds. If you set this value to 0, no timeout will occur, but this is not recommended. Timeout for parsing module versions? =item yaml_load_code Both YAML.pm and YAML::Syck are capable of deserialising code. As this requires a string eval, which might be a security risk, you can use this option to enable or disable the deserialisation of code via CPAN::DeferredCode. (Note: This does not work under perl 5.6) Do you want to enable code deserialisation (yes/no)? =item yaml_module At the time of this writing (2009-03) there are three YAML implementations working: YAML, YAML::Syck, and YAML::XS. The latter two are faster but need a C compiler installed on your system. There may be more alternative YAML conforming modules. When I tried two other players, YAML::Tiny and YAML::Perl, they seemed not powerful enough to work with CPAN.pm. This may have changed in the meantime. Which YAML implementation would you prefer? =back =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut use vars qw( %prompts ); { my @prompts = ( auto_config => qq{ CPAN.pm requires configuration, but most of it can be done automatically. If you answer 'no' below, you will enter an interactive dialog for each configuration option instead. Would you like to configure as much as possible automatically?}, auto_pick => qq{ Would you like me to automatically choose some CPAN mirror sites for you? (This means connecting to the Internet)}, config_intro => qq{ The following questions are intended to help you with the configuration. The CPAN module needs a directory of its own to cache important index files and maybe keep a temporary mirror of CPAN files. This may be a site-wide or a personal directory. }, # cpan_home => qq{ }, cpan_home_where => qq{ First of all, I'd like to create this directory. Where? }, external_progs => qq{ The CPAN module will need a few external programs to work properly. Please correct me, if I guess the wrong path for a program. Don't panic if you do not have some of them, just press ENTER for those. To disable the use of a program, you can type a space followed by ENTER. }, proxy_intro => qq{ If you're accessing the net via proxies, you can specify them in the CPAN configuration or via environment variables. The variable in the \$CPAN::Config takes precedence. }, proxy_user => qq{ If your proxy is an authenticating proxy, you can store your username permanently. If you do not want that, just press ENTER. You will then be asked for your username in every future session. }, proxy_pass => qq{ Your password for the authenticating proxy can also be stored permanently on disk. If this violates your security policy, just press ENTER. You will then be asked for the password in every future session. }, urls_intro => qq{ Now you need to choose your CPAN mirror sites. You can let me pick mirrors for you, you can select them from a list or you can enter them by hand. }, urls_picker_intro => qq{First, pick a nearby continent and country by typing in the number(s) in front of the item(s) you want to select. You can pick several of each, separated by spaces. Then, you will be presented with a list of URLs of CPAN mirrors in the countries you selected, along with previously selected URLs. Select some of those URLs, or just keep the old list. Finally, you will be prompted for any extra URLs -- file:, ftp:, or http: -- that host a CPAN mirror. You should select more than one (just in case the first isn't available). }, password_warn => qq{ Warning: Term::ReadKey seems not to be available, your password will be echoed to the terminal! }, install_help => qq{ Warning: You do not have write permission for Perl library directories. To install modules, you need to configure a local Perl library directory or escalate your privileges. CPAN can help you by bootstrapping the local::lib module or by configuring itself to use 'sudo' (if available). You may also resolve this problem manually if you need to customize your setup. What approach do you want? (Choose 'local::lib', 'sudo' or 'manual') }, local_lib_installed => qq{ local::lib is installed. You must now add the following environment variables to your shell configuration files (or registry, if you are on Windows) and then restart your command line shell and CPAN before installing modules: }, ); die "Coding error in \@prompts declaration. Odd number of elements, above" if (@prompts % 2); %prompts = @prompts; if (scalar(keys %prompts) != scalar(@prompts)/2) { my %already; for my $item (0..$#prompts) { next if $item % 2; die "$prompts[$item] is duplicated\n" if $already{$prompts[$item]}++; } } shift @podpara; while (@podpara) { warn "Alert: cannot parse my own manpage for init dialog" unless $podpara[0] =~ s/^=item\s+//; my $name = shift @podpara; my @para; while (@podpara && $podpara[0] !~ /^=item/) { push @para, shift @podpara; } $prompts{$name} = pop @para; if (@para) { $prompts{$name . "_intro"} = join "", map { "$_\n\n" } @para; } } } sub init { my($configpm, %args) = @_; use Config; # extra args after 'o conf init' my $matcher = $args{args} && @{$args{args}} ? $args{args}[0] : ''; if ($matcher =~ /^\/(.*)\/$/) { # case /regex/ => take the first, ignore the rest $matcher = $1; shift @{$args{args}}; if (@{$args{args}}) { local $" = " "; $CPAN::Frontend->mywarn("Ignoring excessive arguments '@{$args{args}}'"); $CPAN::Frontend->mysleep(2); } } elsif (0 == length $matcher) { } elsif (0 && $matcher eq "~") { # extremely buggy, but a nice idea my @unconfigured = sort grep { not exists $CPAN::Config->{$_} or not defined $CPAN::Config->{$_} or not length $CPAN::Config->{$_} } keys %$CPAN::Config; $matcher = "\\b(".join("|", @unconfigured).")\\b"; $CPAN::Frontend->mywarn("matcher[$matcher]"); } else { # case WORD... => all arguments must be valid for my $arg (@{$args{args}}) { unless (exists $CPAN::HandleConfig::keys{$arg}) { $CPAN::Frontend->mywarn("'$arg' is not a valid configuration variable\n"); return; } } $matcher = "\\b(".join("|",@{$args{args}}).")\\b"; } CPAN->debug("matcher[$matcher]") if $CPAN::DEBUG; unless ($CPAN::VERSION) { require CPAN::Nox; } require CPAN::HandleConfig; CPAN::HandleConfig::require_myconfig_or_config(); $CPAN::Config ||= {}; local($/) = "\n"; local($\) = ""; local($|) = 1; my($ans,$default); # why so half global? # #= Files, directories # local *_real_prompt; if ( $args{autoconfig} ) { $auto_config = 1; } elsif ($matcher) { $auto_config = 0; } else { my $_conf = prompt($prompts{auto_config}, "yes"); $auto_config = ($_conf and $_conf =~ /^y/i) ? 1 : 0; } CPAN->debug("auto_config[$auto_config]") if $CPAN::DEBUG; if ( $auto_config ) { local $^W = 0; # prototype should match that of &MakeMaker::prompt my $current_second = time; my $current_second_count = 0; my $i_am_mad = 0; # silent prompting -- just quietly use default *_real_prompt = sub { return $_[1] }; } # # bootstrap local::lib or sudo # unless ( $matcher || _can_write_to_libdirs() || _using_installbase() || _using_sudo() ) { local $auto_config = 0; # We *must* ask, even under autoconfig local *_real_prompt; # We *must* show prompt my_prompt_loop(install_help => 'local::lib', $matcher, 'local::lib|sudo|manual'); } $CPAN::Config->{install_help} ||= ''; # Temporary to suppress warnings if (!$matcher or q{ build_dir build_dir_reuse cpan_home keep_source_where prefs_dir } =~ /$matcher/) { $CPAN::Frontend->myprint($prompts{config_intro}) unless $auto_config; init_cpan_home($matcher); my_dflt_prompt("keep_source_where", File::Spec->catdir($CPAN::Config->{cpan_home},"sources"), $matcher, ); my_dflt_prompt("build_dir", File::Spec->catdir($CPAN::Config->{cpan_home},"build"), $matcher ); my_yn_prompt(build_dir_reuse => 0, $matcher); my_dflt_prompt("prefs_dir", File::Spec->catdir($CPAN::Config->{cpan_home},"prefs"), $matcher ); } # #= Config: auto_commit # my_yn_prompt(auto_commit => 0, $matcher); # #= Cache size, Index expire # my_dflt_prompt(build_cache => 100, $matcher); my_dflt_prompt(index_expire => 1, $matcher); my_prompt_loop(scan_cache => 'atstart', $matcher, 'atstart|atexit|never'); my_yn_prompt(cleanup_after_install => 0, $matcher); # #= cache_metadata # my_yn_prompt(cache_metadata => 1, $matcher); my_yn_prompt(use_sqlite => 0, $matcher); # #= Do we follow PREREQ_PM? # my_prompt_loop(prerequisites_policy => 'follow', $matcher, 'follow|ask|ignore'); my_prompt_loop(build_requires_install_policy => 'yes', $matcher, 'yes|no|ask/yes|ask/no'); my_yn_prompt(recommends_policy => 1, $matcher); my_yn_prompt(suggests_policy => 0, $matcher); # #= Module::Signature # my_yn_prompt(check_sigs => 0, $matcher); # #= CPAN::Reporter # if (!$matcher or 'test_report' =~ /$matcher/) { my_yn_prompt(test_report => 0, $matcher); if ( $matcher && $CPAN::Config->{test_report} && $CPAN::META->has_inst("CPAN::Reporter") && CPAN::Reporter->can('configure') ) { my $_conf = prompt("Would you like me configure CPAN::Reporter now?", "yes"); if ($_conf =~ /^y/i) { $CPAN::Frontend->myprint("\nProceeding to configure CPAN::Reporter.\n"); CPAN::Reporter::configure(); $CPAN::Frontend->myprint("\nReturning to CPAN configuration.\n"); } } } my_yn_prompt(trust_test_report_history => 0, $matcher); # #= YAML vs. YAML::Syck # if (!$matcher or "yaml_module" =~ /$matcher/) { my_dflt_prompt(yaml_module => "YAML", $matcher); my $old_v = $CPAN::Config->{load_module_verbosity}; $CPAN::Config->{load_module_verbosity} = q[none]; if (!$auto_config && !$CPAN::META->has_inst($CPAN::Config->{yaml_module})) { $CPAN::Frontend->mywarn ("Warning (maybe harmless): '$CPAN::Config->{yaml_module}' not installed.\n"); $CPAN::Frontend->mysleep(3); } $CPAN::Config->{load_module_verbosity} = $old_v; } # #= YAML code deserialisation # my_yn_prompt(yaml_load_code => 0, $matcher); # #= External programs # my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'}; $CPAN::Frontend->myprint($prompts{external_progs}) if !$matcher && !$auto_config; _init_external_progs($matcher, { path => \@path, progs => [ qw/make bzip2 gzip tar unzip gpg patch applypatch/ ], shortcut => 0 }); _init_external_progs($matcher, { path => \@path, progs => [ qw/wget curl lynx ncftpget ncftp ftp/ ], shortcut => 1 }); { my $path = $CPAN::Config->{'pager'} || $ENV{PAGER} || find_exe("less",\@path) || find_exe("more",\@path) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 ) || "more"; my_dflt_prompt(pager => $path, $matcher); } { my $path = $CPAN::Config->{'shell'}; if ($path && File::Spec->file_name_is_absolute($path)) { $CPAN::Frontend->mywarn("Warning: configured $path does not exist\n") unless -e $path; $path = ""; } $path ||= $ENV{SHELL}; $path ||= $ENV{COMSPEC} if $^O eq "MSWin32"; if ($^O eq 'MacOS') { $CPAN::Config->{'shell'} = 'not_here'; } else { $path ||= 'sh', $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only my_dflt_prompt(shell => $path, $matcher); } } { my $tar = $CPAN::Config->{tar}; my $prefer_external_tar = $CPAN::Config->{prefer_external_tar}; # XXX not yet supported unless (defined $prefer_external_tar) { if ($^O =~ /(MSWin32|solaris)/) { # both have a record of broken tars $prefer_external_tar = 0; } elsif ($tar) { $prefer_external_tar = 1; } else { $prefer_external_tar = 0; } } my_yn_prompt(prefer_external_tar => $prefer_external_tar, $matcher); } # # verbosity # my_prompt_loop(tar_verbosity => 'none', $matcher, 'none|v|vv'); my_prompt_loop(load_module_verbosity => 'none', $matcher, 'none|v'); my_prompt_loop(perl5lib_verbosity => 'none', $matcher, 'none|v'); my_yn_prompt(inhibit_startup_message => 0, $matcher); # #= Installer, arguments to make etc. # my_prompt_loop(prefer_installer => 'MB', $matcher, 'MB|EUMM|RAND'); if (!$matcher or 'makepl_arg make_arg' =~ /$matcher/) { my_dflt_prompt(makepl_arg => "", $matcher); my_dflt_prompt(make_arg => "", $matcher); if ( $CPAN::Config->{makepl_arg} =~ /LIBS=|INC=/ ) { $CPAN::Frontend->mywarn( "Warning: Using LIBS or INC in makepl_arg will likely break distributions\n" . "that specify their own LIBS or INC options in Makefile.PL.\n" ); } } require CPAN::HandleConfig; if (exists $CPAN::HandleConfig::keys{make_install_make_command}) { # as long as Windows needs $self->_build_command, we cannot # support sudo on windows :-) my $default = $CPAN::Config->{make} || ""; if ( $default && $CPAN::Config->{install_help} eq 'sudo' ) { if ( find_exe('sudo') ) { $default = "sudo $default"; delete $CPAN::Config->{make_install_make_command} unless $CPAN::Config->{make_install_make_command} =~ /sudo/; } else { $CPAN::Frontend->mywarnonce("Could not find 'sudo' in PATH\n"); } } my_dflt_prompt(make_install_make_command => $default, $matcher); } my_dflt_prompt(make_install_arg => $CPAN::Config->{make_arg} || "", $matcher); my_dflt_prompt(mbuildpl_arg => "", $matcher); my_dflt_prompt(mbuild_arg => "", $matcher); if (exists $CPAN::HandleConfig::keys{mbuild_install_build_command} and $^O ne "MSWin32") { # as long as Windows needs $self->_build_command, we cannot # support sudo on windows :-) my $default = $^O eq 'VMS' ? '@Build.com' : "./Build"; if ( $CPAN::Config->{install_help} eq 'sudo' ) { if ( find_exe('sudo') ) { $default = "sudo $default"; delete $CPAN::Config->{mbuild_install_build_command} unless $CPAN::Config->{mbuild_install_build_command} =~ /sudo/; } else { $CPAN::Frontend->mywarnonce("Could not find 'sudo' in PATH\n"); } } my_dflt_prompt(mbuild_install_build_command => $default, $matcher); } my_dflt_prompt(mbuild_install_arg => "", $matcher); for my $o (qw( allow_installing_outdated_dists allow_installing_module_downgrades )) { my_prompt_loop($o => 'ask/no', $matcher, 'yes|no|ask/yes|ask/no'); } # #== use_prompt_default # my_yn_prompt(use_prompt_default => 0, $matcher); # #= Alarm period # my_dflt_prompt(inactivity_timeout => 0, $matcher); my_dflt_prompt(version_timeout => 15, $matcher); # #== halt_on_failure # my_yn_prompt(halt_on_failure => 0, $matcher); # #= Proxies # my @proxy_vars = qw/ftp_proxy http_proxy no_proxy/; my @proxy_user_vars = qw/proxy_user proxy_pass/; if (!$matcher or "@proxy_vars @proxy_user_vars" =~ /$matcher/) { $CPAN::Frontend->myprint($prompts{proxy_intro}) unless $auto_config; for (@proxy_vars) { $prompts{$_} = "Your $_?"; my_dflt_prompt($_ => $ENV{$_}||"", $matcher); } if ($CPAN::Config->{ftp_proxy} || $CPAN::Config->{http_proxy}) { $default = $CPAN::Config->{proxy_user} || $CPAN::LWP::UserAgent::USER || ""; $CPAN::Frontend->myprint($prompts{proxy_user}) unless $auto_config; if ($CPAN::Config->{proxy_user} = prompt("Your proxy user id?",$default)) { $CPAN::Frontend->myprint($prompts{proxy_pass}) unless $auto_config; if ($CPAN::META->has_inst("Term::ReadKey")) { Term::ReadKey::ReadMode("noecho"); } else { $CPAN::Frontend->myprint($prompts{password_warn}) unless $auto_config; } $CPAN::Config->{proxy_pass} = prompt_no_strip("Your proxy password?"); if ($CPAN::META->has_inst("Term::ReadKey")) { Term::ReadKey::ReadMode("restore"); } $CPAN::Frontend->myprint("\n\n") unless $auto_config; } } } # #= how plugins work # # XXX MISSING: my_array_prompt to be used with plugins. We did something like this near # git log -p fd68f8f5e33f4cecea4fdb7abc5ee19c12f138f0..test-notest-test-dependency # Need to do similar steps for plugin_list. As long as we do not support it here, people # must use the cpan shell prompt to write something like # o conf plugin_list push CPAN::Plugin::Specfile=dir,/tmp/foo-20141013,... # o conf commit # #= how FTP works # my_yn_prompt(ftp_passive => 1, $matcher); # #= how cwd works # my_prompt_loop(getcwd => 'cwd', $matcher, 'cwd|getcwd|fastcwd|getdcwd|backtickcwd'); # #= the CPAN shell itself (prompt, color) # my_yn_prompt(commandnumber_in_prompt => 1, $matcher); my_yn_prompt(term_ornaments => 1, $matcher); if ("colorize_output colorize_print colorize_warn colorize_debug" =~ $matcher) { my_yn_prompt(colorize_output => 0, $matcher); if ($CPAN::Config->{colorize_output}) { if ($CPAN::META->has_inst("Term::ANSIColor")) { my $T="gYw"; $CPAN::Frontend->myprint( " on_ on_y ". " on_ma on_\n") unless $auto_config; $CPAN::Frontend->myprint( " on_black on_red green ellow ". "on_blue genta on_cyan white\n") unless $auto_config; for my $FG ("", "bold", map {$_,"bold $_"} "black","red","green", "yellow","blue", "magenta", "cyan","white") { $CPAN::Frontend->myprint(sprintf( "%12s ", $FG)) unless $auto_config; for my $BG ("",map {"on_$_"} qw(black red green yellow blue magenta cyan white)) { $CPAN::Frontend->myprint( $FG||$BG ? Term::ANSIColor::colored(" $T ","$FG $BG") : " $T ") unless $auto_config; } $CPAN::Frontend->myprint( "\n" ) unless $auto_config; } $CPAN::Frontend->myprint( "\n" ) unless $auto_config; } for my $tuple ( ["colorize_print", "bold blue on_white"], ["colorize_warn", "bold red on_white"], ["colorize_debug", "black on_cyan"], ) { my_dflt_prompt($tuple->[0] => $tuple->[1], $matcher); if ($CPAN::META->has_inst("Term::ANSIColor")) { eval { Term::ANSIColor::color($CPAN::Config->{$tuple->[0]})}; if ($@) { $CPAN::Config->{$tuple->[0]} = $tuple->[1]; $CPAN::Frontend->mywarn($@."setting to default '$tuple->[1]'\n"); } } } } } # #== term_is_latin # my_yn_prompt(term_is_latin => 1, $matcher); # #== save history in file 'histfile' # if (!$matcher or 'histfile histsize' =~ /$matcher/) { $CPAN::Frontend->myprint($prompts{histfile_intro}) unless $auto_config; defined($default = $CPAN::Config->{histfile}) or $default = File::Spec->catfile($CPAN::Config->{cpan_home},"histfile"); my_dflt_prompt(histfile => $default, $matcher); if ($CPAN::Config->{histfile}) { defined($default = $CPAN::Config->{histsize}) or $default = 100; my_dflt_prompt(histsize => $default, $matcher); } } # #== do an ls on the m or the d command # my_yn_prompt(show_upload_date => 0, $matcher); # #== verbosity at the end of the r command # if (!$matcher or 'show_unparsable_versions' =~ /$matcher/ or 'show_zero_versions' =~ /$matcher/ ) { my_yn_prompt(show_unparsable_versions => 0, $matcher); my_yn_prompt(show_zero_versions => 0, $matcher); } # #= MIRRORED.BY and conf_sites() # # Let's assume they want to use the internet and make them turn it # off if they really don't. my_yn_prompt("connect_to_internet_ok" => 1, $matcher); my_yn_prompt("pushy_https" => 1, $matcher); # Allow matching but don't show during manual config if ($matcher) { if ("urllist_ping_external" =~ $matcher) { my_yn_prompt(urllist_ping_external => 0, $matcher); } if ("urllist_ping_verbose" =~ $matcher) { my_yn_prompt(urllist_ping_verbose => 0, $matcher); } if ("randomize_urllist" =~ $matcher) { my_dflt_prompt(randomize_urllist => 0, $matcher); } if ("ftpstats_size" =~ $matcher) { my_dflt_prompt(ftpstats_size => 99, $matcher); } if ("ftpstats_period" =~ $matcher) { my_dflt_prompt(ftpstats_period => 14, $matcher); } } $CPAN::Config->{urllist} ||= []; if ($auto_config) { if(@{ $CPAN::Config->{urllist} }) { $CPAN::Frontend->myprint( "Your 'urllist' is already configured. Type 'o conf init urllist' to change it.\n" ); } else { # Hint: as of 2021-11: to get http, use http://www.cpan.org/ $CPAN::Config->{urllist} = [ 'https://cpan.org/' ]; $CPAN::Frontend->myprint( "We initialized your 'urllist' to @{$CPAN::Config->{urllist}}. Type 'o conf init urllist' to change it.\n" ); } } elsif (!$matcher || "urllist" =~ $matcher) { _do_pick_mirrors(); } if ($auto_config) { $CPAN::Frontend->myprint( "\nAutoconfiguration complete.\n" ); $auto_config = 0; # reset } # bootstrap local::lib now if requested if ( $CPAN::Config->{install_help} eq 'local::lib' ) { if ( ! @{ $CPAN::Config->{urllist} } ) { $CPAN::Frontend->myprint( "\nALERT: Skipping local::lib bootstrap because 'urllist' is not configured.\n" ); } elsif (! $CPAN::Config->{make} ) { $CPAN::Frontend->mywarn( "\nALERT: Skipping local::lib bootstrap because 'make' is not configured.\n" ); _beg_for_make(); # repetitive, but we don't want users to miss it } else { $CPAN::Frontend->myprint("\nAttempting to bootstrap local::lib...\n"); $CPAN::Frontend->myprint("\nWriting $configpm for bootstrap...\n"); delete $CPAN::Config->{install_help}; # temporary only CPAN::HandleConfig->commit; my($dist, $locallib); $locallib = CPAN::Shell->expand('Module', 'local::lib'); if ( $locallib and $dist = $locallib->distribution ) { # this is a hack to force bootstrapping $dist->{prefs}{pl}{commandline} = "$^X Makefile.PL --bootstrap"; # Set @INC for this process so we find things as they bootstrap require lib; lib->import(_local_lib_inc_path()); eval { $dist->install }; } if ( ! $dist || (my $err = $@) ) { $err ||= 'Could not locate local::lib in the CPAN index'; $CPAN::Frontend->mywarn("Error bootstrapping local::lib: $@\n"); $CPAN::Frontend->myprint("From the CPAN Shell, you might try 'look local::lib' and \n" . "run 'perl Makefile --bootstrap' and see if that is successful. Then\n" . "restart your CPAN client\n" ); } else { _local_lib_config(); } } } # install_help is temporary for configuration and not saved delete $CPAN::Config->{install_help}; $CPAN::Frontend->myprint("\n"); if ($matcher && !$CPAN::Config->{auto_commit}) { $CPAN::Frontend->myprint("Please remember to call 'o conf commit' to ". "make the config permanent!\n"); } else { CPAN::HandleConfig->commit; } if (! $matcher) { $CPAN::Frontend->myprint( "\nYou can re-run configuration any time with 'o conf init' in the CPAN shell\n" ); } } sub _local_lib_config { # Set environment stuff for this process require local::lib; # Tell user about environment vars to set $CPAN::Frontend->myprint($prompts{local_lib_installed}); local $ENV{SHELL} = $CPAN::Config->{shell} || $ENV{SHELL}; my $shellvars = local::lib->environment_vars_string_for(_local_lib_path()); $CPAN::Frontend->myprint($shellvars); # Set %ENV after getting string above my %env = local::lib->build_environment_vars_for(_local_lib_path(), 1); while ( my ($k, $v) = each %env ) { $ENV{$k} = $v; } # Offer to mangle the shell config my $munged_rc; if ( my $rc = _find_shell_config() ) { local $auto_config = 0; # We *must* ask, even under autoconfig local *_real_prompt; # We *must* show prompt my $_conf = prompt( "\nWould you like me to append that to $rc now?", "yes" ); if ($_conf =~ /^y/i) { open my $fh, ">>", $rc; print {$fh} "\n$shellvars"; close $fh; $munged_rc++; } } # Warn at exit time if ($munged_rc) { push @{$CPAN::META->_exit_messages}, << "HERE"; *** Remember to restart your shell before running cpan again *** HERE } else { push @{$CPAN::META->_exit_messages}, << "HERE"; *** Remember to add these environment variables to your shell config and restart your shell before running cpan again *** $shellvars HERE } } { my %shell_rc_map = ( map { $_ => ".${_}rc" } qw/ bash tcsh csh /, map { $_ => ".profile" } qw/dash ash sh/, zsh => ".zshenv", ); sub _find_shell_config { my $shell = File::Basename::basename($CPAN::Config->{shell}); if ( my $rc = $shell_rc_map{$shell} ) { my $path = File::Spec->catfile($ENV{HOME}, $rc); return $path if -w $path; } } } sub _local_lib_inc_path { return File::Spec->catdir(_local_lib_path(), qw/lib perl5/); } sub _local_lib_path { return File::Spec->catdir(_local_lib_home(), 'perl5'); } # Adapted from resolve_home_path() in local::lib -- this is where # local::lib thinks the user's home is { my $local_lib_home; sub _local_lib_home { $local_lib_home ||= File::Spec->rel2abs( do { if ($CPAN::META->has_usable("File::HomeDir") && File::HomeDir->VERSION >= 0.65) { File::HomeDir->my_home; } elsif (defined $ENV{HOME}) { $ENV{HOME}; } else { (getpwuid $<)[7] || "~"; } }); } } sub _do_pick_mirrors { local *_real_prompt; *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt; $CPAN::Frontend->myprint($prompts{urls_intro}); # Only prompt for auto-pick if Net::Ping is new enough to do timings my $_conf = 'n'; if ( $CPAN::META->has_usable("Net::Ping") && CPAN::Version->vgt(Net::Ping->VERSION, '2.13')) { $_conf = prompt($prompts{auto_pick}, "yes"); } else { prompt("Autoselection disabled due to Net::Ping missing or insufficient. Please press ENTER"); } my @old_list = @{ $CPAN::Config->{urllist} }; if ( $_conf =~ /^y/i ) { conf_sites( auto_pick => 1 ) or bring_your_own(); } else { _print_urllist('Current') if @old_list; my $msg = scalar @old_list ? "\nWould you like to edit the urllist or pick new mirrors from a list?" : "\nWould you like to pick from the CPAN mirror list?" ; my $_conf = prompt($msg, "yes"); if ( $_conf =~ /^y/i ) { conf_sites(); } bring_your_own(); } _print_urllist('New'); } sub _init_external_progs { my($matcher,$args) = @_; my $PATH = $args->{path}; my @external_progs = @{ $args->{progs} }; my $shortcut = $args->{shortcut}; my $showed_make_warning; if (!$matcher or "@external_progs" =~ /$matcher/) { my $old_warn = $^W; local $^W if $^O eq 'MacOS'; local $^W = $old_warn; my $progname; for $progname (@external_progs) { next if $matcher && $progname !~ /$matcher/; if ($^O eq 'MacOS') { $CPAN::Config->{$progname} = 'not_here'; next; } my $progcall = $progname; unless ($matcher) { # we really don't need ncftp if we have ncftpget, but # if they chose this dialog via matcher, they shall have it next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " "; } my $path = $CPAN::Config->{$progname} || $Config::Config{$progname} || ""; if (File::Spec->file_name_is_absolute($path)) { # testing existence is not good enough, some have these exe # extensions # warn "Warning: configured $path does not exist\n" unless -e $path; # $path = ""; } elsif ($path =~ /^\s+$/) { # preserve disabled programs } else { $path = ''; } unless ($path) { # e.g. make -> nmake $progcall = $Config::Config{$progname} if $Config::Config{$progname}; } $path ||= find_exe($progcall,$PATH); unless ($path) { # not -e $path, because find_exe already checked that local $"=";"; $CPAN::Frontend->mywarn("Warning: $progcall not found in PATH[@$PATH]\n") unless $auto_config; _beg_for_make(), $showed_make_warning++ if $progname eq "make"; } $prompts{$progname} = "Where is your $progname program?"; $path = my_dflt_prompt($progname,$path,$matcher,1); # 1 => no strip spaces my $disabling = $path =~ m/^\s*$/; # don't let them disable or misconfigure make without warning if ( $progname eq "make" && ( $disabling || ! _check_found($path) ) ) { if ( $disabling && $showed_make_warning ) { next; } else { _beg_for_make() unless $showed_make_warning++; undef $CPAN::Config->{$progname}; $CPAN::Frontend->mywarn("Press SPACE and ENTER to disable make (NOT RECOMMENDED)\n"); redo; } } elsif ( $disabling ) { next; } elsif ( _check_found( $CPAN::Config->{$progname} ) ) { last if $shortcut && !$matcher; } else { undef $CPAN::Config->{$progname}; $CPAN::Frontend->mywarn("Press SPACE and ENTER to disable $progname\n"); redo; } } } } sub _check_found { my ($prog) = @_; if ( ! -f $prog ) { $CPAN::Frontend->mywarn("Warning: '$prog' does not exist\n") unless $auto_config; return; } elsif ( ! -x $prog ) { $CPAN::Frontend->mywarn("Warning: '$prog' is not executable\n") unless $auto_config; return; } return 1; } sub _beg_for_make { $CPAN::Frontend->mywarn(<<"HERE"); ALERT: 'make' is an essential tool for building perl Modules. Please make sure you have 'make' (or some equivalent) working. HERE if ($^O eq "MSWin32") { $CPAN::Frontend->mywarn(<<"HERE"); Windows users may want to follow this procedure when back in the CPAN shell: look YVES/scripts/alien_nmake.pl perl alien_nmake.pl This will install nmake on your system which can be used as a 'make' substitute. HERE } $CPAN::Frontend->mywarn(<<"HERE"); You can then retry the 'make' configuration step with o conf init make HERE } sub init_cpan_home { my($matcher) = @_; if (!$matcher or 'cpan_home' =~ /$matcher/) { my $cpan_home = $CPAN::Config->{cpan_home} || CPAN::HandleConfig::cpan_home(); if (-d $cpan_home) { $CPAN::Frontend->myprint( "\nI see you already have a directory\n" . "\n$cpan_home\n" . "Shall we use it as the general CPAN build and cache directory?\n\n" ) unless $auto_config; } else { # no cpan-home, must prompt and get one $CPAN::Frontend->myprint($prompts{cpan_home_where}) unless $auto_config; } my $default = $cpan_home; my $loop = 0; my($last_ans,$ans); $CPAN::Frontend->myprint(" \n") unless $auto_config; PROMPT: while ($ans = prompt("CPAN build and cache directory?",$default)) { if (File::Spec->file_name_is_absolute($ans)) { my @cpan_home = split /[\/\\]/, $ans; DIR: for my $dir (@cpan_home) { if ($dir =~ /^~/ and (!$last_ans or $ans ne $last_ans)) { $CPAN::Frontend ->mywarn("Warning: a tilde in the path will be ". "taken as a literal tilde. Please ". "confirm again if you want to keep it\n"); $last_ans = $default = $ans; next PROMPT; } } } else { require Cwd; my $cwd = Cwd::cwd(); my $absans = File::Spec->catdir($cwd,$ans); $CPAN::Frontend->mywarn("The path '$ans' is not an ". "absolute path. Please specify ". "an absolute path\n"); $default = $absans; next PROMPT; } eval { File::Path::mkpath($ans); }; # dies if it can't if ($@) { $CPAN::Frontend->mywarn("Couldn't create directory $ans.\n". "Please retry.\n"); next PROMPT; } if (-d $ans && -w _) { last PROMPT; } else { $CPAN::Frontend->mywarn("Couldn't find directory $ans\n". "or directory is not writable. Please retry.\n"); if (++$loop > 5) { $CPAN::Frontend->mydie("Giving up"); } } } $CPAN::Config->{cpan_home} = $ans; } } sub my_dflt_prompt { my ($item, $dflt, $m, $no_strip) = @_; my $default = $CPAN::Config->{$item} || $dflt; if (!$auto_config && (!$m || $item =~ /$m/)) { if (my $intro = $prompts{$item . "_intro"}) { $CPAN::Frontend->myprint($intro); } $CPAN::Frontend->myprint(" <$item>\n"); $CPAN::Config->{$item} = $no_strip ? prompt_no_strip($prompts{$item}, $default) : prompt( $prompts{$item}, $default); } else { $CPAN::Config->{$item} = $default; } return $CPAN::Config->{$item}; } sub my_yn_prompt { my ($item, $dflt, $m) = @_; my $default; defined($default = $CPAN::Config->{$item}) or $default = $dflt; if (!$auto_config && (!$m || $item =~ /$m/)) { if (my $intro = $prompts{$item . "_intro"}) { $CPAN::Frontend->myprint($intro); } $CPAN::Frontend->myprint(" <$item>\n"); my $ans = prompt($prompts{$item}, $default ? 'yes' : 'no'); $CPAN::Config->{$item} = ($ans =~ /^[y1]/i ? 1 : 0); } else { $CPAN::Config->{$item} = $default; } } sub my_prompt_loop { my ($item, $dflt, $m, $ok) = @_; my $default = $CPAN::Config->{$item} || $dflt; my $ans; if (!$auto_config && (!$m || $item =~ /$m/)) { my $intro = $prompts{$item . "_intro"}; $CPAN::Frontend->myprint($intro) if defined $intro; $CPAN::Frontend->myprint(" <$item>\n"); do { $ans = prompt($prompts{$item}, $default); } until $ans =~ /$ok/; $CPAN::Config->{$item} = $ans; } else { $CPAN::Config->{$item} = $default; } } # Here's the logic about the MIRRORED.BY file. There are a number of scenarios: # (1) We have a cached MIRRORED.BY file # (1a) We're auto-picking # - Refresh it automatically if it's old # (1b) Otherwise, ask if using cached is ok. If old, default to no. # - If cached is not ok, get it from the Internet. If it succeeds we use # the new file. Otherwise, we use the old file. # (2) We don't have a copy at all # (2a) If we are allowed to connect, we try to get a new copy. If it succeeds, # we use it, otherwise, we warn about failure # (2b) If we aren't allowed to connect, sub conf_sites { my %args = @_; # auto pick implies using the internet $CPAN::Config->{connect_to_internet_ok} = 1 if $args{auto_pick}; my $m = 'MIRRORED.BY'; my $mby = File::Spec->catfile($CPAN::Config->{keep_source_where},$m); File::Path::mkpath(File::Basename::dirname($mby)); # Why are we using MIRRORED.BY from the current directory? # Is this for testing? -- dagolden, 2009-11-05 if (-f $mby && -f $m && -M $m < -M $mby) { require File::Copy; File::Copy::copy($m,$mby) or die "Could not update $mby: $!"; } local $^T = time; # if we have a cached copy is not older than 60 days, we either # use it or refresh it or fall back to it if the refresh failed. if ($mby && -f $mby && -s _ > 0 ) { my $very_old = (-M $mby > 60); my $mtime = localtime((stat _)[9]); # if auto_pick, refresh anything old automatically if ( $args{auto_pick} ) { if ( $very_old ) { $CPAN::Frontend->myprint(qq{Trying to refresh your mirror list\n}); eval { CPAN::FTP->localize($m,$mby,3,1) } or $CPAN::Frontend->myprint(qq{Refresh failed. Using the old cached copy instead.\n}); $CPAN::Frontend->myprint("\n"); } } else { my $prompt = qq{Found a cached mirror list as of $mtime If you'd like to just use the cached copy, answer 'yes', below. If you'd like an updated copy of the mirror list, answer 'no' and I'll get a fresh one from the Internet. Shall I use the cached mirror list?}; my $ans = prompt($prompt, $very_old ? "no" : "yes"); if ($ans =~ /^n/i) { $CPAN::Frontend->myprint(qq{Trying to refresh your mirror list\n}); # you asked for it from the Internet $CPAN::Config->{connect_to_internet_ok} = 1; eval { CPAN::FTP->localize($m,$mby,3,1) } or $CPAN::Frontend->myprint(qq{Refresh failed. Using the old cached copy instead.\n}); $CPAN::Frontend->myprint("\n"); } } } # else there is no cached copy and we must fetch or fail else { # If they haven't agree to connect to the internet, ask again if ( ! $CPAN::Config->{connect_to_internet_ok} ) { my $prompt = q{You are missing a copy of the CPAN mirror list. May I connect to the Internet to get it?}; my $ans = prompt($prompt, "yes"); if ($ans =~ /^y/i) { $CPAN::Config->{connect_to_internet_ok} = 1; } } # Now get it from the Internet or complain if ( $CPAN::Config->{connect_to_internet_ok} ) { $CPAN::Frontend->myprint(qq{Trying to fetch a mirror list from the Internet\n}); eval { CPAN::FTP->localize($m,$mby,3,1) } or $CPAN::Frontend->mywarn(<<'HERE'); We failed to get a copy of the mirror list from the Internet. You will need to provide CPAN mirror URLs yourself. HERE $CPAN::Frontend->myprint("\n"); } else { $CPAN::Frontend->mywarn(<<'HERE'); You will need to provide CPAN mirror URLs yourself or set 'o conf connect_to_internet_ok 1' and try again. HERE } } # if we finally have a good local MIRRORED.BY, get on with picking if (-f $mby && -s _ > 0){ $CPAN::Config->{urllist} = $args{auto_pick} ? auto_mirrored_by($mby) : choose_mirrored_by($mby); return 1; } return; } sub find_exe { my($exe,$path) = @_; $path ||= [split /$Config{'path_sep'}/, $ENV{'PATH'}]; my($dir); #warn "in find_exe exe[$exe] path[@$path]"; for $dir (@$path) { my $abs = File::Spec->catfile($dir,$exe); if (($abs = MM->maybe_command($abs))) { return $abs; } } } sub picklist { my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_; CPAN->debug("picklist('$items','$prompt','$default','$require_nonempty',". "'$empty_warning')") if $CPAN::DEBUG; $default ||= ''; my $pos = 0; my @nums; SELECTION: while (1) { # display, at most, 15 items at a time my $limit = $#{ $items } - $pos; $limit = 15 if $limit > 15; # show the next $limit items, get the new position $pos = display_some($items, $limit, $pos, $default); $pos = 0 if $pos >= @$items; my $num = prompt($prompt,$default); @nums = split (' ', $num); { my %seen; @nums = grep { !$seen{$_}++ } @nums; } my $i = scalar @$items; unrangify(\@nums); if (0 == @nums) { # cannot allow nothing because nothing means paging! # return; } elsif (grep (/\D/ || $_ < 1 || $_ > $i, @nums)) { $CPAN::Frontend->mywarn("invalid items entered, try again\n"); if ("@nums" =~ /\D/) { $CPAN::Frontend->mywarn("(we are expecting only numbers between 1 and $i)\n"); } next SELECTION; } if ($require_nonempty && !@nums) { $CPAN::Frontend->mywarn("$empty_warning\n"); } # a blank line continues... unless (@nums){ $CPAN::Frontend->mysleep(0.1); # prevent hot spinning process on the next bug next SELECTION; } last; } for (@nums) { $_-- } @{$items}[@nums]; } sub unrangify ($) { my($nums) = $_[0]; my @nums2 = (); while (@{$nums||[]}) { my $n = shift @$nums; if ($n =~ /^(\d+)-(\d+)$/) { my @range = $1 .. $2; # warn "range[@range]"; push @nums2, @range; } else { push @nums2, $n; } } push @$nums, @nums2; } sub display_some { my ($items, $limit, $pos, $default) = @_; $pos ||= 0; my @displayable = @$items[$pos .. ($pos + $limit)]; for my $item (@displayable) { $CPAN::Frontend->myprint(sprintf "(%d) %s\n", ++$pos, $item); } my $hit_what = $default ? "SPACE ENTER" : "ENTER"; $CPAN::Frontend->myprint(sprintf("%d more items, hit %s to show them\n", (@$items - $pos), $hit_what, )) if $pos < @$items; return $pos; } sub auto_mirrored_by { my $local = shift or return; local $|=1; $CPAN::Frontend->myprint("Looking for CPAN mirrors near you (please be patient)\n"); my $mirrors = CPAN::Mirrors->new($local); my $cnt = 0; my $callback_was_active = 0; my @best = $mirrors->best_mirrors( how_many => 3, callback => sub { $callback_was_active++; $CPAN::Frontend->myprint("."); if ($cnt++>60) { $cnt=0; $CPAN::Frontend->myprint("\n"); } }, $CPAN::Config->{urllist_ping_external} ? (external_ping => 1) : (), $CPAN::Config->{urllist_ping_verbose} ? (verbose => 1) : (), ); my $urllist = [ map { $_->http } grep { $_ && ref $_ && $_->can('http') } @best ]; push @$urllist, grep { /^file:/ } @{$CPAN::Config->{urllist}}; $CPAN::Frontend->myprint(" done!\n\n") if $callback_was_active; return $urllist } sub choose_mirrored_by { my $local = shift or return; my ($default); my $mirrors = CPAN::Mirrors->new($local); my @previous_urls = @{$CPAN::Config->{urllist}}; $CPAN::Frontend->myprint($prompts{urls_picker_intro}); my (@cont, $cont, %cont, @countries, @urls, %seen); my $no_previous_warn = "Sorry! since you don't have any existing picks, you must make a\n" . "geographic selection."; my $offer_cont = [sort $mirrors->continents]; if (@previous_urls) { push @$offer_cont, "(edit previous picks)"; $default = @$offer_cont; } else { # cannot allow nothing because nothing means paging! # push @$offer_cont, "(none of the above)"; } @cont = picklist($offer_cont, "Select your continent (or several nearby continents)", $default, ! @previous_urls, $no_previous_warn); # cannot allow nothing because nothing means paging! # return unless @cont; foreach $cont (@cont) { my @c = sort $mirrors->countries($cont); @cont{@c} = map ($cont, 0..$#c); @c = map ("$_ ($cont)", @c) if @cont > 1; push (@countries, @c); } if (@previous_urls && @countries) { push @countries, "(edit previous picks)"; $default = @countries; } if (@countries) { @countries = picklist (\@countries, "Select your country (or several nearby countries)", $default, ! @previous_urls, $no_previous_warn); %seen = map (($_ => 1), @previous_urls); # hmmm, should take list of defaults from CPAN::Config->{'urllist'}... foreach my $country (@countries) { next if $country =~ /edit previous picks/; (my $bare_country = $country) =~ s/ \(.*\)//; my @u; for my $m ( $mirrors->mirrors($bare_country) ) { push @u, $m->ftp if $m->ftp; push @u, $m->http if $m->http; } @u = grep (! $seen{$_}, @u); @u = map ("$_ ($bare_country)", @u) if @countries > 1; push (@urls, sort @u); } } push (@urls, map ("$_ (previous pick)", @previous_urls)); my $prompt = "Select as many URLs as you like (by number), put them on one line, separated by blanks, hyphenated ranges allowed e.g. '1 4 5' or '7 1-4 8'"; if (@previous_urls) { $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) .. (scalar @urls)); $prompt .= "\n(or just hit ENTER to keep your previous picks)"; } @urls = picklist (\@urls, $prompt, $default); foreach (@urls) { s/ \(.*\)//; } return [ @urls ]; } sub bring_your_own { my $urllist = [ @{$CPAN::Config->{urllist}} ]; my %seen = map (($_ => 1), @$urllist); my($ans,@urls); my $eacnt = 0; # empty answers $CPAN::Frontend->myprint(<<'HERE'); Now you can enter your own CPAN URLs by hand. A local CPAN mirror can be listed using a 'file:' URL like 'file:///path/to/cpan/' HERE do { my $prompt = "Enter another URL or ENTER to quit:"; unless (%seen) { $prompt = qq{CPAN.pm needs at least one URL where it can fetch CPAN files from. Please enter your CPAN site:}; } $ans = prompt ($prompt, ""); if ($ans) { $ans =~ s|/?\z|/|; # has to end with one slash # XXX This manipulation is odd. Shouldn't we check that $ans is # a directory before converting to file:///? And we need /// below, # too, don't we? -- dagolden, 2009-11-05 $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file: if ($ans =~ /^\w+:\/./) { push @urls, $ans unless $seen{$ans}++; } else { $CPAN::Frontend-> myprint(sprintf(qq{"%s" doesn\'t look like an URL at first sight. I\'ll ignore it for now. You can add it to your %s later if you\'re sure it\'s right.\n}, $ans, $INC{'CPAN/MyConfig.pm'} || $INC{'CPAN/Config.pm'} || "configuration file", )); } } else { if (++$eacnt >= 5) { $CPAN::Frontend-> mywarn("Giving up.\n"); $CPAN::Frontend->mysleep(5); return; } } } while $ans || !%seen; @$urllist = CPAN::_uniq(@$urllist, @urls); $CPAN::Config->{urllist} = $urllist; } sub _print_urllist { my ($which) = @_; $CPAN::Frontend->myprint("$which urllist\n"); for ( @{$CPAN::Config->{urllist} || []} ) { $CPAN::Frontend->myprint(" $_\n") }; } sub _can_write_to_libdirs { return -w $Config{installprivlib} && -w $Config{installarchlib} && -w $Config{installsitelib} && -w $Config{installsitearch} } sub _using_installbase { return 1 if $ENV{PERL_MM_OPT} && $ENV{PERL_MM_OPT} =~ /install_base/i; return 1 if grep { ($CPAN::Config->{$_}||q{}) =~ /install_base/i } qw(makepl_arg make_install_arg mbuildpl_arg mbuild_install_arg); return; } sub _using_sudo { return 1 if grep { ($CPAN::Config->{$_}||q{}) =~ /sudo/ } qw(make_install_make_command mbuild_install_build_command); return; } sub _strip_spaces { $_[0] =~ s/^\s+//; # no leading spaces $_[0] =~ s/\s+\z//; # no trailing spaces } sub prompt ($;$) { unless (defined &_real_prompt) { *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt; } my $ans = _real_prompt(@_); _strip_spaces($ans); $CPAN::Frontend->myprint("\n") unless $auto_config; return $ans; } sub prompt_no_strip ($;$) { unless (defined &_real_prompt) { *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt; } return _real_prompt(@_); } 1; perl5/CPAN/Module.pm000044400000053566152530123070010112 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Module; use strict; @CPAN::Module::ISA = qw(CPAN::InfoObj); use vars qw( $VERSION ); $VERSION = "5.5003"; BEGIN { # alarm() is not implemented in perl 5.6.x and earlier under Windows *ALARM_IMPLEMENTED = sub () { $] >= 5.007 || $^O !~ /MSWin/ }; } # Accessors #-> sub CPAN::Module::userid sub userid { my $self = shift; my $ro = $self->ro; return unless $ro; return $ro->{userid} || $ro->{CPAN_USERID}; } #-> sub CPAN::Module::description sub description { my $self = shift; my $ro = $self->ro or return ""; $ro->{description} } #-> sub CPAN::Module::distribution sub distribution { my($self) = @_; CPAN::Shell->expand("Distribution",$self->cpan_file); } #-> sub CPAN::Module::_is_representative_module sub _is_representative_module { my($self) = @_; return $self->{_is_representative_module} if defined $self->{_is_representative_module}; my $pm = $self->cpan_file or return $self->{_is_representative_module} = 0; $pm =~ s|.+/||; $pm =~ s{\.(?:tar\.(bz2|gz|Z)|t(?:gz|bz)|zip)$}{}i; # see base_id $pm =~ s|-\d+\.\d+.+$||; $pm =~ s|-[\d\.]+$||; $pm =~ s/-/::/g; $self->{_is_representative_module} = $pm eq $self->{ID} ? 1 : 0; # warn "DEBUG: $pm eq $self->{ID} => $self->{_is_representative_module}"; $self->{_is_representative_module}; } #-> sub CPAN::Module::undelay sub undelay { my $self = shift; delete $self->{later}; if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) { $dist->undelay; } } # mark as dirty/clean #-> sub CPAN::Module::color_cmd_tmps ; sub color_cmd_tmps { my($self) = shift; my($depth) = shift || 0; my($color) = shift || 0; my($ancestors) = shift || []; # a module needs to recurse to its cpan_file return if exists $self->{incommandcolor} && $color==1 && $self->{incommandcolor}==$color; return if $color==0 && !$self->{incommandcolor}; if ($color>=1) { if ( $self->uptodate ) { $self->{incommandcolor} = $color; return; } elsif (my $have_version = $self->available_version) { # maybe what we have is good enough if (@$ancestors) { my $who_asked_for_me = $ancestors->[-1]; my $obj = CPAN::Shell->expandany($who_asked_for_me); if (0) { } elsif ($obj->isa("CPAN::Bundle")) { # bundles cannot specify a minimum version return; } elsif ($obj->isa("CPAN::Distribution")) { if (my $prereq_pm = $obj->prereq_pm) { for my $k (keys %$prereq_pm) { if (my $want_version = $prereq_pm->{$k}{$self->id}) { if (CPAN::Version->vcmp($have_version,$want_version) >= 0) { $self->{incommandcolor} = $color; return; } } } } } } } } else { $self->{incommandcolor} = $color; # set me before recursion, # so we can break it } if ($depth>=$CPAN::MAX_RECURSION) { my $e = CPAN::Exception::RecursiveDependency->new($ancestors); if ($e->is_resolvable) { return $self->{incommandcolor}=2; } else { die $e; } } # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) { $dist->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); } # unreached code? # if ($color==0) { # delete $self->{badtestcnt}; # } $self->{incommandcolor} = $color; } #-> sub CPAN::Module::as_glimpse ; sub as_glimpse { my($self) = @_; my(@m); my $class = ref($self); $class =~ s/^CPAN:://; my $color_on = ""; my $color_off = ""; if ( $CPAN::Shell::COLOR_REGISTERED && $CPAN::META->has_inst("Term::ANSIColor") && $self->description ) { $color_on = Term::ANSIColor::color("green"); $color_off = Term::ANSIColor::color("reset"); } my $uptodateness = " "; unless ($class eq "Bundle") { my $u = $self->uptodate; $uptodateness = $u ? "=" : "<" if defined $u; }; my $id = do { my $d = $self->distribution; $d ? $d -> pretty_id : $self->cpan_userid; }; push @m, sprintf("%-7s %1s %s%-22s%s (%s)\n", $class, $uptodateness, $color_on, $self->id, $color_off, $id, ); join "", @m; } #-> sub CPAN::Module::dslip_status sub dslip_status { my($self) = @_; my($stat); # development status @{$stat->{D}}{qw,i c a b R M S,} = qw,idea pre-alpha alpha beta released mature standard,; # support level @{$stat->{S}}{qw,m d u n a,} = qw,mailing-list developer comp.lang.perl.* none abandoned,; # language @{$stat->{L}}{qw,p c + o h,} = qw,perl C C++ other hybrid,; # interface @{$stat->{I}}{qw,f r O p h n,} = qw,functions references+ties object-oriented pragma hybrid none,; # public licence @{$stat->{P}}{qw,p g l b a 2 o d r n,} = qw,Standard-Perl GPL LGPL BSD Artistic Artistic_2 open-source distribution_allowed restricted_distribution no_licence,; for my $x (qw(d s l i p)) { $stat->{$x}{' '} = 'unknown'; $stat->{$x}{'?'} = 'unknown'; } my $ro = $self->ro; return +{} unless $ro && $ro->{statd}; return { D => $ro->{statd}, S => $ro->{stats}, L => $ro->{statl}, I => $ro->{stati}, P => $ro->{statp}, DV => $stat->{D}{$ro->{statd}}, SV => $stat->{S}{$ro->{stats}}, LV => $stat->{L}{$ro->{statl}}, IV => $stat->{I}{$ro->{stati}}, PV => $stat->{P}{$ro->{statp}}, }; } #-> sub CPAN::Module::as_string ; sub as_string { my($self) = @_; my(@m); CPAN->debug("$self entering as_string") if $CPAN::DEBUG; my $class = ref($self); $class =~ s/^CPAN:://; local($^W) = 0; push @m, $class, " id = $self->{ID}\n"; my $sprintf = " %-12s %s\n"; push @m, sprintf($sprintf, 'DESCRIPTION', $self->description) if $self->description; my $sprintf2 = " %-12s %s (%s)\n"; my($userid); $userid = $self->userid; if ( $userid ) { my $author; if ($author = CPAN::Shell->expand('Author',$userid)) { my $email = ""; my $m; # old perls if ($m = $author->email) { $email = " <$m>"; } push @m, sprintf( $sprintf2, 'CPAN_USERID', $userid, $author->fullname . $email ); } } push @m, sprintf($sprintf, 'CPAN_VERSION', $self->cpan_version) if $self->cpan_version; if (my $cpan_file = $self->cpan_file) { push @m, sprintf($sprintf, 'CPAN_FILE', $cpan_file); if (my $dist = CPAN::Shell->expand("Distribution",$cpan_file)) { my $upload_date = $dist->upload_date; if ($upload_date) { push @m, sprintf($sprintf, 'UPLOAD_DATE', $upload_date); } } } my $sprintf3 = " %-12s %1s%1s%1s%1s%1s (%s,%s,%s,%s,%s)\n"; my $dslip = $self->dslip_status; push @m, sprintf( $sprintf3, 'DSLIP_STATUS', @{$dslip}{qw(D S L I P DV SV LV IV PV)}, ) if $dslip->{D}; my $local_file = $self->inst_file; unless ($self->{MANPAGE}) { my $manpage; if ($local_file) { $manpage = $self->manpage_headline($local_file); } else { # If we have already untarred it, we should look there my $dist = $CPAN::META->instance('CPAN::Distribution', $self->cpan_file); # warn "dist[$dist]"; # mff=manifest file; mfh=manifest handle my($mff,$mfh); if ( $dist->{build_dir} and (-f ($mff = File::Spec->catfile($dist->{build_dir}, "MANIFEST"))) and $mfh = FileHandle->new($mff) ) { CPAN->debug("mff[$mff]") if $CPAN::DEBUG; my $lfre = $self->id; # local file RE $lfre =~ s/::/./g; $lfre .= "\\.pm\$"; my($lfl); # local file file local $/ = "\n"; my(@mflines) = <$mfh>; for (@mflines) { s/^\s+//; s/\s.*//s; } while (length($lfre)>5 and !$lfl) { ($lfl) = grep /$lfre/, @mflines; CPAN->debug("lfl[$lfl]lfre[$lfre]") if $CPAN::DEBUG; $lfre =~ s/.+?\.//; } $lfl =~ s/\s.*//; # remove comments $lfl =~ s/\s+//g; # chomp would maybe be too system-specific my $lfl_abs = File::Spec->catfile($dist->{build_dir},$lfl); # warn "lfl_abs[$lfl_abs]"; if (-f $lfl_abs) { $manpage = $self->manpage_headline($lfl_abs); } } } $self->{MANPAGE} = $manpage if $manpage; } my($item); for $item (qw/MANPAGE/) { push @m, sprintf($sprintf, $item, $self->{$item}) if exists $self->{$item}; } for $item (qw/CONTAINS/) { push @m, sprintf($sprintf, $item, join(" ",@{$self->{$item}})) if exists $self->{$item} && @{$self->{$item}}; } push @m, sprintf($sprintf, 'INST_FILE', $local_file || "(not installed)"); push @m, sprintf($sprintf, 'INST_VERSION', $self->inst_version) if $local_file; if (%{$CPAN::META->{is_tested}||{}}) { # XXX needs to be methodified somehow my $available_file = $self->available_file; if ($available_file && $available_file ne $local_file) { push @m, sprintf($sprintf, 'AVAILABLE_FILE', $available_file); push @m, sprintf($sprintf, 'AVAILABLE_VERSION', $self->available_version); } } join "", @m, "\n"; } #-> sub CPAN::Module::manpage_headline sub manpage_headline { my($self,$local_file) = @_; my(@local_file) = $local_file; $local_file =~ s/\.pm(?!\n)\Z/.pod/; push @local_file, $local_file; my(@result,$locf); for $locf (@local_file) { next unless -f $locf; my $fh = FileHandle->new($locf) or $Carp::Frontend->mydie("Couldn't open $locf: $!"); my $inpod = 0; local $/ = "\n"; while (<$fh>) { $inpod = m/^=(?!head1\s+NAME\s*$)/ ? 0 : m/^=head1\s+NAME\s*$/ ? 1 : $inpod; next unless $inpod; next if /^=/; next if /^\s+$/; chomp; push @result, $_; } close $fh; last if @result; } for (@result) { s/^\s+//; s/\s+$//; } join " ", @result; } #-> sub CPAN::Module::cpan_file ; # Note: also inherited by CPAN::Bundle sub cpan_file { my $self = shift; # CPAN->debug(sprintf "id[%s]", $self->id) if $CPAN::DEBUG; unless ($self->ro) { CPAN::Index->reload; } my $ro = $self->ro; if ($ro && defined $ro->{CPAN_FILE}) { return $ro->{CPAN_FILE}; } else { my $userid = $self->userid; if ( $userid ) { if ($CPAN::META->exists("CPAN::Author",$userid)) { my $author = $CPAN::META->instance("CPAN::Author", $userid); my $fullname = $author->fullname; my $email = $author->email; unless (defined $fullname && defined $email) { return sprintf("Contact Author %s", $userid, ); } return "Contact Author $fullname <$email>"; } else { return "Contact Author $userid (Email address not available)"; } } else { return "N/A"; } } } #-> sub CPAN::Module::cpan_version ; sub cpan_version { my $self = shift; my $ro = $self->ro; unless ($ro) { # Can happen with modules that are not on CPAN $ro = {}; } $ro->{CPAN_VERSION} = 'undef' unless defined $ro->{CPAN_VERSION}; $ro->{CPAN_VERSION}; } #-> sub CPAN::Module::force ; sub force { my($self) = @_; $self->{force_update} = 1; } #-> sub CPAN::Module::fforce ; sub fforce { my($self) = @_; $self->{force_update} = 2; } #-> sub CPAN::Module::notest ; sub notest { my($self) = @_; # $CPAN::Frontend->mywarn("XDEBUG: set notest for Module"); $self->{notest}++; } #-> sub CPAN::Module::rematein ; sub rematein { my($self,$meth) = @_; $CPAN::Frontend->myprint(sprintf("Running %s for module '%s'\n", $meth, $self->id)); my $cpan_file = $self->cpan_file; if ($cpan_file eq "N/A" || $cpan_file =~ /^Contact Author/) { $CPAN::Frontend->mywarn(sprintf qq{ The module %s isn\'t available on CPAN. Either the module has not yet been uploaded to CPAN, or it is temporary unavailable. Please contact the author to find out more about the status. Try 'i %s'. }, $self->id, $self->id, ); return; } my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file); $pack->called_for($self->id); if (exists $self->{force_update}) { if ($self->{force_update} == 2) { $pack->fforce($meth); } else { $pack->force($meth); } } $pack->notest($meth) if exists $self->{notest} && $self->{notest}; $pack->{reqtype} ||= ""; CPAN->debug("dist-reqtype[$pack->{reqtype}]". "self-reqtype[$self->{reqtype}]") if $CPAN::DEBUG; if ($pack->{reqtype}) { if ($pack->{reqtype} eq "b" && $self->{reqtype} =~ /^[rc]$/) { $pack->{reqtype} = $self->{reqtype}; if ( exists $pack->{install} && ( UNIVERSAL::can($pack->{install},"failed") ? $pack->{install}->failed : $pack->{install} =~ /^NO/ ) ) { delete $pack->{install}; $CPAN::Frontend->mywarn ("Promoting $pack->{ID} from 'build_requires' to 'requires'"); } } } else { $pack->{reqtype} = $self->{reqtype}; } my $success = eval { $pack->$meth(); }; my $err = $@; $pack->unforce if $pack->can("unforce") && exists $self->{force_update}; $pack->unnotest if $pack->can("unnotest") && exists $self->{notest}; delete $self->{force_update}; delete $self->{notest}; if ($err) { die $err; } return $success; } #-> sub CPAN::Module::perldoc ; sub perldoc { shift->rematein('perldoc') } #-> sub CPAN::Module::readme ; sub readme { shift->rematein('readme') } #-> sub CPAN::Module::look ; sub look { shift->rematein('look') } #-> sub CPAN::Module::cvs_import ; sub cvs_import { shift->rematein('cvs_import') } #-> sub CPAN::Module::get ; sub get { shift->rematein('get',@_) } #-> sub CPAN::Module::make ; sub make { shift->rematein('make') } #-> sub CPAN::Module::test ; sub test { my $self = shift; # $self->{badtestcnt} ||= 0; $self->rematein('test',@_); } #-> sub CPAN::Module::deprecated_in_core ; sub deprecated_in_core { my ($self) = @_; return unless $CPAN::META->has_inst('Module::CoreList') && Module::CoreList->can('is_deprecated'); return Module::CoreList::is_deprecated($self->{ID}); } #-> sub CPAN::Module::inst_deprecated; # Indicates whether the *installed* version of the module is a deprecated *and* # installed as part of the Perl core library path sub inst_deprecated { my ($self) = @_; my $inst_file = $self->inst_file or return; return $self->deprecated_in_core && $self->_in_priv_or_arch($inst_file); } #-> sub CPAN::Module::uptodate ; sub uptodate { my ($self) = @_; local ($_); my $inst = $self->inst_version or return 0; my $cpan = $self->cpan_version; return 0 if CPAN::Version->vgt($cpan,$inst) || $self->inst_deprecated; CPAN->debug (join ("", "returning uptodate. ", "cpan[$cpan]inst[$inst]", )) if $CPAN::DEBUG; return 1; } # returns true if installed in privlib or archlib sub _in_priv_or_arch { my($self,$inst_file) = @_; foreach my $pair ( [qw(sitearchexp archlibexp)], [qw(sitelibexp privlibexp)] ) { my ($site, $priv) = @Config::Config{@$pair}; if ($^O eq 'VMS') { for my $d ($site, $priv) { $d = VMS::Filespec::unixify($d) }; } s!/*$!!g foreach $site, $priv; next if $site eq $priv; if ($priv eq substr($inst_file,0,length($priv))) { return 1; } } return 0; } #-> sub CPAN::Module::install ; sub install { my($self) = @_; my($doit) = 0; if ($self->uptodate && not exists $self->{force_update} ) { $CPAN::Frontend->myprint(sprintf("%s is up to date (%s).\n", $self->id, $self->inst_version, )); } else { $doit = 1; } my $ro = $self->ro; if ($ro && $ro->{stats} && $ro->{stats} eq "a") { $CPAN::Frontend->mywarn(qq{ \n\n\n ***WARNING*** The module $self->{ID} has no active maintainer (CPAN support level flag 'abandoned').\n\n\n }); $CPAN::Frontend->mysleep(5); } return $doit ? $self->rematein('install') : 1; } #-> sub CPAN::Module::clean ; sub clean { shift->rematein('clean') } #-> sub CPAN::Module::inst_file ; sub inst_file { my($self) = @_; $self->_file_in_path([@INC]); } #-> sub CPAN::Module::available_file ; sub available_file { my($self) = @_; my $sep = $Config::Config{path_sep}; my $perllib = $ENV{PERL5LIB}; $perllib = $ENV{PERLLIB} unless defined $perllib; my @perllib = split(/$sep/,$perllib) if defined $perllib; my @cpan_perl5inc; if ($CPAN::Perl5lib_tempfile) { my $yaml = CPAN->_yaml_loadfile($CPAN::Perl5lib_tempfile); @cpan_perl5inc = @{$yaml->[0]{inc} || []}; } $self->_file_in_path([@cpan_perl5inc,@perllib,@INC]); } #-> sub CPAN::Module::file_in_path ; sub _file_in_path { my($self,$path) = @_; my($dir,@packpath); @packpath = split /::/, $self->{ID}; $packpath[-1] .= ".pm"; if (@packpath == 1 && $packpath[0] eq "readline.pm") { unshift @packpath, "Term", "ReadLine"; # historical reasons } foreach $dir (@$path) { my $pmfile = File::Spec->catfile($dir,@packpath); if (-f $pmfile) { return $pmfile; } } return; } #-> sub CPAN::Module::xs_file ; sub xs_file { my($self) = @_; my($dir,@packpath); @packpath = split /::/, $self->{ID}; push @packpath, $packpath[-1]; $packpath[-1] .= "." . $Config::Config{'dlext'}; foreach $dir (@INC) { my $xsfile = File::Spec->catfile($dir,'auto',@packpath); if (-f $xsfile) { return $xsfile; } } return; } #-> sub CPAN::Module::inst_version ; sub inst_version { my($self) = @_; my $parsefile = $self->inst_file or return; my $have = $self->parse_version($parsefile); $have; } #-> sub CPAN::Module::inst_version ; sub available_version { my($self) = @_; my $parsefile = $self->available_file or return; my $have = $self->parse_version($parsefile); $have; } #-> sub CPAN::Module::parse_version ; sub parse_version { my($self,$parsefile) = @_; if (ALARM_IMPLEMENTED) { my $timeout = (exists($CPAN::Config{'version_timeout'})) ? $CPAN::Config{'version_timeout'} : 15; alarm($timeout); } my $have = eval { local $SIG{ALRM} = sub { die "alarm\n" }; MM->parse_version($parsefile); }; if ($@) { $CPAN::Frontend->mywarn("Error while parsing version number in file '$parsefile'\n"); } alarm(0) if ALARM_IMPLEMENTED; my $leastsanity = eval { defined $have && length $have; }; $have = "undef" unless $leastsanity; $have =~ s/^ //; # since the %vd hack these two lines here are needed $have =~ s/ $//; # trailing whitespace happens all the time $have = CPAN::Version->readable($have); $have =~ s/\s*//g; # stringify to float around floating point issues $have; # no stringify needed, \s* above matches always } #-> sub CPAN::Module::reports sub reports { my($self) = @_; $self->distribution->reports; } 1; perl5/CPAN/Admin.pm000044400000017157152530123070007711 0ustar00package CPAN::Admin; use base CPAN; use CPAN; # old base.pm did not load CPAN on previous line use strict; use vars qw(@EXPORT $VERSION); use constant PAUSE_IP => "pause.perl.org"; @EXPORT = qw(shell); $VERSION = "5.501"; push @CPAN::Complete::COMMANDS, qw(register modsearch); $CPAN::Shell::COLOR_REGISTERED = 1; sub shell { CPAN::shell($_[0]||"admin's cpan> ",$_[1]); } sub CPAN::Shell::register { my($self,$mod,@rest) = @_; unless ($mod) { print "register called without argument\n"; return; } if ($CPAN::META->has_inst("URI::Escape")) { require URI::Escape; } else { print "register requires URI::Escape installed, otherwise it cannot work\n"; return; } print "Got request for mod[$mod]\n"; if (@rest) { my $modline = join " ", $mod, @rest; print "Sending to PAUSE [$modline]\n"; my $emodline = URI::Escape::uri_escape($modline, '^\w '); $emodline =~ s/ /+/g; my $url = sprintf("https://%s/pause/authenquery?pause99_add_mod_modid=". "%s;SUBMIT_pause99_add_mod_hint=hint", PAUSE_IP, $emodline, ); print "url[$url]\n\n"; print ">>>>Trying to open a netscape window<<<<\n"; sleep 1; system("netscape","-remote","openURL($url)"); return; } my $m = CPAN::Shell->expand("Module",$mod); unless (ref $m) { print "Could not determine the object for $mod\n"; return; } my $id = $m->id; print "Found module id[$id] in database\n"; if (exists $m->{RO} && $m->{RO}{chapterid}) { print "$id is already registered\n"; return; } my(@namespace) = split /::/, $id; my $rootns = $namespace[0]; # Tk, XML and Apache need special treatment if ($rootns=~/^(Bundle)\b/) { print "Bundles are not yet ready for registering\n"; return; } # make a good suggestion for the chapter my(@simile) = CPAN::Shell->expand("Module","/^$rootns(:|\$)/"); print "Found within this namespace ", join(", ", map { $_->id } @simile), "\n"; my(%seench); for my $ch (map { exists $_->{RO} ? $_->{RO}{chapterid} : ""} @simile) { next unless $ch; $seench{$ch}=undef; } my(@seench) = sort grep {length($_)} keys %seench; my $reco_ch = ""; if (@seench>1) { print "Found rootnamespace[$rootns] in the chapters [", join(", ", @seench), "]\n"; $reco_ch = $seench[0]; print "Picking $reco_ch\n"; } elsif (@seench==1) { print "Found rootnamespace[$rootns] in the chapter[$seench[0]]\n"; $reco_ch = $seench[0]; } else { print "The new rootnamespace[$rootns] needs to be introduced. Oh well.\n"; } # Look closer at the dist my $d = CPAN::Shell->expand("Distribution", $m->cpan_file); printf "Module comes with dist[%s]\n", $d->id; for my $contm ($d->containsmods) { if ($CPAN::META->exists("CPAN::Module",$contm)) { my $contm_obj = CPAN::Shell->expand("Module",$contm) or next; my $is_reg = exists $contm_obj->{RO} && $contm_obj->{RO}{description}; printf(" in same dist: %s%s\n", $contm, $is_reg ? " already in modulelist" : "", ); } } # get it so that m is better and we can inspect for XS CPAN::Shell->get($id); CPAN::Shell->m($id); CPAN::Shell->d($d->id); my $has_xs = 0; { my($mani,@mani); local $/ = "\n"; open $mani, "$d->{build_dir}/MANIFEST" and @mani = <$mani>; my @xs = grep /\.xs\b/, @mani; if (@xs) { print "Found XS files: @xs"; $has_xs=1; } } my $emodid = URI::Escape::uri_escape($id, '\W'); my $ech = $reco_ch; $ech =~ s/ /+/g; my $description = $m->{MANPAGE} || ""; $description =~ s/[A-Z]//; # POD $description =~ s/^\Q$id\E//; # usually this line starts with the modid $description =~ s/^[ \-]+//; # leading spaces and dashes substr($description,44) = "" if length($description)>44; $description = ucfirst($description); my $edescription = URI::Escape::uri_escape($description, '^\w '); $edescription =~ s/ /+/g; my $url = sprintf("https://%s/pause/authenquery?pause99_add_mod_modid=". "%s;pause99_add_mod_chapterid=%s;pause99_add_mod_statd=%s;". "pause99_add_mod_stats=%s;pause99_add_mod_statl=%s;". "pause99_add_mod_stati=%s;pause99_add_mod_description=%s;". "pause99_add_mod_userid=%s;SUBMIT_pause99_add_mod_preview=preview", PAUSE_IP, $emodid, $ech, "R", "d", $has_xs ? "c" : "p", "O", $edescription, $m->{RO}{CPAN_USERID}, ); print "$url\n\n"; print ">>>>Trying to open a netscape window<<<<\n"; system("netscape","-remote","openURL($url)"); } sub CPAN::Shell::modsearch { my($self,@line) = @_; unless (@line) { print "modsearch called without argument\n"; return; } my $request = join " ", @line; print "Got request[$request]\n"; my $erequest = URI::Escape::uri_escape($request, '^\w '); $erequest =~ s/ /+/g; my $url = sprintf("http://www.xray.mpe.mpg.de/cgi-bin/w3glimpse/modules?query=%s". "&errors=0&case=on&maxfiles=100&maxlines=30", $erequest, ); print "$url\n\n"; print ">>>>Trying to open a netscape window<<<<\n"; system("netscape","-remote","openURL('$url')"); } 1; __END__ =head1 NAME CPAN::Admin - A CPAN Shell for CPAN admins =head1 SYNOPSIS perl -MCPAN::Admin -e shell =head1 STATUS Note: this module is currently not maintained. If you need it and fix it for your needs, please submit patches. =head1 DESCRIPTION CPAN::Admin is a subclass of CPAN that adds the commands C and C to the CPAN shell. C calls C on the named module, assembles a couple of informations (description, language), and calls Netscape with the -remote argument so that a form is filled with all the assembled informations and the registration can be performed with a single click. If the command line has more than one argument, register does not run a C, instead it interprets the rest of the line as DSLI status, description, and userid and sends them to netscape such that the form is again mostly filled and can be edited or confirmed with a single click. CPAN::Admin never performs the submission click for you, it is only intended to fill in the form on PAUSE and leave the confirmation to you. C simply passes the arguments to the search engine for the modules@perl.org mailing list at L where all registration requests are stored. It does so in the same way as register, namely with the C command. An experimental feature has also been added, namely to color already registered modules in listings. If you have L installed, the u, r, and m commands will show already registered modules in green. =head1 PREREQUISITES L, a browser available in the path, the browser must understand the -remote switch (as far as I know, this is only available on UNIX); coloring of registered modules is only available if L is installed. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut perl5/CPAN/FTP.pm000044400000141267152530123070007312 0ustar00# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::FTP; use strict; use Errno (); use Fcntl qw(:flock); use File::Basename qw(dirname); use File::Path qw(mkpath); use CPAN::FTP::netrc; use vars qw($connect_to_internet_ok $Ua $Thesite $ThesiteURL $Themethod); @CPAN::FTP::ISA = qw(CPAN::Debug); use vars qw( $VERSION ); $VERSION = "5.5016"; sub _plus_append_open { my($fh, $file) = @_; my $parent_dir = dirname $file; mkpath $parent_dir; my($cnt); until (open $fh, "+>>$file") { next if exists &Errno::EAGAIN && $! == &Errno::EAGAIN; # don't increment on EAGAIN $CPAN::Frontend->mydie("Could not open '$file' after 10000 tries: $!") if ++$cnt > 100000; sleep 0.0001; mkpath $parent_dir; } } #-> sub CPAN::FTP::ftp_statistics # if they want to rewrite, they need to pass in a filehandle sub _ftp_statistics { my($self,$fh) = @_; my $ftpstats_size = $CPAN::Config->{ftpstats_size}; return if defined $ftpstats_size && $ftpstats_size <= 0; my $locktype = $fh ? LOCK_EX : LOCK_SH; # XXX On Windows flock() implements mandatory locking, so we can # XXX only use shared locking to still allow _yaml_loadfile() to # XXX read from the file using a different filehandle. $locktype = LOCK_SH if $^O eq "MSWin32"; $fh ||= FileHandle->new; my $file = File::Spec->catfile($CPAN::Config->{cpan_home},"FTPstats.yml"); _plus_append_open($fh,$file); my $sleep = 1; my $waitstart; while (!CPAN::_flock($fh, $locktype|LOCK_NB)) { $waitstart ||= localtime(); if ($sleep>3) { my $now = localtime(); $CPAN::Frontend->mywarn("$now: waiting for read lock on '$file' (since $waitstart)\n"); } sleep($sleep); # this sleep must not be overridden; # Frontend->mysleep with AUTOMATED_TESTING has # provoked complete lock contention on my NFS if ($sleep <= 6) { $sleep+=0.5; } else { # retry to get a fresh handle. If it is NFS and the handle is stale, we will never get an flock _plus_append_open($fh, $file); } } my $stats = eval { CPAN->_yaml_loadfile($file, {loadblessed => 1}); }; if ($@) { if (ref $@) { if (ref $@ eq "CPAN::Exception::yaml_not_installed") { chomp $@; $CPAN::Frontend->myprintonce("Warning (usually harmless): $@\n"); return; } elsif (ref $@ eq "CPAN::Exception::yaml_process_error") { my $time = time; my $to = "$file.$time"; $CPAN::Frontend->mywarn("Error reading '$file': $@ Trying to stash it away as '$to' to prevent further interruptions. You may want to remove that file later.\n"); # may fail because somebody else has moved it away in the meantime: rename $file, $to or $CPAN::Frontend->mywarn("Could not rename '$file' to '$to': $!\n"); return; } } else { $CPAN::Frontend->mydie($@); } } CPAN::_flock($fh, LOCK_UN); return $stats->[0]; } #-> sub CPAN::FTP::_mytime sub _mytime () { if (CPAN->has_inst("Time::HiRes")) { return Time::HiRes::time(); } else { return time; } } #-> sub CPAN::FTP::_new_stats sub _new_stats { my($self,$file) = @_; my $ret = { file => $file, attempts => [], start => _mytime, }; $ret; } #-> sub CPAN::FTP::_add_to_statistics sub _add_to_statistics { my($self,$stats) = @_; my $yaml_module = CPAN::_yaml_module(); $self->debug("yaml_module[$yaml_module]") if $CPAN::DEBUG; if ($CPAN::META->has_inst($yaml_module)) { $stats->{thesiteurl} = $ThesiteURL; $stats->{end} = CPAN::FTP::_mytime(); my $fh = FileHandle->new; my $time = time; my $sdebug = 0; my @debug; @debug = $time if $sdebug; my $fullstats = $self->_ftp_statistics($fh); close $fh if $fh && defined(fileno($fh)); $fullstats->{history} ||= []; push @debug, scalar @{$fullstats->{history}} if $sdebug; push @debug, time if $sdebug; push @{$fullstats->{history}}, $stats; # YAML.pm 0.62 is unacceptably slow with 999; # YAML::Syck 0.82 has no noticable performance problem with 999; my $ftpstats_size = $CPAN::Config->{ftpstats_size}; $ftpstats_size = 99 unless defined $ftpstats_size; my $ftpstats_period = $CPAN::Config->{ftpstats_period} || 14; while ( @{$fullstats->{history} || []} && ( @{$fullstats->{history}} > $ftpstats_size || $time - $fullstats->{history}[0]{start} > 86400*$ftpstats_period ) ) { shift @{$fullstats->{history}} } push @debug, scalar @{$fullstats->{history}} if $sdebug; push @debug, time if $sdebug; push @debug, scalar localtime($fullstats->{history}[0]{start}) if $sdebug; # need no eval because if this fails, it is serious my $sfile = File::Spec->catfile($CPAN::Config->{cpan_home},"FTPstats.yml"); CPAN->_yaml_dumpfile("$sfile.$$",$fullstats); if ( $sdebug ) { local $CPAN::DEBUG = 512; # FTP push @debug, time; CPAN->debug(sprintf("DEBUG history: before_read[%d]before[%d]at[%d]". "after[%d]at[%d]oldest[%s]dumped backat[%d]", @debug, )); } # Win32 cannot rename a file to an existing filename unlink($sfile) if ($^O eq 'MSWin32' or $^O eq 'os2'); _copy_stat($sfile, "$sfile.$$") if -e $sfile; rename "$sfile.$$", $sfile or $CPAN::Frontend->mywarn("Could not rename '$sfile.$$' to '$sfile': $!\nGiving up\n"); } } # Copy some stat information (owner, group, mode and) from one file to # another. # This is a utility function which might be moved to a utility repository. #-> sub CPAN::FTP::_copy_stat sub _copy_stat { my($src, $dest) = @_; my @stat = stat($src); if (!@stat) { $CPAN::Frontend->mywarn("Can't stat '$src': $!\n"); return; } eval { chmod $stat[2], $dest or $CPAN::Frontend->mywarn("Can't chmod '$dest' to " . sprintf("0%o", $stat[2]) . ": $!\n"); }; warn $@ if $@; eval { chown $stat[4], $stat[5], $dest or do { my $save_err = $!; # otherwise it's lost in the get... calls $CPAN::Frontend->mywarn("Can't chown '$dest' to " . (getpwuid($stat[4]))[0] . "/" . (getgrgid($stat[5]))[0] . ": $save_err\n" ); }; }; warn $@ if $@; } # if file is CHECKSUMS, suggest the place where we got the file to be # checked from, maybe only for young files? #-> sub CPAN::FTP::_recommend_url_for sub _recommend_url_for { my($self, $file, $urllist) = @_; if ($file =~ s|/CHECKSUMS(.gz)?$||) { my $fullstats = $self->_ftp_statistics(); my $history = $fullstats->{history} || []; while (my $last = pop @$history) { last if $last->{end} - time > 3600; # only young results are interesting next unless $last->{file}; # dirname of nothing dies! next unless $file eq dirname($last->{file}); return $last->{thesiteurl}; } } if ($CPAN::Config->{randomize_urllist} && rand(1) < $CPAN::Config->{randomize_urllist} ) { $urllist->[int rand scalar @$urllist]; } else { return (); } } #-> sub CPAN::FTP::_get_urllist sub _get_urllist { my($self, $with_defaults) = @_; $with_defaults ||= 0; CPAN->debug("with_defaults[$with_defaults]") if $CPAN::DEBUG; $CPAN::Config->{urllist} ||= []; unless (ref $CPAN::Config->{urllist} eq 'ARRAY') { $CPAN::Frontend->mywarn("Malformed urllist; ignoring. Configuration file corrupt?\n"); $CPAN::Config->{urllist} = []; } my @urllist = grep { defined $_ and length $_ } @{$CPAN::Config->{urllist}}; push @urllist, @CPAN::Defaultsites if $with_defaults; for my $u (@urllist) { CPAN->debug("u[$u]") if $CPAN::DEBUG; if (UNIVERSAL::can($u,"text")) { $u->{TEXT} .= "/" unless substr($u->{TEXT},-1) eq "/"; } else { $u .= "/" unless substr($u,-1) eq "/"; $u = CPAN::URL->new(TEXT => $u, FROM => "USER"); } } \@urllist; } #-> sub CPAN::FTP::ftp_get ; sub ftp_get { my($class,$host,$dir,$file,$target) = @_; $class->debug( qq[Going to fetch file [$file] from dir [$dir] on host [$host] as local [$target]\n] ) if $CPAN::DEBUG; my $ftp = Net::FTP->new($host); unless ($ftp) { $CPAN::Frontend->mywarn(" Could not connect to host '$host' with Net::FTP\n"); return; } return 0 unless defined $ftp; $ftp->debug(1) if $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG; $class->debug(qq[Going to login("anonymous","$Config::Config{cf_email}")]); unless ( $ftp->login("anonymous",$Config::Config{'cf_email'}) ) { my $msg = $ftp->message; $CPAN::Frontend->mywarn(" Couldn't login on $host: $msg\n"); return; } unless ( $ftp->cwd($dir) ) { my $msg = $ftp->message; $CPAN::Frontend->mywarn(" Couldn't cwd $dir: $msg\n"); return; } $ftp->binary; $class->debug(qq[Going to ->get("$file","$target")\n]) if $CPAN::DEBUG; unless ( $ftp->get($file,$target) ) { my $msg = $ftp->message; $CPAN::Frontend->mywarn(" Couldn't fetch $file from $host: $msg\n"); return; } $ftp->quit; # it's ok if this fails return 1; } # If more accuracy is wanted/needed, Chris Leach sent me this patch... # > *** /install/perl/live/lib/CPAN.pm- Wed Sep 24 13:08:48 1997 # > --- /tmp/cp Wed Sep 24 13:26:40 1997 # > *************** # > *** 1562,1567 **** # > --- 1562,1580 ---- # > return 1 if substr($url,0,4) eq "file"; # > return 1 unless $url =~ m|://([^/]+)|; # > my $host = $1; # > + my $proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'}; # > + if ($proxy) { # > + $proxy =~ m|://([^/:]+)|; # > + $proxy = $1; # > + my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'}; # > + if ($noproxy) { # > + if ($host !~ /$noproxy$/) { # > + $host = $proxy; # > + } # > + } else { # > + $host = $proxy; # > + } # > + } # > require Net::Ping; # > return 1 unless $Net::Ping::VERSION >= 2; # > my $p; #-> sub CPAN::FTP::localize ; sub localize { my($self,$file,$aslocal,$force,$with_defaults) = @_; $force ||= 0; Carp::croak( "Usage: ->localize(cpan_file,as_local_file[,\$force])" ) unless defined $aslocal; if ($CPAN::DEBUG){ require Carp; my $longmess = Carp::longmess(); $self->debug("file[$file] aslocal[$aslocal] force[$force] carplongmess[$longmess]"); } for ($CPAN::Config->{connect_to_internet_ok}) { $connect_to_internet_ok = $_ if not defined $connect_to_internet_ok and defined $_; } my $ph = $CPAN::Config->{pushy_https}; if (!defined $ph || $ph) { return $self->localize_2021($file,$aslocal,$force,$with_defaults); } else { return $self->localize_1995ff($file,$aslocal,$force,$with_defaults); } } sub have_promising_aslocal { my($self, $aslocal, $force) = @_; if (-f $aslocal && -r _ && !($force & 1)) { my $size; if ($size = -s $aslocal) { $self->debug("aslocal[$aslocal]size[$size]") if $CPAN::DEBUG; return 1; } else { # empty file from a previous unsuccessful attempt to download it unlink $aslocal or $CPAN::Frontend->mydie("Found a zero-length '$aslocal' that I ". "could not remove."); } } return; } #-> sub CPAN::FTP::localize ; sub localize_2021 { my($self,$file,$aslocal,$force,$with_defaults) = @_; return $aslocal if $self->have_promising_aslocal($aslocal, $force); my($aslocal_dir) = dirname($aslocal); my $ret; $self->mymkpath($aslocal_dir); my $aslocal_tempfile = $aslocal . ".tmp" . $$; my $base; if ( ($CPAN::META->has_usable('HTTP::Tiny') && $CPAN::META->has_usable('Net::SSLeay') && $CPAN::META->has_usable('IO::Socket::SSL') ) || $CPAN::Config->{curl} || $CPAN::Config->{wget} ) { for my $prx (qw(https_proxy no_proxy)) { $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx}; } $base = "https://cpan.org/"; } else { my @missing_modules = grep { ! $CPAN::META->has_usable($_) } qw(HTTP::Tiny Net::SSLeay IO::Socket::SSL); my $miss = join ", ", map { "'$_'" } @missing_modules; my $modules = @missing_modules == 1 ? "module" : "modules"; $CPAN::Frontend->mywarn("Missing or unusable $modules $miss, and found neither curl nor wget installed.\n"); if ($CPAN::META->has_usable('HTTP::Tiny')) { $CPAN::Frontend->mywarn("Need to fall back to http.\n") } for my $prx (qw(http_proxy no_proxy)) { $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx}; } $base = "http://www.cpan.org/"; } $ret = $self->hostdl_2021($base,$file,$aslocal_tempfile); if ($ret) { # c&p from below CPAN->debug("ret[$ret]aslocal[$aslocal]") if $CPAN::DEBUG; if ($ret eq $aslocal_tempfile) { # if we got it exactly as we asked for, only then we # want to rename rename $aslocal_tempfile, $aslocal or $CPAN::Frontend->mydie("Error while trying to rename ". "'$ret' to '$aslocal': $!"); $ret = $aslocal; } } else { unlink $aslocal_tempfile; return; } return $ret; } sub hostdl_2021 { my($self, $base, $file, $aslocal) = @_; # the $aslocal is $aslocal_tempfile in the caller (old convention) my $proxy_vars = $self->_proxy_vars($base); my($proto) = $base =~ /^(https?)/; my $url = "$base$file"; # hostdl_2021 may be called with either http or https urls if ( $CPAN::META->has_usable('HTTP::Tiny') && ( $proto eq "http" || ( $CPAN::META->has_usable('Net::SSLeay') && $CPAN::META->has_usable('IO::Socket::SSL') ) ) ){ # mostly c&p from below require CPAN::HTTP::Client; my $chc = CPAN::HTTP::Client->new( proxy => $CPAN::Config->{http_proxy} || $ENV{http_proxy}, no_proxy => $CPAN::Config->{no_proxy} || $ENV{no_proxy}, ); for my $try ( $url, ( $url !~ /\.gz(?!\n)\Z/ ? "$url.gz" : () ) ) { $CPAN::Frontend->myprint("Fetching with HTTP::Tiny:\n$try\n"); my $res = eval { $chc->mirror($try, $aslocal) }; if ( $res && $res->{success} ) { my $now = time; utime $now, $now, $aslocal; # download time is more # important than upload # time return $aslocal; } elsif ( $res && $res->{status} ne '599') { $CPAN::Frontend->myprint(sprintf( "HTTP::Tiny failed with code[%s] message[%s]\n", $res->{status}, $res->{reason}, ) ); } elsif ( $res && $res->{status} eq '599') { $CPAN::Frontend->myprint(sprintf( "HTTP::Tiny failed with an internal error: %s\n", $res->{content}, ) ); } else { my $err = $@ || 'Unknown error'; $CPAN::Frontend->myprint(sprintf( "Error downloading with HTTP::Tiny: %s\n", $err ) ); } } } elsif ($CPAN::Config->{curl} || $CPAN::Config->{wget}){ # c&p from further down my($src_switch, $stdout_redir); my($devnull) = $CPAN::Config->{devnull} || ""; DLPRG: for my $dlprg (qw(curl wget)) { my $dlprg_configured = $CPAN::Config->{$dlprg}; next unless defined $dlprg_configured && length $dlprg_configured; my $funkyftp = CPAN::HandleConfig->safe_quote($dlprg_configured); if ($dlprg eq "wget") { $src_switch = " -O \"$aslocal\""; $stdout_redir = ""; } elsif ($dlprg eq 'curl') { $src_switch = ' -L -f -s -S --netrc-optional'; $stdout_redir = " > \"$aslocal\""; if ($proxy_vars->{http_proxy}) { $src_switch .= qq{ -U "$proxy_vars->{proxy_user}:$proxy_vars->{proxy_pass}" -x "$proxy_vars->{http_proxy}"}; } } $CPAN::Frontend->myprint( qq[ Trying with $funkyftp$src_switch to get $url ]); my($system) = "$funkyftp$src_switch \"$url\" $devnull$stdout_redir"; $self->debug("system[$system]") if $CPAN::DEBUG; my($wstatus) = system($system); if ($wstatus == 0) { return $aslocal; } else { my $estatus = $wstatus >> 8; my $size = -f $aslocal ? ", left\n$aslocal with size ".-s _ : "\nWarning: expected file [$aslocal] doesn't exist"; $CPAN::Frontend->myprint(qq{ Function system("$system") returned status $estatus (wstat $wstatus)$size }); } } # DLPRG } # curl, wget return; } #-> sub CPAN::FTP::localize ; sub localize_1995ff { my($self,$file,$aslocal,$force,$with_defaults) = @_; if ($^O eq 'MacOS') { # Comment by AK on 2000-09-03: Uniq short filenames would be # available in CHECKSUMS file my($name, $path) = File::Basename::fileparse($aslocal, ''); if (length($name) > 31) { $name =~ s/( \.( readme(\.(gz|Z))? | (tar\.)?(gz|Z) | tgz | zip | pm\.(gz|Z) ) )$//x; my $suf = $1; my $size = 31 - length($suf); while (length($name) > $size) { chop $name; } $name .= $suf; $aslocal = File::Spec->catfile($path, $name); } } return $aslocal if $self->have_promising_aslocal($aslocal, $force); my($maybe_restore) = 0; if (-f $aslocal) { rename $aslocal, "$aslocal.bak$$"; $maybe_restore++; } my($aslocal_dir) = dirname($aslocal); # Inheritance is not easier to manage than a few if/else branches if ($CPAN::META->has_usable('LWP::UserAgent')) { unless ($Ua) { CPAN::LWP::UserAgent->config; eval {$Ua = CPAN::LWP::UserAgent->new;}; # Why is has_usable still not fit enough? if ($@) { $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n") if $CPAN::DEBUG; } else { my($var); $Ua->proxy('ftp', $var) if $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy}; $Ua->proxy('http', $var) if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy}; $Ua->no_proxy($var) if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy}; } } } for my $prx (qw(ftp_proxy http_proxy no_proxy)) { $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx}; } # Try the list of urls for each single object. We keep a record # where we did get a file from my(@reordered,$last); my $ccurllist = $self->_get_urllist($with_defaults); $last = $#$ccurllist; if ($force & 2) { # local cpans probably out of date, don't reorder @reordered = (0..$last); } else { @reordered = sort { (substr($ccurllist->[$b],0,4) eq "file") <=> (substr($ccurllist->[$a],0,4) eq "file") or defined($ThesiteURL) and ($ccurllist->[$b] eq $ThesiteURL) <=> ($ccurllist->[$a] eq $ThesiteURL) } 0..$last; } my(@levels); $Themethod ||= ""; $self->debug("Themethod[$Themethod]reordered[@reordered]") if $CPAN::DEBUG; my @all_levels = ( ["dleasy", "file"], ["dleasy"], ["dlhard"], ["dlhardest"], ["dleasy", "http","defaultsites"], ["dlhard", "http","defaultsites"], ["dleasy", "ftp", "defaultsites"], ["dlhard", "ftp", "defaultsites"], ["dlhardest","", "defaultsites"], ); if ($Themethod) { @levels = grep {$_->[0] eq $Themethod} @all_levels; push @levels, grep {$_->[0] ne $Themethod} @all_levels; } else { @levels = @all_levels; } @levels = qw/dleasy/ if $^O eq 'MacOS'; my($levelno); local $ENV{FTP_PASSIVE} = exists $CPAN::Config->{ftp_passive} ? $CPAN::Config->{ftp_passive} : 1; my $ret; my $stats = $self->_new_stats($file); LEVEL: for $levelno (0..$#levels) { my $level_tuple = $levels[$levelno]; my($level,$scheme,$sitetag) = @$level_tuple; $self->mymkpath($aslocal_dir) unless $scheme && "file" eq $scheme; my $defaultsites = $sitetag && $sitetag eq "defaultsites" && !@$ccurllist; my @urllist; if ($defaultsites) { unless (defined $connect_to_internet_ok) { $CPAN::Frontend->myprint(sprintf qq{ I would like to connect to one of the following sites to get '%s': %s }, $file, join("",map { " ".$_->text."\n" } @CPAN::Defaultsites), ); my $answer = CPAN::Shell::colorable_makemaker_prompt("Is it OK to try to connect to the Internet?", "yes"); if ($answer =~ /^y/i) { $connect_to_internet_ok = 1; } else { $connect_to_internet_ok = 0; } } if ($connect_to_internet_ok) { @urllist = @CPAN::Defaultsites; } else { my $sleep = 2; # the tricky thing about dying here is that everybody # believes that calls to exists() or all_objects() are # safe. require CPAN::Exception::blocked_urllist; die CPAN::Exception::blocked_urllist->new; } } else { # ! $defaultsites my @host_seq = $level =~ /dleasy/ ? @reordered : 0..$last; # reordered has file and $Thesiteurl first @urllist = map { $ccurllist->[$_] } @host_seq; } $self->debug("synth. urllist[@urllist]") if $CPAN::DEBUG; my $aslocal_tempfile = $aslocal . ".tmp" . $$; if (my $recommend = $self->_recommend_url_for($file,\@urllist)) { @urllist = grep { $_ ne $recommend } @urllist; unshift @urllist, $recommend; } $self->debug("synth. urllist[@urllist]") if $CPAN::DEBUG; $ret = $self->hostdlxxx($level,$scheme,\@urllist,$file,$aslocal_tempfile,$stats); if ($ret) { CPAN->debug("ret[$ret]aslocal[$aslocal]") if $CPAN::DEBUG; if ($ret eq $aslocal_tempfile) { # if we got it exactly as we asked for, only then we # want to rename rename $aslocal_tempfile, $aslocal or $CPAN::Frontend->mydie("Error while trying to rename ". "'$ret' to '$aslocal': $!"); $ret = $aslocal; } elsif (-f $ret && $scheme eq 'file' ) { # it's a local file, so there's nothing left to do, we # let them read from where it is } $Themethod = $level; my $now = time; # utime $now, $now, $aslocal; # too bad, if we do that, we # might alter a local mirror $self->debug("level[$level]") if $CPAN::DEBUG; last LEVEL; } else { unlink $aslocal_tempfile; last if $CPAN::Signal; # need to cleanup } } if ($ret) { $stats->{filesize} = -s $ret; } $self->debug("before _add_to_statistics") if $CPAN::DEBUG; $self->_add_to_statistics($stats); $self->debug("after _add_to_statistics") if $CPAN::DEBUG; if ($ret) { unlink "$aslocal.bak$$"; return $ret; } unless ($CPAN::Signal) { my(@mess); local $" = " "; if (@{$CPAN::Config->{urllist}}) { push @mess, qq{Please check, if the URLs I found in your configuration file \(}. join(", ", @{$CPAN::Config->{urllist}}). qq{\) are valid.}; } else { push @mess, qq{Your urllist is empty!}; } push @mess, qq{The urllist can be edited.}, qq{E.g. with 'o conf urllist push ftp://myurl/'}; $CPAN::Frontend->mywarn(Text::Wrap::wrap("","","@mess"). "\n\n"); $CPAN::Frontend->mydie("Could not fetch $file\n"); } if ($maybe_restore) { rename "$aslocal.bak$$", $aslocal; $CPAN::Frontend->myprint("Trying to get away with old file:\n" . $self->ls($aslocal) . "\n"); return $aslocal; } return; } sub mymkpath { my($self, $aslocal_dir) = @_; mkpath($aslocal_dir); $CPAN::Frontend->mywarn(qq{Warning: You are not allowed to write into }. qq{directory "$aslocal_dir". I\'ll continue, but if you encounter problems, they may be due to insufficient permissions.\n}) unless -w $aslocal_dir; } sub hostdlxxx { my $self = shift; my $level = shift; my $scheme = shift; my $h = shift; $h = [ grep /^\Q$scheme\E:/, @$h ] if $scheme; my $method = "host$level"; $self->$method($h, @_); } sub _set_attempt { my($self,$stats,$method,$url) = @_; push @{$stats->{attempts}}, { method => $method, start => _mytime, url => $url, }; } # package CPAN::FTP; sub hostdleasy { #called from hostdlxxx my($self,$host_seq,$file,$aslocal,$stats) = @_; my($ro_url); HOSTEASY: for $ro_url (@$host_seq) { $self->_set_attempt($stats,"dleasy",$ro_url); my $url = "$ro_url$file"; $self->debug("localizing perlish[$url]") if $CPAN::DEBUG; if ($url =~ /^file:/) { my $l; if ($CPAN::META->has_inst('URI::URL')) { my $u = URI::URL->new($url); $l = $u->file; } else { # works only on Unix, is poorly constructed, but # hopefully better than nothing. # RFC 1738 says fileurl BNF is # fileurl = "file://" [ host | "localhost" ] "/" fpath # Thanks to "Mark D. Baushke" for # the code ($l = $url) =~ s|^file://[^/]*/|/|; # discard the host part $l =~ s|^file:||; # assume they # meant # file://localhost $l =~ s|^/||s if ! -f $l && $l =~ m|^/\w:|; # e.g. /P: } $self->debug("local file[$l]") if $CPAN::DEBUG; if ( -f $l && -r _) { $ThesiteURL = $ro_url; return $l; } # If request is for a compressed file and we can find the # uncompressed file also, return the path of the uncompressed file # otherwise, decompress it and return the resulting path if ($l =~ /(.+)\.gz$/) { my $ungz = $1; if ( -f $ungz && -r _) { $ThesiteURL = $ro_url; return $ungz; } elsif (-f $l && -r _) { eval { CPAN::Tarzip->new($l)->gunzip($aslocal) }; if ( -f $aslocal && -s _) { $ThesiteURL = $ro_url; return $aslocal; } elsif (! -s $aslocal) { unlink $aslocal; } elsif (-f $l) { $CPAN::Frontend->mywarn("Error decompressing '$l': $@\n") if $@; return; } } } # Otherwise, return the local file path if it exists elsif ( -f $l && -r _) { $ThesiteURL = $ro_url; return $l; } # If we can't find it, but there is a compressed version # of it, then decompress it elsif (-f "$l.gz") { $self->debug("found compressed $l.gz") if $CPAN::DEBUG; eval { CPAN::Tarzip->new("$l.gz")->gunzip($aslocal) }; if ( -f $aslocal) { $ThesiteURL = $ro_url; return $aslocal; } else { $CPAN::Frontend->mywarn("Error decompressing '$l': $@\n") if $@; return; } } $CPAN::Frontend->mywarn("Could not find '$l'\n"); } $self->debug("it was not a file URL") if $CPAN::DEBUG; if ($CPAN::META->has_usable('LWP')) { $CPAN::Frontend->myprint("Fetching with LWP:\n$url\n"); unless ($Ua) { CPAN::LWP::UserAgent->config; eval { $Ua = CPAN::LWP::UserAgent->new; }; if ($@) { $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n"); } } my $res = $Ua->mirror($url, $aslocal); if ($res->is_success) { $ThesiteURL = $ro_url; my $now = time; utime $now, $now, $aslocal; # download time is more # important than upload # time return $aslocal; } elsif ($url !~ /\.gz(?!\n)\Z/) { my $gzurl = "$url.gz"; $CPAN::Frontend->myprint("Fetching with LWP:\n$gzurl\n"); $res = $Ua->mirror($gzurl, "$aslocal.gz"); if ($res->is_success) { if (eval {CPAN::Tarzip->new("$aslocal.gz")->gunzip($aslocal)}) { $ThesiteURL = $ro_url; return $aslocal; } } } else { $CPAN::Frontend->myprint(sprintf( "LWP failed with code[%s] message[%s]\n", $res->code, $res->message, )); # Alan Burlison informed me that in firewall environments # Net::FTP can still succeed where LWP fails. So we do not # skip Net::FTP anymore when LWP is available. } } elsif ($url =~ /^http:/i && $CPAN::META->has_usable('HTTP::Tiny')) { require CPAN::HTTP::Client; my $chc = CPAN::HTTP::Client->new( proxy => $CPAN::Config->{http_proxy} || $ENV{http_proxy}, no_proxy => $CPAN::Config->{no_proxy} || $ENV{no_proxy}, ); for my $try ( $url, ( $url !~ /\.gz(?!\n)\Z/ ? "$url.gz" : () ) ) { $CPAN::Frontend->myprint("Fetching with HTTP::Tiny:\n$try\n"); my $res = eval { $chc->mirror($try, $aslocal) }; if ( $res && $res->{success} ) { $ThesiteURL = $ro_url; my $now = time; utime $now, $now, $aslocal; # download time is more # important than upload # time return $aslocal; } elsif ( $res && $res->{status} ne '599') { $CPAN::Frontend->myprint(sprintf( "HTTP::Tiny failed with code[%s] message[%s]\n", $res->{status}, $res->{reason}, ) ); } elsif ( $res && $res->{status} eq '599') { $CPAN::Frontend->myprint(sprintf( "HTTP::Tiny failed with an internal error: %s\n", $res->{content}, ) ); } else { my $err = $@ || 'Unknown error'; $CPAN::Frontend->myprint(sprintf( "Error downloading with HTTP::Tiny: %s\n", $err ) ); } } } return if $CPAN::Signal; if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { # that's the nice and easy way thanks to Graham $self->debug("recognized ftp") if $CPAN::DEBUG; my($host,$dir,$getfile) = ($1,$2,$3); if ($CPAN::META->has_usable('Net::FTP')) { $dir =~ s|/+|/|g; $CPAN::Frontend->myprint("Fetching with Net::FTP:\n$url\n"); $self->debug("getfile[$getfile]dir[$dir]host[$host]" . "aslocal[$aslocal]") if $CPAN::DEBUG; if (CPAN::FTP->ftp_get($host,$dir,$getfile,$aslocal)) { $ThesiteURL = $ro_url; return $aslocal; } if ($aslocal !~ /\.gz(?!\n)\Z/) { my $gz = "$aslocal.gz"; $CPAN::Frontend->myprint("Fetching with Net::FTP\n$url.gz\n"); if (CPAN::FTP->ftp_get($host, $dir, "$getfile.gz", $gz) && eval{CPAN::Tarzip->new($gz)->gunzip($aslocal)} ) { $ThesiteURL = $ro_url; return $aslocal; } } # next HOSTEASY; } else { CPAN->debug("Net::FTP does not count as usable atm") if $CPAN::DEBUG; } } if ( UNIVERSAL::can($ro_url,"text") and $ro_url->{FROM} eq "USER" ) { ##address #17973: default URLs should not try to override ##user-defined URLs just because LWP is not available my $ret = $self->hostdlhard([$ro_url],$file,$aslocal,$stats); return $ret if $ret; } return if $CPAN::Signal; } } # package CPAN::FTP; sub hostdlhard { my($self,$host_seq,$file,$aslocal,$stats) = @_; # Came back if Net::FTP couldn't establish connection (or # failed otherwise) Maybe they are behind a firewall, but they # gave us a socksified (or other) ftp program... my($ro_url); my($devnull) = $CPAN::Config->{devnull} || ""; # < /dev/null "; my($aslocal_dir) = dirname($aslocal); mkpath($aslocal_dir); my $some_dl_success = 0; my $any_attempt = 0; HOSTHARD: for $ro_url (@$host_seq) { $self->_set_attempt($stats,"dlhard",$ro_url); my $url = "$ro_url$file"; my($proto,$host,$dir,$getfile); # Courtesy Mark Conty mark_conty@cargill.com change from # if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { # to if ($url =~ m|^([^:]+)://(.*?)/(.*)/(.*)|) { # proto not yet used ($proto,$host,$dir,$getfile) = ($1,$2,$3,$4); } else { next HOSTHARD; # who said, we could ftp anything except ftp? } next HOSTHARD if $proto eq "file"; # file URLs would have had # success above. Likely a bogus URL # making at least one attempt against a host $any_attempt++; $self->debug("localizing funkyftpwise[$url]") if $CPAN::DEBUG; # Try the most capable first and leave ncftp* for last as it only # does FTP. my $proxy_vars = $self->_proxy_vars($ro_url); DLPRG: for my $f (qw(curl wget lynx ncftpget ncftp)) { my $funkyftp = CPAN::HandleConfig->safe_quote($CPAN::Config->{$f}); next DLPRG unless defined $funkyftp; next DLPRG if $funkyftp =~ /^\s*$/; my($src_switch) = ""; my($chdir) = ""; my($stdout_redir) = " > \"$aslocal\""; if ($f eq "lynx") { $src_switch = " -source"; } elsif ($f eq "ncftp") { next DLPRG unless $url =~ m{\Aftp://}; $src_switch = " -c"; } elsif ($f eq "wget") { $src_switch = " -O \"$aslocal\""; $stdout_redir = ""; } elsif ($f eq 'curl') { $src_switch = ' -L -f -s -S --netrc-optional'; if ($proxy_vars->{http_proxy}) { $src_switch .= qq{ -U "$proxy_vars->{proxy_user}:$proxy_vars->{proxy_pass}" -x "$proxy_vars->{http_proxy}"}; } } elsif ($f eq "ncftpget") { next DLPRG unless $url =~ m{\Aftp://}; $chdir = "cd $aslocal_dir && "; $stdout_redir = ""; } $CPAN::Frontend->myprint( qq[ Trying with $funkyftp$src_switch to get $url ]); my($system) = "$chdir$funkyftp$src_switch \"$url\" $devnull$stdout_redir"; $self->debug("system[$system]") if $CPAN::DEBUG; my($wstatus) = system($system); if ($f eq "lynx") { # lynx returns 0 when it fails somewhere if (-s $aslocal) { my $content = do { local *FH; open FH, $aslocal or die; local $/; }; if ($content =~ /^<.*([45]|Error [45])/si) { $CPAN::Frontend->mywarn(qq{ No success, the file that lynx has downloaded looks like an error message: $content }); $CPAN::Frontend->mysleep(1); next DLPRG; } $some_dl_success++; } else { $CPAN::Frontend->myprint(qq{ No success, the file that lynx has downloaded is an empty file. }); next DLPRG; } } if ($wstatus == 0) { if (-s $aslocal) { # Looks good $some_dl_success++; } $ThesiteURL = $ro_url; return $aslocal; } else { my $estatus = $wstatus >> 8; my $size = -f $aslocal ? ", left\n$aslocal with size ".-s _ : "\nWarning: expected file [$aslocal] doesn't exist"; $CPAN::Frontend->myprint(qq{ Function system("$system") returned status $estatus (wstat $wstatus)$size }); } return if $CPAN::Signal; } # download/transfer programs (DLPRG) } # host return unless $any_attempt; if ($some_dl_success) { $CPAN::Frontend->mywarn("Warning: doesn't seem we had substantial success downloading '$aslocal'. Don't know how to proceed.\n"); } else { $CPAN::Frontend->mywarn("Warning: no success downloading '$aslocal'. Giving up on it.\n"); } return; } #-> CPAN::FTP::_proxy_vars sub _proxy_vars { my($self,$url) = @_; my $ret = +{}; my $http_proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'}; if ($http_proxy) { my($host) = $url =~ m|://([^/:]+)|; my $want_proxy = 1; my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'} || ""; my @noproxy = split /\s*,\s*/, $noproxy; if ($host) { DOMAIN: for my $domain (@noproxy) { if ($host =~ /\Q$domain\E$/) { # cf. LWP::UserAgent $want_proxy = 0; last DOMAIN; } } } else { $CPAN::Frontend->mywarn(" Could not determine host from http_proxy '$http_proxy'\n"); } if ($want_proxy) { my($user, $pass) = CPAN::HTTP::Credentials->get_proxy_credentials(); $ret = { proxy_user => $user, proxy_pass => $pass, http_proxy => $http_proxy }; } } return $ret; } # package CPAN::FTP; sub hostdlhardest { my($self,$host_seq,$file,$aslocal,$stats) = @_; return unless @$host_seq; my($ro_url); my($aslocal_dir) = dirname($aslocal); mkpath($aslocal_dir); my $ftpbin = $CPAN::Config->{ftp}; unless ($ftpbin && length $ftpbin && MM->maybe_command($ftpbin)) { $CPAN::Frontend->myprint("No external ftp command available\n\n"); return; } $CPAN::Frontend->mywarn(qq{ As a last resort we now switch to the external ftp command '$ftpbin' to get '$aslocal'. Doing so often leads to problems that are hard to diagnose. If you're the victim of such problems, please consider unsetting the ftp config variable with o conf ftp "" o conf commit }); $CPAN::Frontend->mysleep(2); HOSTHARDEST: for $ro_url (@$host_seq) { $self->_set_attempt($stats,"dlhardest",$ro_url); my $url = "$ro_url$file"; $self->debug("localizing ftpwise[$url]") if $CPAN::DEBUG; unless ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) { next; } my($host,$dir,$getfile) = ($1,$2,$3); my $timestamp = 0; my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime, $ctime,$blksize,$blocks) = stat($aslocal); $timestamp = $mtime ||= 0; my($netrc) = CPAN::FTP::netrc->new; my($netrcfile) = $netrc->netrc; my($verbose) = $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG ? " -v" : ""; my $targetfile = File::Basename::basename($aslocal); my(@dialog); push( @dialog, "lcd $aslocal_dir", "cd /", map("cd $_", split /\//, $dir), # RFC 1738 "bin", "passive", "get $getfile $targetfile", "quit" ); if (! $netrcfile) { CPAN->debug("No ~/.netrc file found") if $CPAN::DEBUG; } elsif ($netrc->hasdefault || $netrc->contains($host)) { CPAN->debug(sprintf("hasdef[%d]cont($host)[%d]", $netrc->hasdefault, $netrc->contains($host))) if $CPAN::DEBUG; if ($netrc->protected) { my $dialog = join "", map { " $_\n" } @dialog; my $netrc_explain; if ($netrc->contains($host)) { $netrc_explain = "Relying that your .netrc entry for '$host' ". "manages the login"; } else { $netrc_explain = "Relying that your default .netrc entry ". "manages the login"; } $CPAN::Frontend->myprint(qq{ Trying with external ftp to get '$url' $netrc_explain Sending the dialog $dialog } ); $self->talk_ftp("$ftpbin$verbose $host", @dialog); ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal); $mtime ||= 0; if ($mtime > $timestamp) { $CPAN::Frontend->myprint("GOT $aslocal\n"); $ThesiteURL = $ro_url; return $aslocal; } else { $CPAN::Frontend->myprint("Hmm... Still failed!\n"); } return if $CPAN::Signal; } else { $CPAN::Frontend->mywarn(qq{Your $netrcfile is not }. qq{correctly protected.\n}); } } else { $CPAN::Frontend->mywarn("Your ~/.netrc neither contains $host nor does it have a default entry\n"); } # OK, they don't have a valid ~/.netrc. Use 'ftp -n' # then and login manually to host, using e-mail as # password. $CPAN::Frontend->myprint(qq{Issuing "$ftpbin$verbose -n"\n}); unshift( @dialog, "open $host", "user anonymous $Config::Config{'cf_email'}" ); my $dialog = join "", map { " $_\n" } @dialog; $CPAN::Frontend->myprint(qq{ Trying with external ftp to get $url Sending the dialog $dialog } ); $self->talk_ftp("$ftpbin$verbose -n", @dialog); ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal); $mtime ||= 0; if ($mtime > $timestamp) { $CPAN::Frontend->myprint("GOT $aslocal\n"); $ThesiteURL = $ro_url; return $aslocal; } else { $CPAN::Frontend->myprint("Bad luck... Still failed!\n"); } return if $CPAN::Signal; $CPAN::Frontend->mywarn("Can't access URL $url.\n\n"); $CPAN::Frontend->mysleep(2); } # host } # package CPAN::FTP; sub talk_ftp { my($self,$command,@dialog) = @_; my $fh = FileHandle->new; $fh->open("|$command") or die "Couldn't open ftp: $!"; foreach (@dialog) { $fh->print("$_\n") } $fh->close; # Wait for process to complete my $wstatus = $?; my $estatus = $wstatus >> 8; $CPAN::Frontend->myprint(qq{ Subprocess "|$command" returned status $estatus (wstat $wstatus) }) if $wstatus; } # find2perl needs modularization, too, all the following is stolen # from there # CPAN::FTP::ls sub ls { my($self,$name) = @_; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm, $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name); my($perms,%user,%group); my $pname = $name; if ($blocks) { $blocks = int(($blocks + 1) / 2); } else { $blocks = int(($sizemm + 1023) / 1024); } if (-f _) { $perms = '-'; } elsif (-d _) { $perms = 'd'; } elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; } elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; } elsif (-p _) { $perms = 'p'; } elsif (-S _) { $perms = 's'; } else { $perms = 'l'; $pname .= ' -> ' . readlink($_); } my(@rwx) = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx'); my(@moname) = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); my $tmpmode = $mode; my $tmp = $rwx[$tmpmode & 7]; $tmpmode >>= 3; $tmp = $rwx[$tmpmode & 7] . $tmp; $tmpmode >>= 3; $tmp = $rwx[$tmpmode & 7] . $tmp; substr($tmp,2,1) =~ tr/-x/Ss/ if -u _; substr($tmp,5,1) =~ tr/-x/Ss/ if -g _; substr($tmp,8,1) =~ tr/-x/Tt/ if -k _; $perms .= $tmp; my $user = $user{$uid} || $uid; # too lazy to implement lookup my $group = $group{$gid} || $gid; my($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime); my($timeyear); my($moname) = $moname[$mon]; if (-M _ > 365.25 / 2) { $timeyear = $year + 1900; } else { $timeyear = sprintf("%02d:%02d", $hour, $min); } sprintf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n", $ino, $blocks, $perms, $nlink, $user, $group, $sizemm, $moname, $mday, $timeyear, $pname; } 1; �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/CPAN/Index.pm���������������������������������������������������������������������������������0000444�����������������00000053334�15253012307�0007725 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package CPAN::Index; use strict; use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03 $HAVE_REANIMATED $VERSION); $VERSION = "2.29"; @CPAN::Index::ISA = qw(CPAN::Debug); $LAST_TIME ||= 0; $DATE_OF_03 ||= 0; # use constant PROTOCOL => "2.0"; # commented out to avoid warning on upgrade from 1.57 sub PROTOCOL { 2.0 } #-> sub CPAN::Index::force_reload ; sub force_reload { my($class) = @_; $CPAN::Index::LAST_TIME = 0; $class->reload(1); } my @indexbundle = ( { reader => "rd_authindex", dir => "authors", remotefile => '01mailrc.txt.gz', shortlocalfile => '01mailrc.gz', }, { reader => "rd_modpacks", dir => "modules", remotefile => '02packages.details.txt.gz', shortlocalfile => '02packag.gz', }, { reader => "rd_modlist", dir => "modules", remotefile => '03modlist.data.gz', shortlocalfile => '03mlist.gz', }, ); #-> sub CPAN::Index::reload ; sub reload { my($self,$force) = @_; my $time = time; # XXX check if a newer one is available. (We currently read it # from time to time) for ($CPAN::Config->{index_expire}) { $_ = 0.001 unless $_ && $_ > 0.001; } unless (1 || $CPAN::Have_warned->{readmetadatacache}++) { # debug here when CPAN doesn't seem to read the Metadata require Carp; Carp::cluck("META-PROTOCOL[$CPAN::META->{PROTOCOL}]"); } unless ($CPAN::META->{PROTOCOL}) { $self->read_metadata_cache; $CPAN::META->{PROTOCOL} ||= "1.0"; } if ( $CPAN::META->{PROTOCOL} < PROTOCOL ) { # warn "Setting last_time to 0"; $LAST_TIME = 0; # No warning necessary } if ($LAST_TIME + $CPAN::Config->{index_expire}*86400 > $time and ! $force) { # called too often # CPAN->debug("LAST_TIME[$LAST_TIME]index_expire[$CPAN::Config->{index_expire}]time[$time]"); } elsif (0) { # IFF we are developing, it helps to wipe out the memory # between reloads, otherwise it is not what a user expects. undef $CPAN::META; # Neue Gruendlichkeit since v1.52(r1.274) $CPAN::META = CPAN->new; } else { my($debug,$t2); local $LAST_TIME = $time; local $CPAN::META->{PROTOCOL} = PROTOCOL; my $needshort = $^O eq "dos"; INX: for my $indexbundle (@indexbundle) { my $reader = $indexbundle->{reader}; my $localfile = $needshort ? $indexbundle->{shortlocalfile} : $indexbundle->{remotefile}; my $localpath = File::Spec->catfile($indexbundle->{dir}, $localfile); my $remote = join "/", $indexbundle->{dir}, $indexbundle->{remotefile}; my $localized = $self->reload_x($remote, $localpath, $force); $self->$reader($localized); # may die but we let the shell catch it if ($CPAN::DEBUG){ $t2 = time; $debug = "timing reading 01[".($t2 - $time)."]"; $time = $t2; } return if $CPAN::Signal; # this is sometimes lengthy } $self->write_metadata_cache; if ($CPAN::DEBUG){ $t2 = time; $debug .= "03[".($t2 - $time)."]"; $time = $t2; } CPAN->debug($debug) if $CPAN::DEBUG; } if ($CPAN::Config->{build_dir_reuse}) { $self->reanimate_build_dir; } if (CPAN::_sqlite_running()) { $CPAN::SQLite->reload(time => $time, force => $force) if not $LAST_TIME; } $LAST_TIME = $time; $CPAN::META->{PROTOCOL} = PROTOCOL; } #-> sub CPAN::Index::reanimate_build_dir ; sub reanimate_build_dir { my($self) = @_; unless ($CPAN::META->has_inst($CPAN::Config->{yaml_module}||"YAML")) { return; } return if $HAVE_REANIMATED++; my $d = $CPAN::Config->{build_dir}; my $dh = DirHandle->new; opendir $dh, $d or return; # does not exist my $dirent; my $i = 0; my $painted = 0; my $restored = 0; my $start = CPAN::FTP::_mytime(); my @candidates = map { $_->[0] } sort { $b->[1] <=> $a->[1] } map { [ $_, -M File::Spec->catfile($d,$_) ] } grep {/(.+)\.yml$/ && -d File::Spec->catfile($d,$1)} readdir $dh; if ( @candidates ) { $CPAN::Frontend->myprint (sprintf("Reading %d yaml file%s from %s/\n", scalar @candidates, @candidates==1 ? "" : "s", $CPAN::Config->{build_dir} )); DISTRO: for $i (0..$#candidates) { my $dirent = $candidates[$i]; my $y = eval {CPAN->_yaml_loadfile(File::Spec->catfile($d,$dirent), {loadblessed => 1})}; if ($@) { warn "Error while parsing file '$dirent'; error: '$@'"; next DISTRO; } my $c = $y->[0]; if ($c && $c->{perl} && $c->{distribution} && CPAN->_perl_fingerprint($c->{perl})) { my $key = $c->{distribution}{ID}; for my $k (keys %{$c->{distribution}}) { if ($c->{distribution}{$k} && ref $c->{distribution}{$k} && UNIVERSAL::isa($c->{distribution}{$k},"CPAN::Distrostatus")) { $c->{distribution}{$k}{COMMANDID} = $i - @candidates; } } #we tried to restore only if element already #exists; but then we do not work with metadata #turned off. my $do = $CPAN::META->{readwrite}{'CPAN::Distribution'}{$key} = $c->{distribution}; for my $skipper (qw( badtestcnt configure_requires_later configure_requires_later_for force_update later later_for notest should_report sponsored_mods prefs negative_prefs_cache )) { delete $do->{$skipper}; } if ($do->can("tested_ok_but_not_installed")) { if ($do->tested_ok_but_not_installed) { $CPAN::META->is_tested($do->{build_dir},$do->{make_test}{TIME}); } else { next DISTRO; } } $restored++; } $i++; while (($painted/76) < ($i/@candidates)) { $CPAN::Frontend->myprint("."); $painted++; } } } else { $CPAN::Frontend->myprint("Build_dir empty, nothing to restore\n"); } my $took = CPAN::FTP::_mytime() - $start; $CPAN::Frontend->myprint(sprintf( "DONE\nRestored the state of %s (in %.4f secs)\n", $restored || "none", $took, )); } #-> sub CPAN::Index::reload_x ; sub reload_x { my($cl,$wanted,$localname,$force) = @_; $force |= 2; # means we're dealing with an index here CPAN::HandleConfig->load; # we should guarantee loading wherever # we rely on Config XXX $localname ||= $wanted; my $abs_wanted = File::Spec->catfile($CPAN::Config->{'keep_source_where'}, $localname); if ( -f $abs_wanted && -M $abs_wanted < $CPAN::Config->{'index_expire'} && !($force & 1) ) { my $s = $CPAN::Config->{'index_expire'} == 1 ? "" : "s"; $cl->debug(qq{$abs_wanted younger than $CPAN::Config->{'index_expire'} }. qq{day$s. I\'ll use that.}); return $abs_wanted; } else { $force |= 1; # means we're quite serious about it. } return CPAN::FTP->localize($wanted,$abs_wanted,$force); } #-> sub CPAN::Index::rd_authindex ; sub rd_authindex { my($cl, $index_target) = @_; return unless defined $index_target; return if CPAN::_sqlite_running(); my @lines; $CPAN::Frontend->myprint("Reading '$index_target'\n"); local(*FH); tie *FH, 'CPAN::Tarzip', $index_target; local($/) = "\n"; local($_); push @lines, split /\012/ while <FH>; my $i = 0; my $painted = 0; foreach (@lines) { my($userid,$fullname,$email) = m/alias\s+(\S+)\s+\"([^\"\<]*)\s+\<(.*)\>\"/; $fullname ||= $email; if ($userid && $fullname && $email) { my $userobj = $CPAN::META->instance('CPAN::Author',$userid); $userobj->set('FULLNAME' => $fullname, 'EMAIL' => $email); } else { CPAN->debug(sprintf "line[%s]", $_) if $CPAN::DEBUG; } $i++; while (($painted/76) < ($i/@lines)) { $CPAN::Frontend->myprint("."); $painted++; } return if $CPAN::Signal; } $CPAN::Frontend->myprint("DONE\n"); } sub userid { my($self,$dist) = @_; $dist = $self->{'id'} unless defined $dist; my($ret) = $dist =~ m|(?:\w/\w\w/)?([^/]+)/|; $ret; } #-> sub CPAN::Index::rd_modpacks ; sub rd_modpacks { my($self, $index_target) = @_; return unless defined $index_target; return if CPAN::_sqlite_running(); $CPAN::Frontend->myprint("Reading '$index_target'\n"); my $fh = CPAN::Tarzip->TIEHANDLE($index_target); local $_; CPAN->debug(sprintf "start[%d]", time) if $CPAN::DEBUG; my $slurp = ""; my $chunk; while (my $bytes = $fh->READ(\$chunk,8192)) { $slurp.=$chunk; } my @lines = split /\012/, $slurp; CPAN->debug(sprintf "end[%d]", time) if $CPAN::DEBUG; undef $fh; # read header my($line_count,$last_updated); while (@lines) { my $shift = shift(@lines); last if $shift =~ /^\s*$/; $shift =~ /^Line-Count:\s+(\d+)/ and $line_count = $1; $shift =~ /^Last-Updated:\s+(.+)/ and $last_updated = $1; } CPAN->debug("line_count[$line_count]last_updated[$last_updated]") if $CPAN::DEBUG; my $errors = 0; if (not defined $line_count) { $CPAN::Frontend->mywarn(qq{Warning: Your $index_target does not contain a Line-Count header. Please check the validity of the index file by comparing it to more than one CPAN mirror. I'll continue but problems seem likely to happen.\a }); $errors++; $CPAN::Frontend->mysleep(5); } elsif ($line_count != scalar @lines) { $CPAN::Frontend->mywarn(sprintf qq{Warning: Your %s contains a Line-Count header of %d but I see %d lines there. Please check the validity of the index file by comparing it to more than one CPAN mirror. I'll continue but problems seem likely to happen.\a\n}, $index_target, $line_count, scalar(@lines)); } if (not defined $last_updated) { $CPAN::Frontend->mywarn(qq{Warning: Your $index_target does not contain a Last-Updated header. Please check the validity of the index file by comparing it to more than one CPAN mirror. I'll continue but problems seem likely to happen.\a }); $errors++; $CPAN::Frontend->mysleep(5); } else { $CPAN::Frontend ->myprint(sprintf qq{ Database was generated on %s\n}, $last_updated); $DATE_OF_02 = $last_updated; my $age = time; if ($CPAN::META->has_inst('HTTP::Date')) { require HTTP::Date; $age -= HTTP::Date::str2time($last_updated); } else { $CPAN::Frontend->mywarn(" HTTP::Date not available\n"); require Time::Local; my(@d) = $last_updated =~ / (\d+) (\w+) (\d+) (\d+):(\d+):(\d+) /; $d[1] = index("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", $d[1])/4; $age -= $d[1]>=0 ? Time::Local::timegm(@d[5,4,3,0,1,2]) : 0; } $age /= 3600*24; if ($age > 30) { $CPAN::Frontend ->mywarn(sprintf qq{Warning: This index file is %d days old. Please check the host you chose as your CPAN mirror for staleness. I'll continue but problems seem likely to happen.\a\n}, $age); } elsif ($age < -1) { $CPAN::Frontend ->mywarn(sprintf qq{Warning: Your system date is %d days behind this index file! System time: %s Timestamp index file: %s Please fix your system time, problems with the make command expected.\n}, -$age, scalar gmtime, $DATE_OF_02, ); } } # A necessity since we have metadata_cache: delete what isn't # there anymore my $secondtime = $CPAN::META->exists("CPAN::Module","CPAN"); CPAN->debug("secondtime[$secondtime]") if $CPAN::DEBUG; my(%exists); my $i = 0; my $painted = 0; LINE: foreach (@lines) { # before 1.56 we split into 3 and discarded the rest. From # 1.57 we assign remaining text to $comment thus allowing to # influence isa_perl my($mod,$version,$dist,$comment) = split " ", $_, 4; unless ($mod && defined $version && $dist) { require Dumpvalue; my $dv = Dumpvalue->new(tick => '"'); $CPAN::Frontend->mywarn(sprintf "Could not split line[%s]\n", $dv->stringify($_)); if ($errors++ >= 5){ $CPAN::Frontend->mydie("Giving up parsing your $index_target, too many errors"); } next LINE; } my($bundle,$id,$userid); if ($mod eq 'CPAN' && ! ( CPAN::Queue->exists('Bundle::CPAN') || CPAN::Queue->exists('CPAN') ) ) { local($^W)= 0; if ($version > $CPAN::VERSION) { $CPAN::Frontend->mywarn(qq{ New CPAN.pm version (v$version) available. [Currently running version is v$CPAN::VERSION] You might want to try install CPAN reload cpan to both upgrade CPAN.pm and run the new version without leaving the current session. }); #}); $CPAN::Frontend->mysleep(2); $CPAN::Frontend->myprint(qq{\n}); } last if $CPAN::Signal; } elsif ($mod =~ /^Bundle::(.*)/) { $bundle = $1; } if ($bundle) { $id = $CPAN::META->instance('CPAN::Bundle',$mod); # Let's make it a module too, because bundles have so much # in common with modules. # Changed in 1.57_63: seems like memory bloat now without # any value, so commented out # $CPAN::META->instance('CPAN::Module',$mod); } else { # instantiate a module object $id = $CPAN::META->instance('CPAN::Module',$mod); } # Although CPAN prohibits same name with different version the # indexer may have changed the version for the same distro # since the last time ("Force Reindexing" feature) if ($id->cpan_file ne $dist || $id->cpan_version ne $version ) { $userid = $id->userid || $self->userid($dist); $id->set( 'CPAN_USERID' => $userid, 'CPAN_VERSION' => $version, 'CPAN_FILE' => $dist, ); } # instantiate a distribution object if ($CPAN::META->exists('CPAN::Distribution',$dist)) { # we do not need CONTAINSMODS unless we do something with # this dist, so we better produce it on demand. ## my $obj = $CPAN::META->instance( ## 'CPAN::Distribution' => $dist ## ); ## $obj->{CONTAINSMODS}{$mod} = undef; # experimental } else { $CPAN::META->instance( 'CPAN::Distribution' => $dist )->set( 'CPAN_USERID' => $userid, 'CPAN_COMMENT' => $comment, ); } if ($secondtime) { for my $name ($mod,$dist) { # $self->debug("exists name[$name]") if $CPAN::DEBUG; $exists{$name} = undef; } } $i++; while (($painted/76) < ($i/@lines)) { $CPAN::Frontend->myprint("."); $painted++; } return if $CPAN::Signal; } $CPAN::Frontend->myprint("DONE\n"); if ($secondtime) { for my $class (qw(CPAN::Module CPAN::Bundle CPAN::Distribution)) { for my $o ($CPAN::META->all_objects($class)) { next if exists $exists{$o->{ID}}; $CPAN::META->delete($class,$o->{ID}); # CPAN->debug("deleting ID[$o->{ID}] in class[$class]") # if $CPAN::DEBUG; } } } } #-> sub CPAN::Index::rd_modlist ; sub rd_modlist { my($cl,$index_target) = @_; return unless defined $index_target; return if CPAN::_sqlite_running(); $CPAN::Frontend->myprint("Reading '$index_target'\n"); my $fh = CPAN::Tarzip->TIEHANDLE($index_target); local $_; my $slurp = ""; my $chunk; while (my $bytes = $fh->READ(\$chunk,8192)) { $slurp.=$chunk; } my @eval2 = split /\012/, $slurp; while (@eval2) { my $shift = shift(@eval2); if ($shift =~ /^Date:\s+(.*)/) { if ($DATE_OF_03 eq $1) { $CPAN::Frontend->myprint("Unchanged.\n"); return; } ($DATE_OF_03) = $1; } last if $shift =~ /^\s*$/; } push @eval2, q{CPAN::Modulelist->data;}; local($^W) = 0; my($compmt) = Safe->new("CPAN::Safe1"); my($eval2) = join("\n", @eval2); CPAN->debug(sprintf "length of eval2[%d]", length $eval2) if $CPAN::DEBUG; my $ret = $compmt->reval($eval2); Carp::confess($@) if $@; return if $CPAN::Signal; my $i = 0; my $until = keys(%$ret); my $painted = 0; CPAN->debug(sprintf "until[%d]", $until) if $CPAN::DEBUG; for (sort keys %$ret) { my $obj = $CPAN::META->instance("CPAN::Module",$_); delete $ret->{$_}{modid}; # not needed here, maybe elsewhere $obj->set(%{$ret->{$_}}); $i++; while (($painted/76) < ($i/$until)) { $CPAN::Frontend->myprint("."); $painted++; } return if $CPAN::Signal; } $CPAN::Frontend->myprint("DONE\n"); } #-> sub CPAN::Index::write_metadata_cache ; sub write_metadata_cache { my($self) = @_; return unless $CPAN::Config->{'cache_metadata'}; return if CPAN::_sqlite_running(); return unless $CPAN::META->has_usable("Storable"); my $cache; foreach my $k (qw(CPAN::Bundle CPAN::Author CPAN::Module CPAN::Distribution)) { $cache->{$k} = $CPAN::META->{readonly}{$k}; # unsafe meta access, ok } my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata"); $cache->{last_time} = $LAST_TIME; $cache->{DATE_OF_02} = $DATE_OF_02; $cache->{PROTOCOL} = PROTOCOL; $CPAN::Frontend->myprint("Writing $metadata_file\n"); eval { Storable::nstore($cache, $metadata_file) }; $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ?? } #-> sub CPAN::Index::read_metadata_cache ; sub read_metadata_cache { my($self) = @_; return unless $CPAN::Config->{'cache_metadata'}; return if CPAN::_sqlite_running(); return unless $CPAN::META->has_usable("Storable"); my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata"); return unless -r $metadata_file and -f $metadata_file; $CPAN::Frontend->myprint("Reading '$metadata_file'\n"); my $cache; eval { $cache = Storable::retrieve($metadata_file) }; $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ?? if (!$cache || !UNIVERSAL::isa($cache, 'HASH')) { $LAST_TIME = 0; return; } if (exists $cache->{PROTOCOL}) { if (PROTOCOL > $cache->{PROTOCOL}) { $CPAN::Frontend->mywarn(sprintf("Ignoring Metadata cache written ". "with protocol v%s, requiring v%s\n", $cache->{PROTOCOL}, PROTOCOL) ); return; } } else { $CPAN::Frontend->mywarn("Ignoring Metadata cache written ". "with protocol v1.0\n"); return; } my $clcnt = 0; my $idcnt = 0; while(my($class,$v) = each %$cache) { next unless $class =~ /^CPAN::/; $CPAN::META->{readonly}{$class} = $v; # unsafe meta access, ok while (my($id,$ro) = each %$v) { $CPAN::META->{readwrite}{$class}{$id} ||= $class->new(ID=>$id, RO=>$ro); $idcnt++; } $clcnt++; } unless ($clcnt) { # sanity check $CPAN::Frontend->myprint("Warning: Found no data in $metadata_file\n"); return; } if ($idcnt < 1000) { $CPAN::Frontend->myprint("Warning: Found only $idcnt objects ". "in $metadata_file\n"); return; } $CPAN::META->{PROTOCOL} ||= $cache->{PROTOCOL}; # reading does not up or downgrade, but it # does initialize to some protocol $LAST_TIME = $cache->{last_time}; $DATE_OF_02 = $cache->{DATE_OF_02}; $CPAN::Frontend->myprint(" Database was generated on $DATE_OF_02\n") if defined $DATE_OF_02; # An old cache may not contain DATE_OF_02 return; } 1; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/CPAN/Queue.pm���������������������������������������������������������������������������������0000444�����������������00000015724�15253012307�0007743 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- use strict; package CPAN::Queue::Item; # CPAN::Queue::Item::new ; sub new { my($class,@attr) = @_; my $self = bless { @attr }, $class; return $self; } sub as_string { my($self) = @_; $self->{qmod}; } # r => requires, b => build_requires, c => commandline sub reqtype { my($self) = @_; $self->{reqtype}; } sub optional { my($self) = @_; $self->{optional}; } package CPAN::Queue; # One use of the queue is to determine if we should or shouldn't # announce the availability of a new CPAN module # Now we try to use it for dependency tracking. For that to happen # we need to draw a dependency tree and do the leaves first. This can # easily be reached by running CPAN.pm recursively, but we don't want # to waste memory and run into deep recursion. So what we can do is # this: # CPAN::Queue is the package where the queue is maintained. Dependencies # often have high priority and must be brought to the head of the queue, # possibly by jumping the queue if they are already there. My first code # attempt tried to be extremely correct. Whenever a module needed # immediate treatment, I either unshifted it to the front of the queue, # or, if it was already in the queue, I spliced and let it bypass the # others. This became a too correct model that made it impossible to put # an item more than once into the queue. Why would you need that? Well, # you need temporary duplicates as the manager of the queue is a loop # that # # (1) looks at the first item in the queue without shifting it off # # (2) cares for the item # # (3) removes the item from the queue, *even if its agenda failed and # even if the item isn't the first in the queue anymore* (that way # protecting against never ending queues) # # So if an item has prerequisites, the installation fails now, but we # want to retry later. That's easy if we have it twice in the queue. # # I also expect insane dependency situations where an item gets more # than two lives in the queue. Simplest example is triggered by 'install # Foo Foo Foo'. People make this kind of mistakes and I don't want to # get in the way. I wanted the queue manager to be a dumb servant, not # one that knows everything. # # Who would I tell in this model that the user wants to be asked before # processing? I can't attach that information to the module object, # because not modules are installed but distributions. So I'd have to # tell the distribution object that it should ask the user before # processing. Where would the question be triggered then? Most probably # in CPAN::Distribution::rematein. use vars qw{ @All $VERSION }; $VERSION = "5.5003"; # CPAN::Queue::queue_item ; sub queue_item { my($class,@attr) = @_; my $item = "$class\::Item"->new(@attr); $class->qpush($item); return 1; } # CPAN::Queue::qpush ; sub qpush { my($class,$obj) = @_; push @All, $obj; CPAN->debug(sprintf("in new All[%s]", join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All), )) if $CPAN::DEBUG; } # CPAN::Queue::first ; sub first { my $obj = $All[0]; $obj; } # CPAN::Queue::delete_first ; sub delete_first { my($class,$what) = @_; my $i; for my $i (0..$#All) { if ( $All[$i]->{qmod} eq $what ) { splice @All, $i, 1; last; } } CPAN->debug(sprintf("after delete_first mod[%s] All[%s]", $what, join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All) )) if $CPAN::DEBUG; } # CPAN::Queue::jumpqueue ; sub jumpqueue { my $class = shift; my @what = @_; CPAN->debug(sprintf("before jumpqueue All[%s] what[%s]", join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All), join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @what), )) if $CPAN::DEBUG; unless (defined $what[0]{reqtype}) { # apparently it was not the Shell that sent us this enquiry, # treat it as commandline $what[0]{reqtype} = "c"; } my $inherit_reqtype = $what[0]{reqtype} =~ /^(c|r)$/ ? "r" : "b"; WHAT: for my $what_tuple (@what) { my($qmod,$reqtype,$optional) = @$what_tuple{qw(qmod reqtype optional)}; if ($reqtype eq "r" && $inherit_reqtype eq "b" ) { $reqtype = "b"; } my $jumped = 0; for (my $i=0; $i<$#All;$i++) { #prevent deep recursion if ($All[$i]{qmod} eq $qmod) { $jumped++; } } # high jumped values are normal for popular modules when # dealing with large bundles: XML::Simple, # namespace::autoclean, UNIVERSAL::require CPAN->debug("qmod[$qmod]jumped[$jumped]") if $CPAN::DEBUG; my $obj = "$class\::Item"->new( qmod => $qmod, reqtype => $reqtype, optional => !! $optional, ); unshift @All, $obj; } CPAN->debug(sprintf("after jumpqueue All[%s]", join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All) )) if $CPAN::DEBUG; } # CPAN::Queue::exists ; sub exists { my($self,$what) = @_; my @all = map { $_->{qmod} } @All; my $exists = grep { $_->{qmod} eq $what } @All; # warn "in exists what[$what] all[@all] exists[$exists]"; $exists; } # CPAN::Queue::delete ; sub delete { my($self,$mod) = @_; @All = grep { $_->{qmod} ne $mod } @All; CPAN->debug(sprintf("after delete mod[%s] All[%s]", $mod, join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All) )) if $CPAN::DEBUG; } # CPAN::Queue::nullify_queue ; sub nullify_queue { @All = (); } # CPAN::Queue::size ; sub size { return scalar @All; } sub reqtype_of { my($self,$mod) = @_; my $best = ""; for my $item (grep { $_->{qmod} eq $mod } @All) { my $c = $item->{reqtype}; if ($c eq "c") { $best = $c; last; } elsif ($c eq "r") { $best = $c; } elsif ($c eq "b") { if ($best eq "") { $best = $c; } } else { die "Panic: in reqtype_of: reqtype[$c] seen, should never happen"; } } return $best; } sub iterator { my $i = 0; return sub { until ($All[$i] || $i > $#All) { $i++; } return if $i > $#All; return $All[$i++] }; } 1; __END__ =head1 NAME CPAN::Queue - internal queue support for CPAN.pm =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut ��������������������������������������������perl5/CPAN/API/HOWTO.pod����������������������������������������������������������������������������0000444�����������������00000002053�15253012307�0010325 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=head1 NAME CPAN::API::HOWTO - a recipe book for programming with CPAN.pm =head1 RECIPES All of these recipes assume that you have put "use CPAN" at the top of your program. =head2 What distribution contains a particular module? my $distribution = CPAN::Shell->expand( "Module", "Data::UUID" )->distribution()->pretty_id(); This returns a string of the form "AUTHORID/TARBALL". If you want the full path and filename to this distribution on a CPAN mirror, then it is C<.../authors/id/A/AU/AUTHORID/TARBALL>. =head2 What modules does a particular distribution contain? CPAN::Index->reload(); my @modules = CPAN::Shell->expand( "Distribution", "JHI/Graph-0.83.tar.gz" )->containsmods(); You may also refer to a distribution in the form A/AU/AUTHORID/TARBALL. =head1 SEE ALSO the main CPAN.pm documentation =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L<http://www.perl.com/perl/misc/Artistic.html> =head1 AUTHOR David Cantrell =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/CPAN/Distribution.pm��������������������������������������������������������������������������0000444�����������������00000545733�15253012307�0011346 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: package CPAN::Distribution; use strict; use Cwd qw(chdir); use CPAN::Distroprefs; use CPAN::InfoObj; use File::Path (); use POSIX ":sys_wait_h"; @CPAN::Distribution::ISA = qw(CPAN::InfoObj); use vars qw($VERSION); $VERSION = "2.34"; my $run_allow_installing_within_test = 1; # boolean; either in test or in install, there is no third option # no prepare, because prepare is not a command on the shell command line # TODO: clear instance cache on reload my %instance; for my $method (qw(get make test install)) { no strict 'refs'; for my $prefix (qw(pre post)) { my $hookname = sprintf "%s_%s", $prefix, $method; *$hookname = sub { my($self) = @_; for my $plugin (@{$CPAN::Config->{plugin_list}}) { my($plugin_proper,$args) = split /=/, $plugin, 2; $args = "" unless defined $args; if ($CPAN::META->has_inst($plugin_proper)){ my @args = split /,/, $args; $instance{$plugin} ||= $plugin_proper->new(@args); if ($instance{$plugin}->can($hookname)) { $instance{$plugin}->$hookname($self); } } else { $CPAN::Frontend->mydie("Plugin '$plugin_proper' not found for hook '$hookname'"); } } }; } } # Accessors sub cpan_comment { my $self = shift; my $ro = $self->ro or return; $ro->{CPAN_COMMENT} } #-> CPAN::Distribution::undelay sub undelay { my $self = shift; for my $delayer ( "configure_requires_later", "configure_requires_later_for", "later", "later_for", ) { delete $self->{$delayer}; } } #-> CPAN::Distribution::is_dot_dist sub is_dot_dist { my($self) = @_; return substr($self->id,-1,1) eq "."; } # add the A/AN/ stuff #-> CPAN::Distribution::normalize sub normalize { my($self,$s) = @_; $s = $self->id unless defined $s; if (substr($s,-1,1) eq ".") { # using a global because we are sometimes called as static method if (!$CPAN::META->{LOCK} && !$CPAN::Have_warned->{"$s is unlocked"}++ ) { $CPAN::Frontend->mywarn("You are visiting the local directory '$s' without lock, take care that concurrent processes do not do likewise.\n"); $CPAN::Frontend->mysleep(1); } if ($s eq ".") { $s = "$CPAN::iCwd/."; } elsif (File::Spec->file_name_is_absolute($s)) { } elsif (File::Spec->can("rel2abs")) { $s = File::Spec->rel2abs($s); } else { $CPAN::Frontend->mydie("Your File::Spec is too old, please upgrade File::Spec"); } CPAN->debug("s[$s]") if $CPAN::DEBUG; unless ($CPAN::META->exists("CPAN::Distribution", $s)) { for ($CPAN::META->instance("CPAN::Distribution", $s)) { $_->{build_dir} = $s; $_->{archived} = "local_directory"; $_->{unwrapped} = CPAN::Distrostatus->new("YES -- local_directory"); } } } elsif ( $s =~ tr|/|| == 1 or $s !~ m|[A-Z]/[A-Z-0-9]{2}/[A-Z-0-9]{2,}/| ) { return $s if $s =~ m:^N/A|^Contact Author: ; $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4|; CPAN->debug("s[$s]") if $CPAN::DEBUG; } $s; } #-> sub CPAN::Distribution::author ; sub author { my($self) = @_; my($authorid); if (substr($self->id,-1,1) eq ".") { $authorid = "LOCAL"; } else { ($authorid) = $self->pretty_id =~ /^([\w\-]+)/; } CPAN::Shell->expand("Author",$authorid); } # tries to get the yaml from CPAN instead of the distro itself: # EXPERIMENTAL, UNDOCUMENTED AND UNTESTED, for Tels sub fast_yaml { my($self) = @_; my $meta = $self->pretty_id; $meta =~ s/\.(tar.gz|tgz|zip|tar.bz2)/.meta/; my(@ls) = CPAN::Shell->globls($meta); my $norm = $self->normalize($meta); my($local_file); my($local_wanted) = File::Spec->catfile( $CPAN::Config->{keep_source_where}, "authors", "id", split(/\//,$norm) ); $self->debug("Doing localize") if $CPAN::DEBUG; unless ($local_file = CPAN::FTP->localize("authors/id/$norm", $local_wanted)) { $CPAN::Frontend->mydie("Giving up on downloading yaml file '$local_wanted'\n"); } my $yaml = CPAN->_yaml_loadfile($local_file)->[0]; } #-> sub CPAN::Distribution::cpan_userid sub cpan_userid { my $self = shift; if ($self->{ID} =~ m{[A-Z]/[A-Z\-]{2}/([A-Z\-]+)/}) { return $1; } return $self->SUPER::cpan_userid; } #-> sub CPAN::Distribution::pretty_id sub pretty_id { my $self = shift; my $id = $self->id; return $id unless $id =~ m|^./../|; substr($id,5); } #-> sub CPAN::Distribution::base_id sub base_id { my $self = shift; my $id = $self->pretty_id(); my $base_id = File::Basename::basename($id); $base_id =~ s{\.(?:tar\.(bz2|gz|Z)|t(?:gz|bz)|zip)$}{}i; return $base_id; } #-> sub CPAN::Distribution::tested_ok_but_not_installed sub tested_ok_but_not_installed { my $self = shift; return ( $self->{make_test} && $self->{build_dir} && (UNIVERSAL::can($self->{make_test},"failed") ? ! $self->{make_test}->failed : $self->{make_test} =~ /^YES/ ) && ( !$self->{install} || $self->{install}->failed ) ); } # mark as dirty/clean for the sake of recursion detection. $color=1 # means "in use", $color=0 means "not in use anymore". $color=2 means # we have determined prereqs now and thus insist on passing this # through (at least) once again. #-> sub CPAN::Distribution::color_cmd_tmps ; sub color_cmd_tmps { my($self) = shift; my($depth) = shift || 0; my($color) = shift || 0; my($ancestors) = shift || []; # a distribution needs to recurse into its prereq_pms $self->debug("color_cmd_tmps[$depth,$color,@$ancestors]") if $CPAN::DEBUG; return if exists $self->{incommandcolor} && $color==1 && $self->{incommandcolor}==$color; $CPAN::MAX_RECURSION||=0; # silence 'once' warnings if ($depth>=$CPAN::MAX_RECURSION) { my $e = CPAN::Exception::RecursiveDependency->new($ancestors); if ($e->is_resolvable) { return $self->{incommandcolor}=2; } else { die $e; } } # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; my $prereq_pm = $self->prereq_pm; if (defined $prereq_pm) { # XXX also optional_req & optional_breq? -- xdg, 2012-04-01 # A: no, optional deps may recurse -- ak, 2014-05-07 PREREQ: for my $pre (sort( keys %{$prereq_pm->{requires}||{}}, keys %{$prereq_pm->{build_requires}||{}}, )) { next PREREQ if $pre eq "perl"; my $premo; unless ($premo = CPAN::Shell->expand("Module",$pre)) { $CPAN::Frontend->mywarn("prerequisite module[$pre] not known\n"); $CPAN::Frontend->mysleep(0.2); next PREREQ; } $premo->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]); } } if ($color==0) { delete $self->{sponsored_mods}; # as we are at the end of a command, we'll give up this # reminder of a broken test. Other commands may test this guy # again. Maybe 'badtestcnt' should be renamed to # 'make_test_failed_within_command'? delete $self->{badtestcnt}; } $self->{incommandcolor} = $color; } #-> sub CPAN::Distribution::as_string ; sub as_string { my $self = shift; $self->containsmods; $self->upload_date; $self->SUPER::as_string(@_); } #-> sub CPAN::Distribution::containsmods ; sub containsmods { my $self = shift; return sort keys %{$self->{CONTAINSMODS}} if exists $self->{CONTAINSMODS}; my $dist_id = $self->{ID}; for my $mod ($CPAN::META->all_objects("CPAN::Module")) { my $mod_file = $mod->cpan_file or next; my $mod_id = $mod->{ID} or next; # warn "mod_file[$mod_file] dist_id[$dist_id] mod_id[$mod_id]"; # sleep 1; if ($CPAN::Signal) { delete $self->{CONTAINSMODS}; return; } $self->{CONTAINSMODS}{$mod_id} = undef if $mod_file eq $dist_id; } sort keys %{$self->{CONTAINSMODS}||={}}; } #-> sub CPAN::Distribution::upload_date ; sub upload_date { my $self = shift; return $self->{UPLOAD_DATE} if exists $self->{UPLOAD_DATE}; my(@local_wanted) = split(/\//,$self->id); my $filename = pop @local_wanted; push @local_wanted, "CHECKSUMS"; my $author = CPAN::Shell->expand("Author",$self->cpan_userid); return unless $author; my @dl = $author->dir_listing(\@local_wanted,0,$CPAN::Config->{show_upload_date}); return unless @dl; my($dirent) = grep { $_->[2] eq $filename } @dl; # warn sprintf "dirent[%s]id[%s]", $dirent, $self->id; return unless $dirent->[1]; return $self->{UPLOAD_DATE} = $dirent->[1]; } #-> sub CPAN::Distribution::uptodate ; sub uptodate { my($self) = @_; my $c; foreach $c ($self->containsmods) { my $obj = CPAN::Shell->expandany($c); unless ($obj->uptodate) { my $id = $self->pretty_id; $self->debug("$id not uptodate due to $c") if $CPAN::DEBUG; return 0; } } return 1; } #-> sub CPAN::Distribution::called_for ; sub called_for { my($self,$id) = @_; $self->{CALLED_FOR} = $id if defined $id; return $self->{CALLED_FOR}; } #-> sub CPAN::Distribution::shortcut_get ; # return values: undef means don't shortcut; 0 means shortcut as fail; # and 1 means shortcut as success sub shortcut_get { my ($self) = @_; if (exists $self->{cleanup_after_install_done}) { if ($self->{force_update}) { delete $self->{cleanup_after_install_done}; } else { my $id = $self->{CALLED_FOR} || $self->pretty_id; return $self->success( "Has already been *installed and cleaned up in the staging area* within this session, will not work on it again; if you really want to start over, try something like `force get $id`" ); } } if (my $why = $self->check_disabled) { $self->{unwrapped} = CPAN::Distrostatus->new("NO $why"); # XXX why is this goodbye() instead of just print/warn? # Alternatively, should other print/warns here be goodbye()? # -- xdg, 2012-04-05 return $self->goodbye("[disabled] -- NA $why"); } $self->debug("checking already unwrapped[$self->{ID}]") if $CPAN::DEBUG; if (exists $self->{build_dir} && -d $self->{build_dir}) { # this deserves print, not warn: return $self->success("Has already been unwrapped into directory ". "$self->{build_dir}" ); } # XXX I'm not sure this should be here because it's not really # a test for whether get should continue or return; this is # a side effect -- xdg, 2012-04-05 $self->debug("checking missing build_dir[$self->{ID}]") if $CPAN::DEBUG; if (exists $self->{build_dir} && ! -d $self->{build_dir}){ # we have lost it. $self->fforce(""); # no method to reset all phases but not set force (dodge) return undef; # no shortcut } # although we talk about 'force' we shall not test on # force directly. New model of force tries to refrain from # direct checking of force. $self->debug("checking unwrapping error[$self->{ID}]") if $CPAN::DEBUG; if ( exists $self->{unwrapped} and ( UNIVERSAL::can($self->{unwrapped},"failed") ? $self->{unwrapped}->failed : $self->{unwrapped} =~ /^NO/ ) ) { return $self->goodbye("Unwrapping had some problem, won't try again without force"); } return undef; # no shortcut } #-> sub CPAN::Distribution::get ; sub get { my($self) = @_; $self->pre_get(); $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG; if (my $goto = $self->prefs->{goto}) { $self->post_get(); return $self->goto($goto); } if ( defined( my $sc = $self->shortcut_get) ) { $self->post_get(); return $sc; } local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) ? $ENV{PERL5LIB} : ($ENV{PERLLIB} || ""); local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : ""; # local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # get $CPAN::META->set_perl5lib; local $ENV{MAKEFLAGS}; # protect us from outer make calls my $sub_wd = CPAN::anycwd(); # for cleaning up as good as possible my($local_file); # XXX I don't think this check needs to be here, as it # is already checked in shortcut_get() -- xdg, 2012-04-05 unless ($self->{build_dir} && -d $self->{build_dir}) { $self->get_file_onto_local_disk; if ($CPAN::Signal){ $self->post_get(); return; } $self->check_integrity; if ($CPAN::Signal){ $self->post_get(); return; } (my $packagedir,$local_file) = $self->run_preps_on_packagedir; # XXX why is this check here? -- xdg, 2012-04-08 if (exists $self->{writemakefile} && ref $self->{writemakefile} && $self->{writemakefile}->can("failed") && $self->{writemakefile}->failed) { # $self->post_get(); return; } $packagedir ||= $self->{build_dir}; $self->{build_dir} = $packagedir; } # XXX should this move up to after run_preps_on_packagedir? # Otherwise, failing writemakefile can return without # a $CPAN::Signal check -- xdg, 2012-04-05 if ($CPAN::Signal) { $self->safe_chdir($sub_wd); $self->post_get(); return; } unless ($self->patch){ $self->post_get(); return; } $self->store_persistent_state; $self->post_get(); return 1; # success } #-> CPAN::Distribution::get_file_onto_local_disk sub get_file_onto_local_disk { my($self) = @_; return if $self->is_dot_dist; my($local_file); my($local_wanted) = File::Spec->catfile( $CPAN::Config->{keep_source_where}, "authors", "id", split(/\//,$self->id) ); $self->debug("Doing localize") if $CPAN::DEBUG; unless ($local_file = CPAN::FTP->localize("authors/id/$self->{ID}", $local_wanted)) { my $note = ""; if ($CPAN::Index::DATE_OF_02) { $note = "Note: Current database in memory was generated ". "on $CPAN::Index::DATE_OF_02\n"; } $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n$note"); } $self->debug("local_wanted[$local_wanted]local_file[$local_file]") if $CPAN::DEBUG; $self->{localfile} = $local_file; } #-> CPAN::Distribution::check_integrity sub check_integrity { my($self) = @_; return if $self->is_dot_dist; if ($CPAN::META->has_inst("Digest::SHA")) { $self->debug("Digest::SHA is installed, verifying"); $self->verifyCHECKSUM; } else { $self->debug("Digest::SHA is NOT installed"); } } #-> CPAN::Distribution::run_preps_on_packagedir sub run_preps_on_packagedir { my($self) = @_; return if $self->is_dot_dist; $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); # unsafe meta access, ok my $builddir = $CPAN::META->{cachemgr}->dir; # unsafe meta access, ok $self->safe_chdir($builddir); $self->debug("Removing tmp-$$") if $CPAN::DEBUG; File::Path::rmtree("tmp-$$"); unless (mkdir "tmp-$$", 0755) { $CPAN::Frontend->unrecoverable_error(<<EOF); Couldn't mkdir '$builddir/tmp-$$': $! Cannot continue: Please find the reason why I cannot make the directory $builddir/tmp-$$ and fix the problem, then retry. EOF } if ($CPAN::Signal) { return; } $self->safe_chdir("tmp-$$"); # # Unpack the goods # my $local_file = $self->{localfile}; my $ct = eval{CPAN::Tarzip->new($local_file)}; unless ($ct) { $self->{unwrapped} = CPAN::Distrostatus->new("NO"); delete $self->{build_dir}; return; } if ($local_file =~ /(\.tar\.(bz2|gz|Z)|\.tgz)(?!\n)\Z/i) { $self->{was_uncompressed}++ unless eval{$ct->gtest()}; $self->untar_me($ct); } elsif ( $local_file =~ /\.zip(?!\n)\Z/i ) { $self->unzip_me($ct); } else { $self->{was_uncompressed}++ unless $ct->gtest(); $local_file = $self->handle_singlefile($local_file); } # we are still in the tmp directory! # Let's check if the package has its own directory. my $dh = DirHandle->new(File::Spec->curdir) or Carp::croak("Couldn't opendir .: $!"); my @readdir = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh->read; ### MAC?? if (grep { $_ eq "pax_global_header" } @readdir) { $CPAN::Frontend->mywarn("Your (un)tar seems to have extracted a file named 'pax_global_header' from the tarball '$local_file'. This is almost certainly an error. Please upgrade your tar. I'll ignore this file for now. See also http://rt.cpan.org/Ticket/Display.html?id=38932\n"); $CPAN::Frontend->mysleep(5); @readdir = grep { $_ ne "pax_global_header" } @readdir; } $dh->close; my $tdir_base; my $from_dir; my @dirents; if (@readdir == 1 && -d $readdir[0]) { $tdir_base = $readdir[0]; $from_dir = File::Spec->catdir(File::Spec->curdir,$readdir[0]); my($mode) = (stat $from_dir)[2]; chmod $mode | 00755, $from_dir; # JONATHAN/Math-Calculus-TaylorSeries-0.1.tar.gz has 0644 my $dh2; unless ($dh2 = DirHandle->new($from_dir)) { my $why = sprintf ( "Couldn't opendir '%s', mode '%o': %s", $from_dir, $mode, $!, ); $CPAN::Frontend->mywarn("$why\n"); $self->{writemakefile} = CPAN::Distrostatus->new("NO -- $why"); return; } @dirents = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh2->read; ### MAC?? } else { my $userid = $self->cpan_userid; CPAN->debug("userid[$userid]"); if (!$userid or $userid eq "N/A") { $userid = "anon"; } $tdir_base = $userid; $from_dir = File::Spec->curdir; @dirents = @readdir; } my $packagedir; my $eexist = ($CPAN::META->has_usable("Errno") && defined &Errno::EEXIST) ? &Errno::EEXIST : undef; for(my $suffix = 0; ; $suffix++) { $packagedir = File::Spec->catdir($builddir, "$tdir_base-$suffix"); my $parent = $builddir; mkdir($packagedir, 0777) and last; if((defined($eexist) && $! != $eexist) || $suffix == 999) { $CPAN::Frontend->mydie("Cannot create directory $packagedir: $!\n"); } } my $f; for $f (@dirents) { # is already without "." and ".." my $from = File::Spec->catfile($from_dir,$f); my($mode) = (stat $from)[2]; chmod $mode | 00755, $from if -d $from; # OTTO/Pod-Trial-LinkImg-0.005.tgz my $to = File::Spec->catfile($packagedir,$f); unless (File::Copy::move($from,$to)) { my $err = $!; $from = File::Spec->rel2abs($from); $CPAN::Frontend->mydie( "Couldn't move $from to $to: $err; #82295? ". "CPAN::VERSION=$CPAN::VERSION; ". "File::Copy::VERSION=$File::Copy::VERSION; ". "$from " . (-e $from ? "exists; " : "does not exist; "). "$to " . (-e $to ? "exists; " : "does not exist; "). "cwd=" . CPAN::anycwd() . ";" ); } } $self->{build_dir} = $packagedir; $self->safe_chdir($builddir); File::Path::rmtree("tmp-$$"); $self->safe_chdir($packagedir); $self->_signature_business(); $self->safe_chdir($builddir); return($packagedir,$local_file); } #-> sub CPAN::Distribution::pick_meta_file ; sub pick_meta_file { my($self, $filter) = @_; $filter = '.' unless defined $filter; my $build_dir; unless ($build_dir = $self->{build_dir}) { # maybe permission on build_dir was missing $CPAN::Frontend->mywarn("Warning: cannot determine META.yml without a build_dir.\n"); return; } my $has_cm = $CPAN::META->has_usable("CPAN::Meta"); my $has_pcm = $CPAN::META->has_usable("Parse::CPAN::Meta"); my @choices; push @choices, 'MYMETA.json' if $has_cm; push @choices, 'MYMETA.yml' if $has_cm || $has_pcm; push @choices, 'META.json' if $has_cm; push @choices, 'META.yml' if $has_cm || $has_pcm; for my $file ( grep { /$filter/ } @choices ) { my $path = File::Spec->catfile( $build_dir, $file ); return $path if -f $path } return; } #-> sub CPAN::Distribution::parse_meta_yml ; sub parse_meta_yml { my($self, $yaml) = @_; $self->debug(sprintf("parse_meta_yml[%s]",$yaml||'undef')) if $CPAN::DEBUG; my $build_dir = $self->{build_dir} or die "PANIC: cannot parse yaml without a build_dir"; $yaml ||= File::Spec->catfile($build_dir,"META.yml"); $self->debug("meta[$yaml]") if $CPAN::DEBUG; return unless -f $yaml; my $early_yaml; eval { $CPAN::META->has_inst("Parse::CPAN::Meta") or die; die "Parse::CPAN::Meta yaml too old" unless $Parse::CPAN::Meta::VERSION >= "1.40"; # P::C::M returns last document in scalar context $early_yaml = Parse::CPAN::Meta::LoadFile($yaml); }; unless ($early_yaml) { eval { $early_yaml = CPAN->_yaml_loadfile($yaml)->[0]; }; } $self->debug(sprintf("yaml[%s]", $early_yaml || 'UNDEF')) if $CPAN::DEBUG; $self->debug($early_yaml) if $CPAN::DEBUG && $early_yaml; if (!ref $early_yaml or ref $early_yaml ne "HASH"){ # fix rt.cpan.org #95271 $CPAN::Frontend->mywarn("The content of '$yaml' is not a HASH reference. Cannot use it.\n"); return {}; } return $early_yaml || undef; } #-> sub CPAN::Distribution::satisfy_requires ; # return values: 1 means requirements are satisfied; # and 0 means not satisfied (and maybe queued) sub satisfy_requires { my ($self) = @_; $self->debug("Entering satisfy_requires") if $CPAN::DEBUG; if (my @prereq = $self->unsat_prereq("later")) { if ($CPAN::DEBUG){ require Data::Dumper; my $prereq = Data::Dumper->new(\@prereq)->Terse(1)->Indent(0)->Dump; $self->debug("unsatisfied[$prereq]"); } if ($prereq[0][0] eq "perl") { my $need = "requires perl '$prereq[0][1]'"; my $id = $self->pretty_id; $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n"); $self->{make} = CPAN::Distrostatus->new("NO $need"); $self->store_persistent_state; die "[prereq] -- NOT OK\n"; } else { my $follow = eval { $self->follow_prereqs("later",@prereq); }; if (0) { } elsif ($follow) { return; # we need deps } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) { $CPAN::Frontend->mywarn($@); die "[depend] -- NOT OK\n"; } } } return 1; } #-> sub CPAN::Distribution::satisfy_configure_requires ; # return values: 1 means configure_require is satisfied; # and 0 means not satisfied (and maybe queued) sub satisfy_configure_requires { my($self) = @_; $self->debug("Entering satisfy_configure_requires") if $CPAN::DEBUG; my $enable_configure_requires = 1; if (!$enable_configure_requires) { return 1; # if we return 1 here, everything is as before we introduced # configure_requires that means, things with # configure_requires simply fail, all others succeed } my @prereq = $self->unsat_prereq("configure_requires_later"); $self->debug(sprintf "configure_requires[%s]", join(",",map {join "/",@$_} @prereq)) if $CPAN::DEBUG; return 1 unless @prereq; $self->debug(\@prereq) if $CPAN::DEBUG; if ($self->{configure_requires_later}) { for my $k (sort keys %{$self->{configure_requires_later_for}||{}}) { if ($self->{configure_requires_later_for}{$k}>1) { my $type = ""; for my $p (@prereq) { if ($p->[0] eq $k) { $type = $p->[1]; } } $type = " $type" if $type; $CPAN::Frontend->mywarn("Warning: unmanageable(?) prerequisite $k$type"); sleep 1; } } } if ($prereq[0][0] eq "perl") { my $need = "requires perl '$prereq[0][1]'"; my $id = $self->pretty_id; $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n"); $self->{make} = CPAN::Distrostatus->new("NO $need"); $self->store_persistent_state; return $self->goodbye("[prereq] -- NOT OK"); } else { my $follow = eval { $self->follow_prereqs("configure_requires_later", @prereq); }; if (0) { } elsif ($follow) { return; # we need deps } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) { $CPAN::Frontend->mywarn($@); return $self->goodbye("[depend] -- NOT OK"); } else { return $self->goodbye("[configure_requires] -- NOT OK"); } } die "never reached"; } #-> sub CPAN::Distribution::choose_MM_or_MB ; sub choose_MM_or_MB { my($self) = @_; $self->satisfy_configure_requires() or return; my $local_file = $self->{localfile}; my($mpl) = File::Spec->catfile($self->{build_dir},"Makefile.PL"); my($mpl_exists) = -f $mpl; unless ($mpl_exists) { # NFS has been reported to have racing problems after the # renaming of a directory in some environments. # This trick helps. $CPAN::Frontend->mysleep(1); my $mpldh = DirHandle->new($self->{build_dir}) or Carp::croak("Couldn't opendir $self->{build_dir}: $!"); $mpl_exists = grep /^Makefile\.PL$/, $mpldh->read; $mpldh->close; } my $prefer_installer = "eumm"; # eumm|mb if (-f File::Spec->catfile($self->{build_dir},"Build.PL")) { if ($mpl_exists) { # they *can* choose if ($CPAN::META->has_inst("Module::Build")) { $prefer_installer = CPAN::HandleConfig->prefs_lookup( $self, q{prefer_installer} ); # M::B <= 0.35 left a DATA handle open that # causes problems upgrading M::B on Windows close *Module::Build::Version::DATA if fileno *Module::Build::Version::DATA; } } else { $prefer_installer = "mb"; } } if (lc($prefer_installer) eq "rand") { $prefer_installer = rand()<.5 ? "eumm" : "mb"; } if (lc($prefer_installer) eq "mb") { $self->{modulebuild} = 1; } elsif ($self->{archived} eq "patch") { # not an edge case, nothing to install for sure my $why = "A patch file cannot be installed"; $CPAN::Frontend->mywarn("Refusing to handle this file: $why\n"); $self->{writemakefile} = CPAN::Distrostatus->new("NO $why"); } elsif (! $mpl_exists) { $self->_edge_cases($mpl,$local_file); } if ($self->{build_dir} && $CPAN::Config->{build_dir_reuse} ) { $self->store_persistent_state; } return $self; } # see also reanimate_build_dir #-> CPAN::Distribution::store_persistent_state sub store_persistent_state { my($self) = @_; my $dir = $self->{build_dir}; unless (defined $dir && length $dir) { my $id = $self->id; $CPAN::Frontend->mywarnonce("build_dir of $id is not known, ". "will not store persistent state\n"); return; } # self-build-dir my $sbd = Cwd::realpath( File::Spec->catdir($dir, File::Spec->updir ()) ); # config-build-dir my $cbd = Cwd::realpath( # the catdir is a workaround for bug https://rt.cpan.org/Ticket/Display.html?id=101283 File::Spec->catdir($CPAN::Config->{build_dir}, File::Spec->curdir()) ); unless ($sbd eq $cbd) { $CPAN::Frontend->mywarnonce("Directory '$dir' not below $CPAN::Config->{build_dir}, ". "will not store persistent state\n"); return; } my $file = sprintf "%s.yml", $dir; my $yaml_module = CPAN::_yaml_module(); if ($CPAN::META->has_inst($yaml_module)) { CPAN->_yaml_dumpfile( $file, { time => time, perl => CPAN::_perl_fingerprint(), distribution => $self, } ); } else { $CPAN::Frontend->myprintonce("'$yaml_module' not installed, ". "will not store persistent state\n"); } } #-> CPAN::Distribution::try_download sub try_download { my($self,$patch) = @_; my $norm = $self->normalize($patch); my($local_wanted) = File::Spec->catfile( $CPAN::Config->{keep_source_where}, "authors", "id", split(/\//,$norm), ); $self->debug("Doing localize") if $CPAN::DEBUG; return CPAN::FTP->localize("authors/id/$norm", $local_wanted); } { my $stdpatchargs = ""; #-> CPAN::Distribution::patch sub patch { my($self) = @_; $self->debug("checking patches id[$self->{ID}]") if $CPAN::DEBUG; my $patches = $self->prefs->{patches}; $patches ||= ""; $self->debug("patches[$patches]") if $CPAN::DEBUG; if ($patches) { return unless @$patches; $self->safe_chdir($self->{build_dir}); CPAN->debug("patches[$patches]") if $CPAN::DEBUG; my $patchbin = $CPAN::Config->{patch}; unless ($patchbin && length $patchbin) { $CPAN::Frontend->mydie("No external patch command configured\n\n". "Please run 'o conf init /patch/'\n\n"); } unless (MM->maybe_command($patchbin)) { $CPAN::Frontend->mydie("No external patch command available\n\n". "Please run 'o conf init /patch/'\n\n"); } $patchbin = CPAN::HandleConfig->safe_quote($patchbin); local $ENV{PATCH_GET} = 0; # formerly known as -g0 unless ($stdpatchargs) { my $system = "$patchbin --version |"; local *FH; open FH, $system or die "Could not fork '$system': $!"; local $/ = "\n"; my $pversion; PARSEVERSION: while (<FH>) { if (/^patch\s+([\d\.]+)/) { $pversion = $1; last PARSEVERSION; } } if ($pversion) { $stdpatchargs = "-N --fuzz=3"; } else { $stdpatchargs = "-N"; } } my $countedpatches = @$patches == 1 ? "1 patch" : (scalar @$patches . " patches"); $CPAN::Frontend->myprint("Applying $countedpatches:\n"); my $patches_dir = $CPAN::Config->{patches_dir}; for my $patch (@$patches) { if ($patches_dir && !File::Spec->file_name_is_absolute($patch)) { my $f = File::Spec->catfile($patches_dir, $patch); $patch = $f if -f $f; } unless (-f $patch) { CPAN->debug("not on disk: patch[$patch]") if $CPAN::DEBUG; if (my $trydl = $self->try_download($patch)) { $patch = $trydl; } else { my $fail = "Could not find patch '$patch'"; $CPAN::Frontend->mywarn("$fail; cannot continue\n"); $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail"); delete $self->{build_dir}; return; } } $CPAN::Frontend->myprint(" $patch\n"); my $readfh = CPAN::Tarzip->TIEHANDLE($patch); my $pcommand; my($ppp,$pfiles) = $self->_patch_p_parameter($readfh); if ($ppp eq "applypatch") { $pcommand = "$CPAN::Config->{applypatch} -verbose"; } else { my $thispatchargs = join " ", $stdpatchargs, $ppp; $pcommand = "$patchbin $thispatchargs"; require Config; # usually loaded from CPAN.pm if ($Config::Config{osname} eq "solaris") { # native solaris patch cannot patch readonly files for my $file (@{$pfiles||[]}) { my @stat = stat $file or next; chmod $stat[2] | 0600, $file; # may fail } } } $readfh = CPAN::Tarzip->TIEHANDLE($patch); # open again my $writefh = FileHandle->new; $CPAN::Frontend->myprint(" $pcommand\n"); unless (open $writefh, "|$pcommand") { my $fail = "Could not fork '$pcommand'"; $CPAN::Frontend->mywarn("$fail; cannot continue\n"); $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail"); delete $self->{build_dir}; return; } binmode($writefh); while (my $x = $readfh->READLINE) { print $writefh $x; } unless (close $writefh) { my $fail = "Could not apply patch '$patch'"; $CPAN::Frontend->mywarn("$fail; cannot continue\n"); $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail"); delete $self->{build_dir}; return; } } $self->{patched}++; } return 1; } } # may return # - "applypatch" # - ("-p0"|"-p1", $files) sub _patch_p_parameter { my($self,$fh) = @_; my $cnt_files = 0; my $cnt_p0files = 0; my @files; local($_); while ($_ = $fh->READLINE) { if ( $CPAN::Config->{applypatch} && /\#\#\#\# ApplyPatch data follows \#\#\#\#/ ) { return "applypatch" } next unless /^[\*\+]{3}\s(\S+)/; my $file = $1; push @files, $file; $cnt_files++; $cnt_p0files++ if -f $file; CPAN->debug("file[$file]cnt_files[$cnt_files]cnt_p0files[$cnt_p0files]") if $CPAN::DEBUG; } return "-p1" unless $cnt_files; my $opt_p = $cnt_files==$cnt_p0files ? "-p0" : "-p1"; return ($opt_p, \@files); } #-> sub CPAN::Distribution::_edge_cases # with "configure" or "Makefile" or single file scripts sub _edge_cases { my($self,$mpl,$local_file) = @_; $self->debug(sprintf("makefilepl[%s]anycwd[%s]", $mpl, CPAN::anycwd(), )) if $CPAN::DEBUG; my $build_dir = $self->{build_dir}; my($configure) = File::Spec->catfile($build_dir,"Configure"); if (-f $configure) { # do we have anything to do? $self->{configure} = $configure; } elsif (-f File::Spec->catfile($build_dir,"Makefile")) { $CPAN::Frontend->mywarn(qq{ Package comes with a Makefile and without a Makefile.PL. We\'ll try to build it with that Makefile then. }); $self->{writemakefile} = CPAN::Distrostatus->new("YES"); $CPAN::Frontend->mysleep(2); } else { my $cf = $self->called_for || "unknown"; if ($cf =~ m|/|) { $cf =~ s|.*/||; $cf =~ s|\W.*||; } $cf =~ s|[/\\:]||g; # risk of filesystem damage $cf = "unknown" unless length($cf); if (my $crud = $self->_contains_crud($build_dir)) { my $why = qq{Package contains $crud; not recognized as a perl package, giving up}; $CPAN::Frontend->mywarn("$why\n"); $self->{writemakefile} = CPAN::Distrostatus->new(qq{NO -- $why}); return; } $CPAN::Frontend->mywarn(qq{Package seems to come without Makefile.PL. (The test -f "$mpl" returned false.) Writing one on our own (setting NAME to $cf)\a\n}); $self->{had_no_makefile_pl}++; $CPAN::Frontend->mysleep(3); # Writing our own Makefile.PL my $exefile_stanza = ""; if ($self->{archived} eq "maybe_pl") { $exefile_stanza = $self->_exefile_stanza($build_dir,$local_file); } my $fh = FileHandle->new; $fh->open(">$mpl") or Carp::croak("Could not open >$mpl: $!"); $fh->print( qq{# This Makefile.PL has been autogenerated by the module CPAN.pm # because there was no Makefile.PL supplied. # Autogenerated on: }.scalar localtime().qq{ use ExtUtils::MakeMaker; WriteMakefile( NAME => q[$cf],$exefile_stanza ); }); $fh->close; } } #-> CPAN;:Distribution::_contains_crud sub _contains_crud { my($self,$dir) = @_; my(@dirs, $dh, @files); opendir $dh, $dir or return; my $dirent; for $dirent (readdir $dh) { next if $dirent =~ /^\.\.?$/; my $path = File::Spec->catdir($dir,$dirent); if (-d $path) { push @dirs, $dirent; } elsif (-f $path) { push @files, $dirent; } } if (@dirs && @files) { return "both files[@files] and directories[@dirs]"; } elsif (@files > 2) { return "several files[@files] but no Makefile.PL or Build.PL"; } return; } #-> CPAN;:Distribution::_exefile_stanza sub _exefile_stanza { my($self,$build_dir,$local_file) = @_; my $fh = FileHandle->new; my $script_file = File::Spec->catfile($build_dir,$local_file); $fh->open($script_file) or Carp::croak("Could not open script '$script_file': $!"); local $/ = "\n"; # parse name and prereq my($state) = "poddir"; my($name, $prereq) = ("", ""); while (<$fh>) { if ($state eq "poddir" && /^=head\d\s+(\S+)/) { if ($1 eq 'NAME') { $state = "name"; } elsif ($1 eq 'PREREQUISITES') { $state = "prereq"; } } elsif ($state =~ m{^(name|prereq)$}) { if (/^=/) { $state = "poddir"; } elsif (/^\s*$/) { # nop } elsif ($state eq "name") { if ($name eq "") { ($name) = /^(\S+)/; $state = "poddir"; } } elsif ($state eq "prereq") { $prereq .= $_; } } elsif (/^=cut\b/) { last; } } $fh->close; for ($name) { s{.*<}{}; # strip X<...> s{>.*}{}; } chomp $prereq; $prereq = join " ", split /\s+/, $prereq; my($PREREQ_PM) = join("\n", map { s{.*<}{}; # strip X<...> s{>.*}{}; if (/[\s\'\"]/) { # prose? } else { s/[^\w:]$//; # period? " "x28 . "'$_' => 0,"; } } split /\s*,\s*/, $prereq); if ($name) { my $to_file = File::Spec->catfile($build_dir, $name); rename $script_file, $to_file or die "Can't rename $script_file to $to_file: $!"; } return " EXE_FILES => ['$name'], PREREQ_PM => { $PREREQ_PM }, "; } #-> CPAN::Distribution::_signature_business sub _signature_business { my($self) = @_; my $check_sigs = CPAN::HandleConfig->prefs_lookup($self, q{check_sigs}); if ($check_sigs) { if ($CPAN::META->has_inst("Module::Signature")) { if (-f "SIGNATURE") { $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG; my $rv = Module::Signature::verify(); if ($rv != Module::Signature::SIGNATURE_OK() and $rv != Module::Signature::SIGNATURE_MISSING()) { $CPAN::Frontend->mywarn( qq{\nSignature invalid for }. qq{distribution file. }. qq{Please investigate.\n\n} ); my $wrap = sprintf(qq{I'd recommend removing %s. Some error occurred }. qq{while checking its signature, so it could }. qq{be invalid. Maybe you have configured }. qq{your 'urllist' with a bad URL. Please check this }. qq{array with 'o conf urllist' and retry. Or }. qq{examine the distribution in a subshell. Try look %s and run cpansign -v }, $self->{localfile}, $self->pretty_id, ); $self->{signature_verify} = CPAN::Distrostatus->new("NO"); $CPAN::Frontend->mywarn(Text::Wrap::wrap("","",$wrap)); $CPAN::Frontend->mysleep(5) if $CPAN::Frontend->can("mysleep"); } else { $self->{signature_verify} = CPAN::Distrostatus->new("YES"); $self->debug("Module::Signature has verified") if $CPAN::DEBUG; } } else { $CPAN::Frontend->mywarn(qq{Package came without SIGNATURE\n\n}); } } else { $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG; } } } #-> CPAN::Distribution::untar_me ; sub untar_me { my($self,$ct) = @_; $self->{archived} = "tar"; my $result = eval { $ct->untar() }; if ($result) { $self->{unwrapped} = CPAN::Distrostatus->new("YES"); } else { # unfortunately we have no $@ here, Tarzip is using mydie which dies with "\n" $self->{unwrapped} = CPAN::Distrostatus->new("NO -- untar failed"); } } # CPAN::Distribution::unzip_me ; sub unzip_me { my($self,$ct) = @_; $self->{archived} = "zip"; if (eval { $ct->unzip() }) { $self->{unwrapped} = CPAN::Distrostatus->new("YES"); } else { $self->{unwrapped} = CPAN::Distrostatus->new("NO -- unzip failed during unzip"); } return; } sub handle_singlefile { my($self,$local_file) = @_; if ( $local_file =~ /\.pm(\.(gz|Z))?(?!\n)\Z/ ) { $self->{archived} = "pm"; } elsif ( $local_file =~ /\.patch(\.(gz|bz2))?(?!\n)\Z/ ) { $self->{archived} = "patch"; } else { $self->{archived} = "maybe_pl"; } my $to = File::Basename::basename($local_file); if ($to =~ s/\.(gz|Z)(?!\n)\Z//) { if (eval{CPAN::Tarzip->new($local_file)->gunzip($to)}) { $self->{unwrapped} = CPAN::Distrostatus->new("YES"); } else { $self->{unwrapped} = CPAN::Distrostatus->new("NO -- uncompressing failed"); } } else { if (File::Copy::cp($local_file,".")) { $self->{unwrapped} = CPAN::Distrostatus->new("YES"); } else { $self->{unwrapped} = CPAN::Distrostatus->new("NO -- copying failed"); } } return $to; } #-> sub CPAN::Distribution::new ; sub new { my($class,%att) = @_; # $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); my $this = { %att }; return bless $this, $class; } #-> sub CPAN::Distribution::look ; sub look { my($self) = @_; if ($^O eq 'MacOS') { $self->Mac::BuildTools::look; return; } if ( $CPAN::Config->{'shell'} ) { $CPAN::Frontend->myprint(qq{ Trying to open a subshell in the build directory... }); } else { $CPAN::Frontend->myprint(qq{ Your configuration does not define a value for subshells. Please define it with "o conf shell <your shell>" }); return; } my $dist = $self->id; my $dir; unless ($dir = $self->dir) { $self->get; } unless ($dir ||= $self->dir) { $CPAN::Frontend->mywarn(qq{ Could not determine which directory to use for looking at $dist. }); return; } my $pwd = CPAN::anycwd(); $self->safe_chdir($dir); $CPAN::Frontend->myprint(qq{Working directory is $dir\n}); { local $ENV{CPAN_SHELL_LEVEL} = $ENV{CPAN_SHELL_LEVEL}||0; $ENV{CPAN_SHELL_LEVEL} += 1; my $shell = CPAN::HandleConfig->safe_quote($CPAN::Config->{'shell'}); local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) ? $ENV{PERL5LIB} : ($ENV{PERLLIB} || ""); local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : ""; # local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # look $CPAN::META->set_perl5lib; local $ENV{MAKEFLAGS}; # protect us from outer make calls unless (system($shell) == 0) { my $code = $? >> 8; $CPAN::Frontend->mywarn("Subprocess shell exit code $code\n"); } } $self->safe_chdir($pwd); } # CPAN::Distribution::cvs_import ; sub cvs_import { my($self) = @_; $self->get; my $dir = $self->dir; my $package = $self->called_for; my $module = $CPAN::META->instance('CPAN::Module', $package); my $version = $module->cpan_version; my $userid = $self->cpan_userid; my $cvs_dir = (split /\//, $dir)[-1]; $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//; my $cvs_root = $CPAN::Config->{cvsroot} || $ENV{CVSROOT}; my $cvs_site_perl = $CPAN::Config->{cvs_site_perl} || $ENV{CVS_SITE_PERL}; if ($cvs_site_perl) { $cvs_dir = "$cvs_site_perl/$cvs_dir"; } my $cvs_log = qq{"imported $package $version sources"}; $version =~ s/\./_/g; # XXX cvs: undocumented and unclear how it was meant to work my @cmd = ('cvs', '-d', $cvs_root, 'import', '-m', $cvs_log, "$cvs_dir", $userid, "v$version"); my $pwd = CPAN::anycwd(); chdir($dir) or $CPAN::Frontend->mydie(qq{Could not chdir to "$dir": $!}); $CPAN::Frontend->myprint(qq{Working directory is $dir\n}); $CPAN::Frontend->myprint(qq{@cmd\n}); system(@cmd) == 0 or # XXX cvs $CPAN::Frontend->mydie("cvs import failed"); chdir($pwd) or $CPAN::Frontend->mydie(qq{Could not chdir to "$pwd": $!}); } #-> sub CPAN::Distribution::readme ; sub readme { my($self) = @_; my($dist) = $self->id; my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/; $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG; my($local_file); my($local_wanted) = File::Spec->catfile( $CPAN::Config->{keep_source_where}, "authors", "id", split(/\//,"$sans.readme"), ); my $readme = "authors/id/$sans.readme"; $self->debug("Doing localize for '$readme'") if $CPAN::DEBUG; $local_file = CPAN::FTP->localize($readme, $local_wanted) or $CPAN::Frontend->mydie(qq{No $sans.readme found}); if ($^O eq 'MacOS') { Mac::BuildTools::launch_file($local_file); return; } my $fh_pager = FileHandle->new; local($SIG{PIPE}) = "IGNORE"; my $pager = $CPAN::Config->{'pager'} || "cat"; $fh_pager->open("|$pager") or die "Could not open pager $pager\: $!"; my $fh_readme = FileHandle->new; $fh_readme->open($local_file) or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!}); $CPAN::Frontend->myprint(qq{ Displaying file $local_file with pager "$pager" }); $fh_pager->print(<$fh_readme>); $fh_pager->close; } #-> sub CPAN::Distribution::verifyCHECKSUM ; sub verifyCHECKSUM { my($self) = @_; EXCUSE: { my @e; $self->{CHECKSUM_STATUS} ||= ""; $self->{CHECKSUM_STATUS} eq "OK" and push @e, "Checksum was ok"; $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; } my($lc_want,$lc_file,@local,$basename); @local = split(/\//,$self->id); pop @local; push @local, "CHECKSUMS"; $lc_want = File::Spec->catfile($CPAN::Config->{keep_source_where}, "authors", "id", @local); local($") = "/"; if (my $size = -s $lc_want) { $self->debug("lc_want[$lc_want]size[$size]") if $CPAN::DEBUG; my @stat = stat $lc_want; my $epoch_starting_support_of_cpan_path = 1637471530; if ($stat[9] >= $epoch_starting_support_of_cpan_path) { if ($self->CHECKSUM_check_file($lc_want, 1)) { return $self->{CHECKSUM_STATUS} = "OK"; } } else { unlink $lc_want; } } $lc_file = CPAN::FTP->localize("authors/id/@local", $lc_want,1); unless ($lc_file) { $CPAN::Frontend->myprint("Trying $lc_want.gz\n"); $local[-1] .= ".gz"; $lc_file = CPAN::FTP->localize("authors/id/@local", "$lc_want.gz",1); if ($lc_file) { $lc_file =~ s/\.gz(?!\n)\Z//; eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)}; } else { return; } } if ($self->CHECKSUM_check_file($lc_file)) { return $self->{CHECKSUM_STATUS} = "OK"; } } #-> sub CPAN::Distribution::SIG_check_file ; sub SIG_check_file { my($self,$chk_file) = @_; my $rv = eval { Module::Signature::_verify($chk_file) }; if ($rv eq Module::Signature::CANNOT_VERIFY()) { $CPAN::Frontend->myprint(qq{\nSignature for }. qq{file $chk_file could not be verified for an unknown reason. }. $self->as_string. qq{Module::Signature verification returned value $rv\n\n} ); my $wrap = qq{The manual says for this case: Cannot verify the OpenPGP signature, maybe due to the lack of a network connection to the key server, or if neither gnupg nor Crypt::OpenPGP exists on the system. You probably want to analyse the situation and if you cannot fix it you will have to decide whether you want to stop this session or you want to turn off signature verification. The latter would be done with the command 'o conf init check_sigs'}; $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap)); } if ($rv == Module::Signature::SIGNATURE_OK()) { $CPAN::Frontend->myprint("Signature for $chk_file ok\n"); return $self->{SIG_STATUS} = "OK"; } else { $CPAN::Frontend->mywarn(qq{\nSignature invalid for }. qq{file $chk_file. }. qq{Please investigate.\n\n}. $self->as_string. qq{Module::Signature verification returned value $rv\n\n} ); my $wrap = qq{I\'d recommend removing $chk_file. Its signature is invalid. Maybe you have configured your 'urllist' with a bad URL. Please check this array with 'o conf urllist', and retry.}; $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap)); } } #-> sub CPAN::Distribution::CHECKSUM_check_file ; # sloppy is 1 when we have an old checksums file that maybe is good # enough sub CHECKSUM_check_file { my($self,$chk_file,$sloppy) = @_; my($cksum,$file,$basename); $sloppy ||= 0; $self->debug("chk_file[$chk_file]sloppy[$sloppy]") if $CPAN::DEBUG; my $check_sigs = CPAN::HandleConfig->prefs_lookup($self, q{check_sigs}); if ($check_sigs) { if ($CPAN::META->has_inst("Module::Signature")) { $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG; $self->SIG_check_file($chk_file); } else { $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG; } } $file = $self->{localfile}; $basename = File::Basename::basename($file); my($signed_data); my $fh = FileHandle->new; if ($check_sigs) { my $tempdir; if ($CPAN::META->has_usable("File::Temp")) { $tempdir = File::Temp::tempdir("CHECKSUMS-XXXX", CLEANUP => 1, DIR => "/tmp" ); } else { $tempdir = File::Spec->catdir(File::Spec->tmpdir, "CHECKSUMS-$$"); File::Path::mkpath($tempdir); } my $tempfile = File::Spec->catfile($tempdir, "CHECKSUMS.$$"); unlink $tempfile; # ignore missing file my $devnull = File::Spec->devnull; my $gpg = $CPAN::Config->{gpg} or $CPAN::Frontend->mydie("Your configuration suggests that you do not have 'gpg' installed. This is needed to verify checksums with the config variable 'check_sigs' on. Please configure it with 'o conf init gpg'"); my $system = qq{"$gpg" --verify --batch --no-tty --output "$tempfile" "$chk_file" 2> "$devnull"}; 0 == system $system or $CPAN::Frontend->mydie("gpg run was failing, cannot continue: $system"); open $fh, $tempfile or $CPAN::Frontend->mydie("Could not open $tempfile: $!"); local $/; $signed_data = <$fh>; close $fh; File::Path::rmtree($tempdir); } else { my $fh = FileHandle->new; if (open $fh, $chk_file) { local($/); $signed_data = <$fh>; } else { $CPAN::Frontend->mydie("Could not open $chk_file for reading"); } close $fh; } $signed_data =~ s/\015?\012/\n/g; my($compmt) = Safe->new(); $cksum = $compmt->reval($signed_data); if ($@) { rename $chk_file, "$chk_file.bad"; Carp::confess($@) if $@; } if (! ref $cksum or ref $cksum ne "HASH") { $CPAN::Frontend->mywarn(qq{ Warning: checksum file '$chk_file' broken. When trying to read that file I expected to get a hash reference for further processing, but got garbage instead. }); my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed nonetheless?", "no"); $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n"); $self->{CHECKSUM_STATUS} = "NIL -- CHECKSUMS file broken"; return; } elsif (exists $cksum->{$basename} && ! exists $cksum->{$basename}{cpan_path}) { $CPAN::Frontend->mywarn(qq{ Warning: checksum file '$chk_file' not conforming. The cksum does not contain the key 'cpan_path' for '$basename'. }); my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed nonetheless?", "no"); $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n"); $self->{CHECKSUM_STATUS} = "NIL -- CHECKSUMS file without cpan_path"; return; } elsif (exists $cksum->{$basename} && substr($self->{ID},0,length($cksum->{$basename}{cpan_path})) ne $cksum->{$basename}{cpan_path}) { $CPAN::Frontend->mywarn(qq{ Warning: checksum file not matching path '$self->{ID}'. The cksum contain the key 'cpan_path=$cksum->{$basename}{cpan_path}' which does not match the ID of the distribution '$self->{ID}'. Something's suspicious might be going on here. Please investigate. }); my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed nonetheless?", "no"); $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n"); $self->{CHECKSUM_STATUS} = "NIL -- CHECKSUMS non-matching cpan_path vs. ID"; return; } elsif (exists $cksum->{$basename}{sha256}) { $self->debug("Found checksum for $basename:" . "$cksum->{$basename}{sha256}\n") if $CPAN::DEBUG; open($fh, $file); binmode $fh; my $eq = $self->eq_CHECKSUM($fh,$cksum->{$basename}{sha256}); $fh->close; $fh = CPAN::Tarzip->TIEHANDLE($file); unless ($eq) { my $dg = Digest::SHA->new(256); my($data,$ref); $ref = \$data; while ($fh->READ($ref, 4096) > 0) { $dg->add($data); } my $hexdigest = $dg->hexdigest; $eq += $hexdigest eq $cksum->{$basename}{'sha256-ungz'}; } if ($eq) { $CPAN::Frontend->myprint("Checksum for $file ok\n"); return $self->{CHECKSUM_STATUS} = "OK"; } else { $CPAN::Frontend->myprint(qq{\nChecksum mismatch for }. qq{distribution file. }. qq{Please investigate.\n\n}. $self->as_string, $CPAN::META->instance( 'CPAN::Author', $self->cpan_userid )->as_string); my $wrap = qq{I\'d recommend removing $file. Its checksum is incorrect. Maybe you have configured your 'urllist' with a bad URL. Please check this array with 'o conf urllist', and retry.}; $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap)); # former versions just returned here but this seems a # serious threat that deserves a die # $CPAN::Frontend->myprint("\n\n"); # sleep 3; # return; } # close $fh if fileno($fh); } else { return if $sloppy; unless ($self->{CHECKSUM_STATUS}) { $CPAN::Frontend->mywarn(qq{ Warning: No checksum for $basename in $chk_file. The cause for this may be that the file is very new and the checksum has not yet been calculated, but it may also be that something is going awry right now. }); my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed?", "yes"); $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n"); } $self->{CHECKSUM_STATUS} = "NIL -- distro not in CHECKSUMS file"; return; } } #-> sub CPAN::Distribution::eq_CHECKSUM ; sub eq_CHECKSUM { my($self,$fh,$expect) = @_; if ($CPAN::META->has_inst("Digest::SHA")) { my $dg = Digest::SHA->new(256); my($data); while (read($fh, $data, 4096)) { $dg->add($data); } my $hexdigest = $dg->hexdigest; # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]"; return $hexdigest eq $expect; } return 1; } #-> sub CPAN::Distribution::force ; # Both CPAN::Modules and CPAN::Distributions know if "force" is in # effect by autoinspection, not by inspecting a global variable. One # of the reason why this was chosen to work that way was the treatment # of dependencies. They should not automatically inherit the force # status. But this has the downside that ^C and die() will return to # the prompt but will not be able to reset the force_update # attributes. We try to correct for it currently in the read_metadata # routine, and immediately before we check for a Signal. I hope this # works out in one of v1.57_53ff # "Force get forgets previous error conditions" #-> sub CPAN::Distribution::fforce ; sub fforce { my($self, $method) = @_; $self->force($method,1); } #-> sub CPAN::Distribution::force ; sub force { my($self, $method,$fforce) = @_; my %phase_map = ( get => [ "unwrapped", "build_dir", "archived", "localfile", "CHECKSUM_STATUS", "signature_verify", "prefs", "prefs_file", "prefs_file_doc", "cleanup_after_install_done", ], make => [ "writemakefile", "make", "modulebuild", "prereq_pm", "cleanup_after_install_done", ], test => [ "badtestcnt", "make_test", "cleanup_after_install_done", ], install => [ "install", "cleanup_after_install_done", ], unknown => [ "reqtype", "yaml_content", "cleanup_after_install_done", ], ); my $methodmatch = 0; my $ldebug = 0; PHASE: for my $phase (qw(unknown get make test install)) { # order matters $methodmatch = 1 if $fforce || ($method && $phase eq $method); next unless $methodmatch; ATTRIBUTE: for my $att (@{$phase_map{$phase}}) { if ($phase eq "get") { if (substr($self->id,-1,1) eq "." && $att =~ /(unwrapped|build_dir|archived)/ ) { # cannot be undone for local distros next ATTRIBUTE; } if ($att eq "build_dir" && $self->{build_dir} && $CPAN::META->{is_tested} ) { delete $CPAN::META->{is_tested}{$self->{build_dir}}; } } elsif ($phase eq "test") { if ($att eq "make_test" && $self->{make_test} && $self->{make_test}{COMMANDID} && $self->{make_test}{COMMANDID} == $CPAN::CurrentCommandId ) { # endless loop too likely next ATTRIBUTE; } } delete $self->{$att}; if ($ldebug || $CPAN::DEBUG) { # local $CPAN::DEBUG = 16; # Distribution CPAN->debug(sprintf "id[%s]phase[%s]att[%s]", $self->id, $phase, $att); } } } if ($method && $method =~ /make|test|install/) { $self->{force_update} = 1; # name should probably have been force_install } } #-> sub CPAN::Distribution::notest ; sub notest { my($self, $method) = @_; # $CPAN::Frontend->mywarn("XDEBUG: set notest for $self $method"); $self->{"notest"}++; # name should probably have been force_install } #-> sub CPAN::Distribution::unnotest ; sub unnotest { my($self) = @_; # warn "XDEBUG: deleting notest"; delete $self->{notest}; } #-> sub CPAN::Distribution::unforce ; sub unforce { my($self) = @_; delete $self->{force_update}; } #-> sub CPAN::Distribution::isa_perl ; sub isa_perl { my($self) = @_; my $file = File::Basename::basename($self->id); if ($file =~ m{ ^ perl ( -(5\.\d+\.\d+) | (5)[._-](00[0-5](?:_[0-4][0-9])?) ) \.tar[._-](?:gz|bz2) (?!\n)\Z }xs) { my $perl_version; if ($2) { $perl_version = $2; } else { $perl_version = "$3.$4"; } return $perl_version; } elsif ($self->cpan_comment && $self->cpan_comment =~ /isa_perl\(.+?\)/) { return $1; } } #-> sub CPAN::Distribution::perl ; sub perl { my ($self) = @_; if (! $self) { use Carp qw(carp); carp __PACKAGE__ . "::perl was called without parameters."; } return CPAN::HandleConfig->safe_quote($CPAN::Perl); } #-> sub CPAN::Distribution::shortcut_prepare ; # return values: undef means don't shortcut; 0 means shortcut as fail; # and 1 means shortcut as success sub shortcut_prepare { my ($self) = @_; $self->debug("checking archive type[$self->{ID}]") if $CPAN::DEBUG; if (!$self->{archived} || $self->{archived} eq "NO") { return $self->goodbye("Is neither a tar nor a zip archive."); } $self->debug("checking unwrapping[$self->{ID}]") if $CPAN::DEBUG; if (!$self->{unwrapped} || ( UNIVERSAL::can($self->{unwrapped},"failed") ? $self->{unwrapped}->failed : $self->{unwrapped} =~ /^NO/ )) { return $self->goodbye("Had problems unarchiving. Please build manually"); } $self->debug("checking signature[$self->{ID}]") if $CPAN::DEBUG; if ( ! $self->{force_update} && exists $self->{signature_verify} && ( UNIVERSAL::can($self->{signature_verify},"failed") ? $self->{signature_verify}->failed : $self->{signature_verify} =~ /^NO/ ) ) { return $self->goodbye("Did not pass the signature test."); } $self->debug("checking writemakefile[$self->{ID}]") if $CPAN::DEBUG; if ($self->{writemakefile}) { if ( UNIVERSAL::can($self->{writemakefile},"failed") ? $self->{writemakefile}->failed : $self->{writemakefile} =~ /^NO/ ) { # XXX maybe a retry would be in order? my $err = UNIVERSAL::can($self->{writemakefile},"text") ? $self->{writemakefile}->text : $self->{writemakefile}; $err =~ s/^NO\s*(--\s+)?//; $err ||= "Had some problem writing Makefile"; $err .= ", not re-running"; return $self->goodbye($err); } else { return $self->success("Has already been prepared"); } } $self->debug("checking configure_requires_later[$self->{ID}]") if $CPAN::DEBUG; if( my $later = $self->{configure_requires_later} ) { # see also undelay return $self->goodbye($later); } return undef; # no shortcut } sub prepare { my ($self) = @_; $self->get or return; if ( defined( my $sc = $self->shortcut_prepare) ) { return $sc; } local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) ? $ENV{PERL5LIB} : ($ENV{PERLLIB} || ""); local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : ""; local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} && defined $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # prepare $CPAN::META->set_perl5lib; local $ENV{MAKEFLAGS}; # protect us from outer make calls if ($CPAN::Signal) { delete $self->{force_update}; return; } my $builddir = $self->dir or $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n"); unless (chdir $builddir) { $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!"); return; } if ($CPAN::Signal) { delete $self->{force_update}; return; } $self->debug("Changed directory to $builddir") if $CPAN::DEBUG; local $ENV{PERL_AUTOINSTALL} = $ENV{PERL_AUTOINSTALL} || ''; local $ENV{PERL_EXTUTILS_AUTOINSTALL} = $ENV{PERL_EXTUTILS_AUTOINSTALL} || ''; $self->choose_MM_or_MB or return; my $configurator = $self->{configure} ? "Configure" : $self->{modulebuild} ? "Build.PL" : "Makefile.PL"; $CPAN::Frontend->myprint("Configuring ".$self->id." with $configurator\n"); if ($CPAN::Config->{prerequisites_policy} eq "follow") { $ENV{PERL_AUTOINSTALL} ||= "--defaultdeps"; $ENV{PERL_EXTUTILS_AUTOINSTALL} ||= "--defaultdeps"; } my $system; my $pl_commandline; if ($self->prefs->{pl}) { $pl_commandline = $self->prefs->{pl}{commandline}; } local $ENV{PERL} = defined $ENV{PERL}? $ENV{PERL} : $^X; local $ENV{PERL5_CPAN_IS_EXECUTING} = $ENV{PERL5_CPAN_IS_EXECUTING} || ''; local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default}; local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default}; if ($pl_commandline) { $system = $pl_commandline; $ENV{PERL} = $^X; } elsif ($self->{'configure'}) { $system = $self->{'configure'}; } elsif ($self->{modulebuild}) { my($perl) = $self->perl or die "Couldn\'t find executable perl\n"; my $mbuildpl_arg = $self->_make_phase_arg("pl"); $system = sprintf("%s Build.PL%s", $perl, $mbuildpl_arg ? " $mbuildpl_arg" : "", ); } else { my($perl) = $self->perl or die "Couldn\'t find executable perl\n"; my $switch = ""; # This needs a handler that can be turned on or off: # $switch = "-MExtUtils::MakeMaker ". # "-Mops=:default,:filesys_read,:filesys_open,require,chdir" # if $] > 5.00310; my $makepl_arg = $self->_make_phase_arg("pl"); $ENV{PERL5_CPAN_IS_EXECUTING} = File::Spec->catfile($self->{build_dir}, "Makefile.PL"); $system = sprintf("%s%s Makefile.PL%s", $perl, $switch ? " $switch" : "", $makepl_arg ? " $makepl_arg" : "", ); } my $pl_env; if ($self->prefs->{pl}) { $pl_env = $self->prefs->{pl}{env}; } local @ENV{keys %$pl_env} = values %$pl_env if $pl_env; if (exists $self->{writemakefile}) { } else { local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" }; my($ret,$pid,$output); $@ = ""; my $go_via_alarm; if ($CPAN::Config->{inactivity_timeout}) { require Config; if ($Config::Config{d_alarm} && $Config::Config{d_alarm} eq "define" ) { $go_via_alarm++ } else { $CPAN::Frontend->mywarn("Warning: you have configured the config ". "variable 'inactivity_timeout' to ". "'$CPAN::Config->{inactivity_timeout}'. But ". "on this machine the system call 'alarm' ". "isn't available. This means that we cannot ". "provide the feature of intercepting long ". "waiting code and will turn this feature off.\n" ); $CPAN::Config->{inactivity_timeout} = 0; } } if ($go_via_alarm) { if ( $self->_should_report('pl') ) { ($output, $ret) = CPAN::Reporter::record_command( $system, $CPAN::Config->{inactivity_timeout}, ); CPAN::Reporter::grade_PL( $self, $system, $output, $ret ); } else { eval { alarm $CPAN::Config->{inactivity_timeout}; local $SIG{CHLD}; # = sub { wait }; if (defined($pid = fork)) { if ($pid) { #parent # wait; waitpid $pid, 0; } else { #child # note, this exec isn't necessary if # inactivity_timeout is 0. On the Mac I'd # suggest, we set it always to 0. exec $system; } } else { $CPAN::Frontend->myprint("Cannot fork: $!"); return; } }; alarm 0; if ($@) { kill 9, $pid; waitpid $pid, 0; my $err = "$@"; $CPAN::Frontend->myprint($err); $self->{writemakefile} = CPAN::Distrostatus->new("NO $err"); $@ = ""; $self->store_persistent_state; return $self->goodbye("$system -- TIMED OUT"); } } } else { if (my $expect_model = $self->_prefs_with_expect("pl")) { # XXX probably want to check _should_report here and warn # about not being able to use CPAN::Reporter with expect $ret = $self->_run_via_expect($system,'writemakefile',$expect_model); if (! defined $ret && $self->{writemakefile} && $self->{writemakefile}->failed) { # timeout return; } } elsif ( $self->_should_report('pl') ) { ($output, $ret) = eval { CPAN::Reporter::record_command($system) }; if (! defined $output or $@) { my $err = $@ || "Unknown error"; $CPAN::Frontend->mywarn("Error while running PL phase: $err\n"); $self->{writemakefile} = CPAN::Distrostatus ->new("NO '$system' returned status $ret and no output"); return $self->goodbye("$system -- NOT OK"); } CPAN::Reporter::grade_PL( $self, $system, $output, $ret ); } else { $ret = system($system); } if ($ret != 0) { $self->{writemakefile} = CPAN::Distrostatus ->new("NO '$system' returned status $ret"); $CPAN::Frontend->mywarn("Warning: No success on command[$system]\n"); $self->store_persistent_state; return $self->goodbye("$system -- NOT OK"); } } if (-f "Makefile" || -f "Build" || ($^O eq 'VMS' && (-f 'descrip.mms' || -f 'Build.com'))) { $self->{writemakefile} = CPAN::Distrostatus->new("YES"); delete $self->{make_clean}; # if cleaned before, enable next $self->store_persistent_state; return $self->success("$system -- OK"); } else { my $makefile = $self->{modulebuild} ? "Build" : "Makefile"; my $why = "No '$makefile' created"; $CPAN::Frontend->mywarn($why); $self->{writemakefile} = CPAN::Distrostatus ->new(qq{NO -- $why\n}); $self->store_persistent_state; return $self->goodbye("$system -- NOT OK"); } } $self->store_persistent_state; return 1; # success } #-> sub CPAN::Distribution::shortcut_make ; # return values: undef means don't shortcut; 0 means shortcut as fail; # and 1 means shortcut as success sub shortcut_make { my ($self) = @_; $self->debug("checking make/build results[$self->{ID}]") if $CPAN::DEBUG; if (defined $self->{make}) { if (UNIVERSAL::can($self->{make},"failed") ? $self->{make}->failed : $self->{make} =~ /^NO/ ) { if ($self->{force_update}) { # Trying an already failed 'make' (unless somebody else blocks) return undef; # no shortcut } else { # introduced for turning recursion detection into a distrostatus my $error = length $self->{make}>3 ? substr($self->{make},3) : "Unknown error"; $self->store_persistent_state; return $self->goodbye("Could not make: $error\n"); } } else { return $self->success("Has already been made") } } return undef; # no shortcut } #-> sub CPAN::Distribution::make ; sub make { my($self) = @_; $self->pre_make(); if (exists $self->{cleanup_after_install_done}) { $self->post_make(); return $self->get; } $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG; if (my $goto = $self->prefs->{goto}) { $self->post_make(); return $self->goto($goto); } # Emergency brake if they said install Pippi and get newest perl # XXX Would this make more sense in shortcut_prepare, since # that doesn't make sense on a perl dist either? Broader # question: what is the purpose of suggesting force install # on a perl distribution? That seems unlikely to result in # such a dependency being satisfied, even if the perl is # successfully installed. This situation is tantamount to # a prereq on a version of perl greater than the current one # so I think we should just abort. -- xdg, 2012-04-06 if ($self->isa_perl) { if ( $self->called_for ne $self->id && ! $self->{force_update} ) { # if we die here, we break bundles $CPAN::Frontend ->mywarn(sprintf( qq{The most recent version "%s" of the module "%s" is part of the perl-%s distribution. To install that, you need to run force install %s --or-- install %s }, $CPAN::META->instance( 'CPAN::Module', $self->called_for )->cpan_version, $self->called_for, $self->isa_perl, $self->called_for, $self->pretty_id, )); $self->{make} = CPAN::Distrostatus->new("NO isa perl"); $CPAN::Frontend->mysleep(1); $self->post_make(); return; } } unless ($self->prepare){ $self->post_make(); return; } if ( defined( my $sc = $self->shortcut_make) ) { $self->post_make(); return $sc; } if ($CPAN::Signal) { delete $self->{force_update}; $self->post_make(); return; } my $builddir = $self->dir or $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n"); unless (chdir $builddir) { $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!"); $self->post_make(); return; } my $make = $self->{modulebuild} ? "Build" : "make"; $CPAN::Frontend->myprint(sprintf "Running %s for %s\n", $make, $self->id); local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) ? $ENV{PERL5LIB} : ($ENV{PERLLIB} || ""); local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : ""; local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} && defined $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # make $CPAN::META->set_perl5lib; local $ENV{MAKEFLAGS}; # protect us from outer make calls if ($CPAN::Signal) { delete $self->{force_update}; $self->post_make(); return; } if ($^O eq 'MacOS') { Mac::BuildTools::make($self); $self->post_make(); return; } my %env; while (my($k,$v) = each %ENV) { next if defined $v; $env{$k} = ''; } local @ENV{keys %env} = values %env; my $satisfied = eval { $self->satisfy_requires }; if ($@) { return $self->goodbye($@); } unless ($satisfied){ $self->post_make(); return; } if ($CPAN::Signal) { delete $self->{force_update}; $self->post_make(); return; } # need to chdir again, because $self->satisfy_requires might change the directory unless (chdir $builddir) { $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!"); $self->post_make(); return; } my $system; my $make_commandline; if ($self->prefs->{make}) { $make_commandline = $self->prefs->{make}{commandline}; } local $ENV{PERL} = defined $ENV{PERL}? $ENV{PERL} : $^X; local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default}; local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default}; if ($make_commandline) { $system = $make_commandline; $ENV{PERL} = CPAN::find_perl(); } else { if ($self->{modulebuild}) { unless (-f "Build" || ($^O eq 'VMS' && -f 'Build.com')) { my $cwd = CPAN::anycwd(); $CPAN::Frontend->mywarn("Alert: no Build file available for 'make $self->{id}'". " in cwd[$cwd]. Danger, Will Robinson!\n"); $CPAN::Frontend->mysleep(5); } $system = join " ", $self->_build_command(), $CPAN::Config->{mbuild_arg}; } else { $system = join " ", $self->_make_command(), $CPAN::Config->{make_arg}; } $system =~ s/\s+$//; my $make_arg = $self->_make_phase_arg("make"); $system = sprintf("%s%s", $system, $make_arg ? " $make_arg" : "", ); } my $make_env; if ($self->prefs->{make}) { $make_env = $self->prefs->{make}{env}; } local @ENV{keys %$make_env} = values %$make_env if $make_env; my $expect_model = $self->_prefs_with_expect("make"); my $want_expect = 0; if ( $expect_model && @{$expect_model->{talk}} ) { my $can_expect = $CPAN::META->has_inst("Expect"); if ($can_expect) { $want_expect = 1; } else { $CPAN::Frontend->mywarn("Expect not installed, falling back to ". "system()\n"); } } my ($system_ok, $system_err); if ($want_expect) { # XXX probably want to check _should_report here and # warn about not being able to use CPAN::Reporter with expect $system_ok = $self->_run_via_expect($system,'make',$expect_model) == 0; } elsif ( $self->_should_report('make') ) { my ($output, $ret) = CPAN::Reporter::record_command($system); CPAN::Reporter::grade_make( $self, $system, $output, $ret ); $system_ok = ! $ret; } else { my $rc = system($system); $system_ok = $rc == 0; $system_err = $! if $rc == -1; } $self->introduce_myself; if ( $system_ok ) { $CPAN::Frontend->myprint(" $system -- OK\n"); $self->{make} = CPAN::Distrostatus->new("YES"); } else { $self->{writemakefile} ||= CPAN::Distrostatus->new("YES"); $self->{make} = CPAN::Distrostatus->new("NO"); $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); $CPAN::Frontend->mywarn(" $system_err\n") if defined $system_err; } $self->store_persistent_state; $self->post_make(); return !! $system_ok; } # CPAN::Distribution::goodbye ; sub goodbye { my($self,$goodbye) = @_; my $id = $self->pretty_id; $CPAN::Frontend->mywarn(" $id\n $goodbye\n"); return 0; # must be explicit false, not undef } sub success { my($self,$why) = @_; my $id = $self->pretty_id; $CPAN::Frontend->myprint(" $id\n $why\n"); return 1; } # CPAN::Distribution::_run_via_expect ; sub _run_via_expect { my($self,$system,$phase,$expect_model) = @_; CPAN->debug("system[$system]expect_model[$expect_model]") if $CPAN::DEBUG; if ($CPAN::META->has_inst("Expect")) { my $expo = Expect->new; # expo Expect object; $expo->spawn($system); $expect_model->{mode} ||= "deterministic"; if ($expect_model->{mode} eq "deterministic") { return $self->_run_via_expect_deterministic($expo,$phase,$expect_model); } elsif ($expect_model->{mode} eq "anyorder") { return $self->_run_via_expect_anyorder($expo,$phase,$expect_model); } else { die "Panic: Illegal expect mode: $expect_model->{mode}"; } } else { $CPAN::Frontend->mywarn("Expect not installed, falling back to system()\n"); return system($system); } } sub _run_via_expect_anyorder { my($self,$expo,$phase,$expect_model) = @_; my $timeout = $expect_model->{timeout} || 5; my $reuse = $expect_model->{reuse}; my @expectacopy = @{$expect_model->{talk}}; # we trash it! my $but = ""; my $timeout_start = time; EXPECT: while () { my($eof,$ran_into_timeout); # XXX not up to the full power of expect. one could certainly # wrap all of the talk pairs into a single expect call and on # success tweak it and step ahead to the next question. The # current implementation unnecessarily limits itself to a # single match. my @match = $expo->expect(1, [ eof => sub { $eof++; } ], [ timeout => sub { $ran_into_timeout++; } ], -re => eval"qr{.}", ); if ($match[2]) { $but .= $match[2]; } $but .= $expo->clear_accum; if ($eof) { $expo->soft_close; return $expo->exitstatus(); } elsif ($ran_into_timeout) { # warn "DEBUG: they are asking a question, but[$but]"; for (my $i = 0; $i <= $#expectacopy; $i+=2) { my($next,$send) = @expectacopy[$i,$i+1]; my $regex = eval "qr{$next}"; # warn "DEBUG: will compare with regex[$regex]."; if ($but =~ /$regex/) { # warn "DEBUG: will send send[$send]"; $expo->send($send); # never allow reusing an QA pair unless they told us splice @expectacopy, $i, 2 unless $reuse; $but =~ s/(?s:^.*?)$regex//; $timeout_start = time; next EXPECT; } } my $have_waited = time - $timeout_start; if ($have_waited < $timeout) { # warn "DEBUG: have_waited[$have_waited]timeout[$timeout]"; next EXPECT; } my $why = "could not answer a question during the dialog"; $CPAN::Frontend->mywarn("Failing: $why\n"); $self->{$phase} = CPAN::Distrostatus->new("NO $why"); return 0; } } } sub _run_via_expect_deterministic { my($self,$expo,$phase,$expect_model) = @_; my $ran_into_timeout; my $ran_into_eof; my $timeout = $expect_model->{timeout} || 15; # currently unsettable my $expecta = $expect_model->{talk}; EXPECT: for (my $i = 0; $i <= $#$expecta; $i+=2) { my($re,$send) = @$expecta[$i,$i+1]; CPAN->debug("timeout[$timeout]re[$re]") if $CPAN::DEBUG; my $regex = eval "qr{$re}"; $expo->expect($timeout, [ eof => sub { my $but = $expo->clear_accum; $CPAN::Frontend->mywarn("EOF (maybe harmless) expected[$regex]\nbut[$but]\n\n"); $ran_into_eof++; } ], [ timeout => sub { my $but = $expo->clear_accum; $CPAN::Frontend->mywarn("TIMEOUT expected[$regex]\nbut[$but]\n\n"); $ran_into_timeout++; } ], -re => $regex); if ($ran_into_timeout) { # note that the caller expects 0 for success $self->{$phase} = CPAN::Distrostatus->new("NO timeout during expect dialog"); return 0; } elsif ($ran_into_eof) { last EXPECT; } $expo->send($send); } $expo->soft_close; return $expo->exitstatus(); } #-> CPAN::Distribution::_validate_distropref sub _validate_distropref { my($self,@args) = @_; if ( $CPAN::META->has_inst("CPAN::Kwalify") && $CPAN::META->has_inst("Kwalify") ) { eval {CPAN::Kwalify::_validate("distroprefs",@args);}; if ($@) { $CPAN::Frontend->mywarn($@); } } else { CPAN->debug("not validating '@args'") if $CPAN::DEBUG; } } #-> CPAN::Distribution::_find_prefs sub _find_prefs { my($self) = @_; my $distroid = $self->pretty_id; #CPAN->debug("distroid[$distroid]") if $CPAN::DEBUG; my $prefs_dir = $CPAN::Config->{prefs_dir}; return if $prefs_dir =~ /^\s*$/; eval { File::Path::mkpath($prefs_dir); }; if ($@) { $CPAN::Frontend->mydie("Cannot create directory $prefs_dir"); } # shortcut if there are no distroprefs files { my $dh = DirHandle->new($prefs_dir) or $CPAN::Frontend->mydie("Couldn't open '$prefs_dir': $!"); my @files = map { /\.(yml|dd|st)\z/i } $dh->read; return unless @files; } my $yaml_module = CPAN::_yaml_module(); my $ext_map = {}; my @extensions; if ($CPAN::META->has_inst($yaml_module)) { $ext_map->{yml} = 'CPAN'; } else { my @fallbacks; if ($CPAN::META->has_inst("Data::Dumper")) { push @fallbacks, $ext_map->{dd} = 'Data::Dumper'; } if ($CPAN::META->has_inst("Storable")) { push @fallbacks, $ext_map->{st} = 'Storable'; } if (@fallbacks) { local $" = " and "; unless ($self->{have_complained_about_missing_yaml}++) { $CPAN::Frontend->mywarnonce("'$yaml_module' not installed, falling back ". "to @fallbacks to read prefs '$prefs_dir'\n"); } } else { unless ($self->{have_complained_about_missing_yaml}++) { $CPAN::Frontend->mywarnonce("'$yaml_module' not installed, cannot ". "read prefs '$prefs_dir'\n"); } } } my $finder = CPAN::Distroprefs->find($prefs_dir, $ext_map); DIRENT: while (my $result = $finder->next) { if ($result->is_warning) { $CPAN::Frontend->mywarn($result->as_string); $CPAN::Frontend->mysleep(1); next DIRENT; } elsif ($result->is_fatal) { $CPAN::Frontend->mydie($result->as_string); } my @prefs = @{ $result->prefs }; ELEMENT: for my $y (0..$#prefs) { my $pref = $prefs[$y]; $self->_validate_distropref($pref->data, $result->abs, $y); # I don't know why we silently skip when there's no match, but # complain if there's an empty match hashref, and there's no # comment explaining why -- hdp, 2008-03-18 unless ($pref->has_any_match) { next ELEMENT; } unless ($pref->has_valid_subkeys) { $CPAN::Frontend->mydie(sprintf "Nonconforming .%s file '%s': " . "missing match/* subattribute. " . "Please remove, cannot continue.", $result->ext, $result->abs, ); } my $arg = { env => \%ENV, distribution => $distroid, perl => \&CPAN::find_perl, perlconfig => \%Config::Config, module => sub { [ $self->containsmods ] }, }; if ($pref->matches($arg)) { return { prefs => $pref->data, prefs_file => $result->abs, prefs_file_doc => $y, }; } } } return; } # CPAN::Distribution::prefs sub prefs { my($self) = @_; if (exists $self->{negative_prefs_cache} && $self->{negative_prefs_cache} != $CPAN::CurrentCommandId ) { delete $self->{negative_prefs_cache}; delete $self->{prefs}; } if (exists $self->{prefs}) { return $self->{prefs}; # XXX comment out during debugging } if ($CPAN::Config->{prefs_dir}) { CPAN->debug("prefs_dir[$CPAN::Config->{prefs_dir}]") if $CPAN::DEBUG; my $prefs = $self->_find_prefs(); $prefs ||= ""; # avoid warning next line CPAN->debug("prefs[$prefs]") if $CPAN::DEBUG; if ($prefs) { for my $x (qw(prefs prefs_file prefs_file_doc)) { $self->{$x} = $prefs->{$x}; } my $bs = sprintf( "%s[%s]", File::Basename::basename($self->{prefs_file}), $self->{prefs_file_doc}, ); my $filler1 = "_" x 22; my $filler2 = int(66 - length($bs))/2; $filler2 = 0 if $filler2 < 0; $filler2 = " " x $filler2; $CPAN::Frontend->myprint(" $filler1 D i s t r o P r e f s $filler1 $filler2 $bs $filler2 "); $CPAN::Frontend->mysleep(1); return $self->{prefs}; } } $self->{negative_prefs_cache} = $CPAN::CurrentCommandId; return $self->{prefs} = +{}; } # CPAN::Distribution::_make_phase_arg sub _make_phase_arg { my($self, $phase) = @_; my $_make_phase_arg; my $prefs = $self->prefs; if ( $prefs && exists $prefs->{$phase} && exists $prefs->{$phase}{args} && $prefs->{$phase}{args} ) { $_make_phase_arg = join(" ", map {CPAN::HandleConfig ->safe_quote($_)} @{$prefs->{$phase}{args}}, ); } # cpan[2]> o conf make[TAB] # make make_install_make_command # make_arg makepl_arg # make_install_arg # cpan[2]> o conf mbuild[TAB] # mbuild_arg mbuild_install_build_command # mbuild_install_arg mbuildpl_arg my $mantra; # must switch make/mbuild here if ($self->{modulebuild}) { $mantra = "mbuild"; } else { $mantra = "make"; } my %map = ( pl => "pl_arg", make => "_arg", test => "_test_arg", # does not really exist but maybe # will some day and now protects # us from unini warnings install => "_install_arg", ); my $phase_underscore_meshup = $map{$phase}; my $what = sprintf "%s%s", $mantra, $phase_underscore_meshup; $_make_phase_arg ||= $CPAN::Config->{$what}; return $_make_phase_arg; } # CPAN::Distribution::_make_command sub _make_command { my ($self) = @_; if ($self) { return CPAN::HandleConfig ->safe_quote( CPAN::HandleConfig->prefs_lookup($self, q{make}) || $Config::Config{make} || 'make' ); } else { # Old style call, without object. Deprecated Carp::confess("CPAN::_make_command() used as function. Don't Do That."); return safe_quote(undef, CPAN::HandleConfig->prefs_lookup($self,q{make}) || $CPAN::Config->{make} || $Config::Config{make} || 'make'); } } sub _make_install_make_command { my ($self) = @_; my $mimc = CPAN::HandleConfig->prefs_lookup($self, q{make_install_make_command}); return $self->_make_command() unless $mimc; # Quote the "make install" make command on Windows, where it is commonly # found in, e.g., C:\Program Files\... and therefore needs quoting. We can't # do this in general because the command maybe "sudo make..." (i.e. a # program with arguments), but that is unlikely to be the case on Windows. $mimc = CPAN::HandleConfig->safe_quote($mimc) if $^O eq 'MSWin32'; return $mimc; } #-> sub CPAN::Distribution::is_locally_optional sub is_locally_optional { my($self, $prereq_pm, $prereq) = @_; $prereq_pm ||= $self->{prereq_pm}; my($nmo,$opt); for my $rt (qw(requires build_requires)) { if (exists $prereq_pm->{$rt}{$prereq}) { # rt 121914 $nmo ||= $CPAN::META->instance("CPAN::Module",$prereq); my $av = $nmo->available_version; return 0 if !$av || CPAN::Version->vlt($av,$prereq_pm->{$rt}{$prereq}); } if (exists $prereq_pm->{"opt_$rt"}{$prereq}) { $opt = 1; } } return $opt||0; } #-> sub CPAN::Distribution::follow_prereqs ; sub follow_prereqs { my($self) = shift; my($slot) = shift; my(@prereq_tuples) = grep {$_->[0] ne "perl"} @_; return unless @prereq_tuples; my(@good_prereq_tuples); for my $p (@prereq_tuples) { # e.g. $p = ['Devel::PartialDump', 'r', 1] # promote if possible if ($p->[1] =~ /^(r|c)$/) { push @good_prereq_tuples, $p; } elsif ($p->[1] =~ /^(b)$/) { my $reqtype = CPAN::Queue->reqtype_of($p->[0]); if ($reqtype =~ /^(r|c)$/) { push @good_prereq_tuples, [$p->[0], $reqtype, $p->[2]]; } else { push @good_prereq_tuples, $p; } } else { die "Panic: in follow_prereqs: reqtype[$p->[1]] seen, should never happen"; } } my $pretty_id = $self->pretty_id; my %map = ( b => "build_requires", r => "requires", c => "commandline", ); my($filler1,$filler2,$filler3,$filler4); my $unsat = "Unsatisfied dependencies detected during"; my $w = length($unsat) > length($pretty_id) ? length($unsat) : length($pretty_id); { my $r = int(($w - length($unsat))/2); my $l = $w - length($unsat) - $r; $filler1 = "-"x4 . " "x$l; $filler2 = " "x$r . "-"x4 . "\n"; } { my $r = int(($w - length($pretty_id))/2); my $l = $w - length($pretty_id) - $r; $filler3 = "-"x4 . " "x$l; $filler4 = " "x$r . "-"x4 . "\n"; } $CPAN::Frontend-> myprint("$filler1 $unsat $filler2". "$filler3 $pretty_id $filler4". join("", map {sprintf " %s \[%s%s]\n", $_->[0], $map{$_->[1]}, $self->is_locally_optional(undef,$_->[0]) ? ",optional" : ""} @good_prereq_tuples), ); my $follow = 0; if ($CPAN::Config->{prerequisites_policy} eq "follow") { $follow = 1; } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") { my $answer = CPAN::Shell::colorable_makemaker_prompt( "Shall I follow them and prepend them to the queue of modules we are processing right now?", "yes"); $follow = $answer =~ /^\s*y/i; } else { my @prereq = map { $_->[0] } @good_prereq_tuples; local($") = ", "; $CPAN::Frontend-> myprint(" Ignoring dependencies on modules @prereq\n"); } if ($follow) { my $id = $self->id; my(@to_queue_mand,@to_queue_opt); for my $gp (@good_prereq_tuples) { my($prereq,$reqtype,$optional) = @$gp; my $qthing = +{qmod=>$prereq,reqtype=>$reqtype,optional=>$optional}; if ($optional && $self->is_locally_optional(undef,$prereq) ){ # Since we do not depend on this one, we do not need # this in a mandatory arrangement: push @to_queue_opt, $qthing; } else { my $any = CPAN::Shell->expandany($prereq); $self->{$slot . "_for"}{$any->id}++; if ($any) { unless ($optional) { # No recursion check in an optional area of the tree $any->color_cmd_tmps(0,2); } } else { $CPAN::Frontend->mywarn("Warning (maybe a bug): Cannot expand prereq '$prereq'\n"); $CPAN::Frontend->mysleep(2); } # order everything that is not locally_optional just # like mandatory items: this keeps leaves before # branches unshift @to_queue_mand, $qthing; } } if (@to_queue_mand) { unshift @to_queue_mand, {qmod => $id, reqtype => $self->{reqtype}, optional=> !$self->{mandatory}}; CPAN::Queue->jumpqueue(@to_queue_opt,@to_queue_mand); $self->{$slot} = "Delayed until after prerequisites"; return 1; # signal we need dependencies } elsif (@to_queue_opt) { CPAN::Queue->jumpqueue(@to_queue_opt); } } return; } sub _feature_depends { my($self) = @_; my $meta_yml = $self->parse_meta_yml(); my $optf = $meta_yml->{optional_features} or return; if (!ref $optf or ref $optf ne "HASH"){ $CPAN::Frontend->mywarn("The content of optional_features is not a HASH reference. Cannot use it.\n"); $optf = {}; } my $wantf = $self->prefs->{features} or return; if (!ref $wantf or ref $wantf ne "ARRAY"){ $CPAN::Frontend->mywarn("The content of 'features' is not an ARRAY reference. Cannot use it.\n"); $wantf = []; } my $dep = +{}; for my $wf (@$wantf) { if (my $f = $optf->{$wf}) { $CPAN::Frontend->myprint("Found the demanded feature '$wf' that ". "is accompanied by this description:\n". $f->{description}. "\n\n" ); # configure_requires currently not in the spec, unlikely to be useful anyway for my $reqtype (qw(configure_requires build_requires requires)) { my $reqhash = $f->{$reqtype} or next; while (my($k,$v) = each %$reqhash) { $dep->{$reqtype}{$k} = $v; } } } else { $CPAN::Frontend->mywarn("The demanded feature '$wf' was not ". "found in the META.yml file". "\n\n" ); } } $dep; } sub prereqs_for_slot { my($self,$slot) = @_; my($prereq_pm); unless ($CPAN::META->has_usable("CPAN::Meta::Requirements")) { my $whynot = "not available"; if (defined $CPAN::Meta::Requirements::VERSION) { $whynot = "version $CPAN::Meta::Requirements::VERSION not sufficient"; } $CPAN::Frontend->mywarn("CPAN::Meta::Requirements $whynot\n"); my $before = ""; if ($self->{CALLED_FOR}){ if ($self->{CALLED_FOR} =~ /^( CPAN::Meta::Requirements |CPAN::DistnameInfo |version |parent |ExtUtils::MakeMaker |Test::Harness )$/x) { $CPAN::Frontend->mywarn("Please install CPAN::Meta::Requirements ". "as soon as possible; it is needed for a reliable operation of ". "the cpan shell; setting requirements to nil for '$1' for now ". "to prevent deadlock during bootstrapping\n"); return; } $before = " before $self->{CALLED_FOR}"; } $CPAN::Frontend->mydie("Please install CPAN::Meta::Requirements manually$before"); } my $merged = CPAN::Meta::Requirements->new; my $prefs_depends = $self->prefs->{depends}||{}; my $feature_depends = $self->_feature_depends(); if ($slot eq "configure_requires_later") { for my $hash ( $self->configure_requires, $prefs_depends->{configure_requires}, $feature_depends->{configure_requires}, ) { $merged->add_requirements( CPAN::Meta::Requirements->from_string_hash($hash) ); } if (-f "Build.PL" && ! -f File::Spec->catfile($self->{build_dir},"Makefile.PL") && ! @{[ $merged->required_modules ]} && ! $CPAN::META->has_inst("Module::Build") ) { $CPAN::Frontend->mywarn( " Warning: CPAN.pm discovered Module::Build as undeclared prerequisite.\n". " Adding it now as such.\n" ); $CPAN::Frontend->mysleep(5); $merged->add_minimum( "Module::Build" => 0 ); delete $self->{writemakefile}; } $prereq_pm = {}; # configure_requires defined as "b" } elsif ($slot eq "later") { my $prereq_pm_0 = $self->prereq_pm || {}; for my $reqtype (qw(requires build_requires opt_requires opt_build_requires)) { $prereq_pm->{$reqtype} = {%{$prereq_pm_0->{$reqtype}||{}}}; # copy to not pollute it for my $dep ($prefs_depends,$feature_depends) { for my $k (keys %{$dep->{$reqtype}||{}}) { $prereq_pm->{$reqtype}{$k} = $dep->{$reqtype}{$k}; } } } # XXX what about optional_req|breq? -- xdg, 2012-04-01 for my $hash ( $prereq_pm->{requires}, $prereq_pm->{build_requires}, $prereq_pm->{opt_requires}, $prereq_pm->{opt_build_requires}, ) { $merged->add_requirements( CPAN::Meta::Requirements->from_string_hash($hash) ); } } else { die "Panic: illegal slot '$slot'"; } return ($merged->as_string_hash, $prereq_pm); } #-> sub CPAN::Distribution::unsat_prereq ; # return ([Foo,"r"],[Bar,"b"]) for normal modules # return ([perl=>5.008]) if we need a newer perl than we are running under # (sorry for the inconsistency, it was an accident) sub unsat_prereq { my($self,$slot) = @_; my($merged_hash,$prereq_pm) = $self->prereqs_for_slot($slot); my(@need); unless ($CPAN::META->has_usable("CPAN::Meta::Requirements")) { $CPAN::Frontend->mywarn("CPAN::Meta::Requirements not available, please install as soon as possible, trying to continue with severly limited capabilities\n"); return; } my $merged = CPAN::Meta::Requirements->from_string_hash($merged_hash); my @merged = sort $merged->required_modules; CPAN->debug("all merged_prereqs[@merged]") if $CPAN::DEBUG; NEED: for my $need_module ( @merged ) { my $need_version = $merged->requirements_for_module($need_module); my($available_version,$inst_file,$available_file,$nmo); if ($need_module eq "perl") { $available_version = $]; $available_file = CPAN::find_perl(); } else { if (CPAN::_sqlite_running()) { CPAN::Index->reload; $CPAN::SQLite->search("CPAN::Module",$need_module); } $nmo = $CPAN::META->instance("CPAN::Module",$need_module); $inst_file = $nmo->inst_file || ''; $available_file = $nmo->available_file || ''; $available_version = $nmo->available_version; if ($nmo->uptodate) { my $accepts = eval { $merged->accepts_module($need_module, $available_version); }; unless ($accepts) { my $rq = $merged->requirements_for_module( $need_module ); $CPAN::Frontend->mywarn( "Warning: Version '$available_version' of ". "'$need_module' is up to date but does not ". "fulfill requirements ($rq). I will continue, ". "but chances to succeed are low.\n"); } next NEED; } # if they have not specified a version, we accept any # installed one; in that case inst_file is always # sufficient and available_file is sufficient on # both build_requires and configure_requires my $sufficient = $inst_file || ( exists $prereq_pm->{requires}{$need_module} ? 0 : $available_file ); if ( $sufficient and ( # a few quick short circuits not defined $need_version or $need_version eq '0' # "==" would trigger warning when not numeric or $need_version eq "undef" )) { unless ($nmo->inst_deprecated) { next NEED; } } } # We only want to install prereqs if either they're not installed # or if the installed version is too old. We cannot omit this # check, because if 'force' is in effect, nobody else will check. # But we don't want to accept a deprecated module installed as part # of the Perl core, so we continue if the available file is the installed # one and is deprecated if ( $available_file ) { my $fulfills_all_version_rqs = $self->_fulfills_all_version_rqs ( $need_module, $available_file, $available_version, $need_version, ); if ( $inst_file && $available_file eq $inst_file && $nmo->inst_deprecated ) { # continue installing as a prereq. we really want that # because the deprecated module may spit out warnings # and third party did not know until today. Only one # exception is OK, because CPANPLUS is special after # all: if ( $fulfills_all_version_rqs and $nmo->id =~ /^CPANPLUS(?:::Dist::Build)$/ ) { # here we have an available version that is good # enough although deprecated (preventing circular # loop CPANPLUS => CPANPLUS::Dist::Build RT#83042) next NEED; } } elsif ( $self->{reqtype} # e.g. maybe we came via goto? && $self->{reqtype} =~ /^(r|c)$/ && ( exists $prereq_pm->{requires}{$need_module} || exists $prereq_pm->{opt_requires}{$need_module} ) && $nmo && !$inst_file ) { # continue installing as a prereq; this may be a # distro we already used when it was a build_requires # so we did not install it. But suddenly somebody # wants it as a requires my $need_distro = $nmo->distribution; if ($need_distro->{install} && $need_distro->{install}->failed && $need_distro->{install}->text =~ /is only/) { my $id = $need_distro->pretty_id; $CPAN::Frontend->myprint("Promoting $id from build_requires to requires due $need_module\n"); delete $need_distro->{install}; # promote to another installation attempt $need_distro->{reqtype} = "r"; $need_distro->install; next NEED; } } else { next NEED if $fulfills_all_version_rqs; } } if ($need_module eq "perl") { return ["perl", $need_version]; } $self->{sponsored_mods}{$need_module} ||= 0; CPAN->debug("need_module[$need_module]s/s/n[$self->{sponsored_mods}{$need_module}]") if $CPAN::DEBUG; if (my $sponsoring = $self->{sponsored_mods}{$need_module}++) { # We have already sponsored it and for some reason it's still # not available. So we do ... what?? # if we push it again, we have a potential infinite loop # The following "next" was a very problematic construct. # It helped a lot but broke some day and had to be # replaced. # We must be able to deal with modules that come again and # again as a prereq and have themselves prereqs and the # queue becomes long but finally we would find the correct # order. The RecursiveDependency check should trigger a # die when it's becoming too weird. Unfortunately removing # this next breaks many other things. # The bug that brought this up is described in Todo under # "5.8.9 cannot install Compress::Zlib" # next; # this is the next that had to go away # The following "next NEED" are fine and the error message # explains well what is going on. For example when the DBI # fails and consequently DBD::SQLite fails and now we are # processing CPAN::SQLite. Then we must have a "next" for # DBD::SQLite. How can we get it and how can we identify # all other cases we must identify? my $do = $nmo->distribution; next NEED unless $do; # not on CPAN if (CPAN::Version->vcmp($need_version, $nmo->ro->{CPAN_VERSION}) > 0){ $CPAN::Frontend->mywarn("Warning: Prerequisite ". "'$need_module => $need_version' ". "for '$self->{ID}' seems ". "not available according to the indices\n" ); next NEED; } NOSAYER: for my $nosayer ( "unwrapped", "writemakefile", "signature_verify", "make", "make_test", "install", "make_clean", ) { if ($do->{$nosayer}) { my $selfid = $self->pretty_id; my $did = $do->pretty_id; if (UNIVERSAL::can($do->{$nosayer},"failed") ? $do->{$nosayer}->failed : $do->{$nosayer} =~ /^NO/) { if ($nosayer eq "make_test" && $do->{make_test}{COMMANDID} != $CPAN::CurrentCommandId ) { next NOSAYER; } ### XXX don't complain about missing optional deps -- xdg, 2012-04-01 if ($self->is_locally_optional($prereq_pm, $need_module)) { # don't complain about failing optional prereqs } else { $CPAN::Frontend->mywarn("Warning: Prerequisite ". "'$need_module => $need_version' ". "for '$selfid' failed when ". "processing '$did' with ". "'$nosayer => $do->{$nosayer}'. Continuing, ". "but chances to succeed are limited.\n" ); $CPAN::Frontend->mysleep($sponsoring/10); } next NEED; } else { # the other guy succeeded if ($nosayer =~ /^(install|make_test)$/) { # we had this with # DMAKI/DateTime-Calendar-Chinese-0.05.tar.gz # in 2007-03 for 'make install' # and 2008-04: #30464 (for 'make test') # $CPAN::Frontend->mywarn("Warning: Prerequisite ". # "'$need_module => $need_version' ". # "for '$selfid' already built ". # "but the result looks suspicious. ". # "Skipping another build attempt, ". # "to prevent looping endlessly.\n" # ); next NEED; } } } } } my $needed_as; if (0) { } elsif (exists $prereq_pm->{requires}{$need_module} || exists $prereq_pm->{opt_requires}{$need_module} ) { $needed_as = "r"; } elsif ($slot eq "configure_requires_later") { # in ae872487d5 we said: C< we have not yet run the # {Build,Makefile}.PL, we must presume "r" >; but the # meta.yml standard says C< These dependencies are not # required after the distribution is installed. >; so now # we change it back to "b" and care for the proper # promotion later. $needed_as = "b"; } else { $needed_as = "b"; } # here need to flag as optional for recommends/suggests # -- xdg, 2012-04-01 $self->debug(sprintf "%s manadory?[%s]", $self->pretty_id, $self->{mandatory}) if $CPAN::DEBUG; my $optional = !$self->{mandatory} || $self->is_locally_optional($prereq_pm, $need_module); push @need, [$need_module,$needed_as,$optional]; } my @unfolded = map { "[".join(",",@$_)."]" } @need; CPAN->debug("returning from unsat_prereq[@unfolded]") if $CPAN::DEBUG; @need; } sub _fulfills_all_version_rqs { my($self,$need_module,$available_file,$available_version,$need_version) = @_; my(@all_requirements) = split /\s*,\s*/, $need_version; local($^W) = 0; my $ok = 0; RQ: for my $rq (@all_requirements) { if ($rq =~ s|>=\s*||) { } elsif ($rq =~ s|>\s*||) { # 2005-12: one user if (CPAN::Version->vgt($available_version,$rq)) { $ok++; } next RQ; } elsif ($rq =~ s|!=\s*||) { # 2005-12: no user if (CPAN::Version->vcmp($available_version,$rq)) { $ok++; next RQ; } else { $ok=0; last RQ; } } elsif ($rq =~ m|<=?\s*|) { # 2005-12: no user $CPAN::Frontend->mywarn("Downgrading not supported (rq[$rq])\n"); $ok++; next RQ; } elsif ($rq =~ s|==\s*||) { # 2009-07: ELLIOTJS/Perl-Critic-1.099_002.tar.gz if (CPAN::Version->vcmp($available_version,$rq)) { $ok=0; last RQ; } else { $ok++; next RQ; } } if (! CPAN::Version->vgt($rq, $available_version)) { $ok++; } CPAN->debug(sprintf("need_module[%s]available_file[%s]". "available_version[%s]rq[%s]ok[%d]", $need_module, $available_file, $available_version, CPAN::Version->readable($rq), $ok, )) if $CPAN::DEBUG; } my $ret = $ok == @all_requirements; CPAN->debug(sprintf("need_module[%s]ok[%s]all_requirements[%d]",$need_module, $ok, scalar @all_requirements)) if $CPAN::DEBUG; return $ret; } #-> sub CPAN::Distribution::read_meta # read any sort of meta files, return CPAN::Meta object if no errors sub read_meta { my($self) = @_; my $meta_file = $self->pick_meta_file or return; return unless $CPAN::META->has_usable("CPAN::Meta"); my $meta = eval { CPAN::Meta->load_file($meta_file)} or return; # Very old EU::MM could have wrong META if ($meta_file eq 'META.yml' && $meta->generated_by =~ /ExtUtils::MakeMaker version ([\d\._]+)/ ) { my $eummv = do { local $^W = 0; $1+0; }; return if $eummv < 6.2501; } return $meta; } #-> sub CPAN::Distribution::read_yaml ; # XXX This should be DEPRECATED -- dagolden, 2011-02-05 sub read_yaml { my($self) = @_; my $meta_file = $self->pick_meta_file('\.yml$'); $self->debug("meta_file[$meta_file]") if $CPAN::DEBUG; return unless $meta_file; my $yaml; eval { $yaml = $self->parse_meta_yml($meta_file) }; if ($@ or ! $yaml) { return undef; # if we die, then we cannot read YAML's own META.yml } # not "authoritative" if (defined $yaml && (! ref $yaml || ref $yaml ne "HASH")) { $CPAN::Frontend->mywarn("META.yml does not seem to be conforming, cannot use it.\n"); $yaml = undef; } $self->debug(sprintf "yaml[%s]", $yaml || "UNDEF") if $CPAN::DEBUG; $self->debug($yaml) if $CPAN::DEBUG && $yaml; # MYMETA.yml is static and authoritative by definition if ( $meta_file =~ /MYMETA\.yml/ ) { return $yaml; } # META.yml is authoritative only if dynamic_config is defined and false if ( defined $yaml->{dynamic_config} && ! $yaml->{dynamic_config} ) { return $yaml; } # otherwise, we can't use what we found return undef; } #-> sub CPAN::Distribution::configure_requires ; sub configure_requires { my($self) = @_; return unless my $meta_file = $self->pick_meta_file('^META'); if (my $meta_obj = $self->read_meta) { my $prereqs = $meta_obj->effective_prereqs; my $cr = $prereqs->requirements_for(qw/configure requires/); return $cr ? $cr->as_string_hash : undef; } else { my $yaml = eval { $self->parse_meta_yml($meta_file) }; return $yaml->{configure_requires}; } } #-> sub CPAN::Distribution::prereq_pm ; sub prereq_pm { my($self) = @_; return unless $self->{writemakefile} # no need to have succeeded # but we must have run it || $self->{modulebuild}; unless ($self->{build_dir}) { return; } # no Makefile/Build means configuration aborted, so don't look for prereqs my $makefile = File::Spec->catfile($self->{build_dir}, $^O eq 'VMS' ? 'descrip.mms' : 'Makefile'); my $buildfile = File::Spec->catfile($self->{build_dir}, $^O eq 'VMS' ? 'Build.com' : 'Build'); return unless -f $makefile || -f $buildfile; CPAN->debug(sprintf "writemakefile[%s]modulebuild[%s]", $self->{writemakefile}||"", $self->{modulebuild}||"", ) if $CPAN::DEBUG; my($req,$breq, $opt_req, $opt_breq); my $meta_obj = $self->read_meta; # META/MYMETA is only authoritative if dynamic_config is false if ($meta_obj && ! $meta_obj->dynamic_config) { my $prereqs = $meta_obj->effective_prereqs; my $requires = $prereqs->requirements_for(qw/runtime requires/); my $build_requires = $prereqs->requirements_for(qw/build requires/); my $test_requires = $prereqs->requirements_for(qw/test requires/); # XXX we don't yet distinguish build vs test, so merge them for now $build_requires->add_requirements($test_requires); $req = $requires->as_string_hash; $breq = $build_requires->as_string_hash; # XXX assemble optional_req && optional_breq from recommends/suggests # depending on corresponding policies -- xdg, 2012-04-01 CPAN->use_inst("CPAN::Meta::Requirements"); my $opt_runtime = CPAN::Meta::Requirements->new; my $opt_build = CPAN::Meta::Requirements->new; if ( $CPAN::Config->{recommends_policy} ) { $opt_runtime->add_requirements( $prereqs->requirements_for(qw/runtime recommends/)); $opt_build->add_requirements( $prereqs->requirements_for(qw/build recommends/)); $opt_build->add_requirements( $prereqs->requirements_for(qw/test recommends/)); } if ( $CPAN::Config->{suggests_policy} ) { $opt_runtime->add_requirements( $prereqs->requirements_for(qw/runtime suggests/)); $opt_build->add_requirements( $prereqs->requirements_for(qw/build suggests/)); $opt_build->add_requirements( $prereqs->requirements_for(qw/test suggests/)); } $opt_req = $opt_runtime->as_string_hash; $opt_breq = $opt_build->as_string_hash; } elsif (my $yaml = $self->read_yaml) { # often dynamic_config prevents a result here $req = $yaml->{requires} || {}; $breq = $yaml->{build_requires} || {}; if ( $CPAN::Config->{recommends_policy} ) { $opt_req = $yaml->{recommends} || {}; } undef $req unless ref $req eq "HASH" && %$req; if ($req) { if ($yaml->{generated_by} && $yaml->{generated_by} =~ /ExtUtils::MakeMaker version ([\d\._]+)/) { my $eummv = do { local $^W = 0; $1+0; }; if ($eummv < 6.2501) { # thanks to Slaven for digging that out: MM before # that could be wrong because it could reflect a # previous release undef $req; } } my $areq; my $do_replace; foreach my $k (sort keys %{$req||{}}) { my $v = $req->{$k}; next unless defined $v; if ($v =~ /\d/) { $areq->{$k} = $v; } elsif ($k =~ /[A-Za-z]/ && $v =~ /[A-Za-z]/ && $CPAN::META->exists("CPAN::Module",$v) ) { $CPAN::Frontend->mywarn("Suspicious key-value pair in META.yml's ". "requires hash: $k => $v; I'll take both ". "key and value as a module name\n"); $CPAN::Frontend->mysleep(1); $areq->{$k} = 0; $areq->{$v} = 0; $do_replace++; } } $req = $areq if $do_replace; } } else { $CPAN::Frontend->mywarnonce("Could not read metadata file. Falling back to other ". "methods to determine prerequisites\n"); } unless ($req || $breq) { my $build_dir; unless ( $build_dir = $self->{build_dir} ) { return; } my $makefile = File::Spec->catfile($build_dir,"Makefile"); my $fh; if (-f $makefile and $fh = FileHandle->new("<$makefile\0")) { CPAN->debug("Getting prereq from Makefile") if $CPAN::DEBUG; local($/) = "\n"; while (<$fh>) { last if /MakeMaker post_initialize section/; my($p) = m{^[\#] \s+PREREQ_PM\s+=>\s+(.+) }x; next unless $p; # warn "Found prereq expr[$p]"; # Regexp modified by A.Speer to remember actual version of file # PREREQ_PM hash key wants, then add to while ( $p =~ m/(?:\s)([\w\:]+)=>(q\[.*?\]|undef),?/g ) { my($m,$n) = ($1,$2); # When a prereq is mentioned twice: let the bigger # win; usual culprit is that they declared # build_requires separately from requires; see # rt.cpan.org #47774 my($prevn); if ( defined $req->{$m} ) { $prevn = $req->{$m}; } if ($n =~ /^q\[(.*?)\]$/) { $n = $1; } if (!$prevn || CPAN::Version->vlt($prevn, $n)){ $req->{$m} = $n; } } last; } } } unless ($req || $breq) { my $build_dir = $self->{build_dir} or die "Panic: no build_dir?"; my $buildfile = File::Spec->catfile($build_dir,"Build"); if (-f $buildfile) { CPAN->debug("Found '$buildfile'") if $CPAN::DEBUG; my $build_prereqs = File::Spec->catfile($build_dir,"_build","prereqs"); if (-f $build_prereqs) { CPAN->debug("Getting prerequisites from '$build_prereqs'") if $CPAN::DEBUG; my $content = do { local *FH; open FH, $build_prereqs or $CPAN::Frontend->mydie("Could not open ". "'$build_prereqs': $!"); local $/; <FH>; }; my $bphash = eval $content; if ($@) { } else { $req = $bphash->{requires} || +{}; $breq = $bphash->{build_requires} || +{}; } } } } # XXX needs to be adapted for optional_req & optional_breq -- xdg, 2012-04-01 if ($req || $breq || $opt_req || $opt_breq ) { return $self->{prereq_pm} = { requires => $req, build_requires => $breq, opt_requires => $opt_req, opt_build_requires => $opt_breq, }; } } #-> sub CPAN::Distribution::shortcut_test ; # return values: undef means don't shortcut; 0 means shortcut as fail; # and 1 means shortcut as success sub shortcut_test { my ($self) = @_; $self->debug("checking badtestcnt[$self->{ID}]") if $CPAN::DEBUG; $self->{badtestcnt} ||= 0; if ($self->{badtestcnt} > 0) { require Data::Dumper; CPAN->debug(sprintf "NOREPEAT[%s]", Data::Dumper::Dumper($self)) if $CPAN::DEBUG; return $self->goodbye("Won't repeat unsuccessful test during this command"); } for my $slot ( qw/later configure_requires_later/ ) { $self->debug("checking $slot slot[$self->{ID}]") if $CPAN::DEBUG; return $self->success($self->{$slot}) if $self->{$slot}; } $self->debug("checking if tests passed[$self->{ID}]") if $CPAN::DEBUG; if ( $self->{make_test} ) { if ( UNIVERSAL::can($self->{make_test},"failed") ? $self->{make_test}->failed : $self->{make_test} =~ /^NO/ ) { if ( UNIVERSAL::can($self->{make_test},"commandid") && $self->{make_test}->commandid == $CPAN::CurrentCommandId ) { return $self->goodbye("Has already been tested within this command"); } } else { # if global "is_tested" has been cleared, we need to mark this to # be added to PERL5LIB if not already installed if ($self->tested_ok_but_not_installed) { $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME}); } return $self->success("Has already been tested successfully"); } } if ($self->{notest}) { $self->{make_test} = CPAN::Distrostatus->new("YES"); return $self->success("Skipping test because of notest pragma"); } return undef; # no shortcut } #-> sub CPAN::Distribution::_exe_files ; sub _exe_files { my($self) = @_; return unless $self->{writemakefile} # no need to have succeeded # but we must have run it || $self->{modulebuild}; unless ($self->{build_dir}) { return; } CPAN->debug(sprintf "writemakefile[%s]modulebuild[%s]", $self->{writemakefile}||"", $self->{modulebuild}||"", ) if $CPAN::DEBUG; my $build_dir; unless ( $build_dir = $self->{build_dir} ) { return; } my $makefile = File::Spec->catfile($build_dir,"Makefile"); my $fh; my @exe_files; if (-f $makefile and $fh = FileHandle->new("<$makefile\0")) { CPAN->debug("Getting exefiles from Makefile") if $CPAN::DEBUG; local($/) = "\n"; while (<$fh>) { last if /MakeMaker post_initialize section/; my($p) = m{^[\#] \s+EXE_FILES\s+=>\s+\[(.+)\] }x; next unless $p; # warn "Found exefiles expr[$p]"; my @p = split /,\s*/, $p; for my $p2 (@p) { if ($p2 =~ /^q\[(.+)\]/) { push @exe_files, $1; } } } } return \@exe_files if @exe_files; my $buildparams = File::Spec->catfile($build_dir,"_build","build_params"); if (-f $buildparams) { CPAN->debug("Found '$buildparams'") if $CPAN::DEBUG; my $x = do $buildparams; for my $sf ($x->[2]{script_files}) { if (my $reftype = ref $sf) { if ($reftype eq "ARRAY") { push @exe_files, @$sf; } elsif ($reftype eq "HASH") { push @exe_files, keys %$sf; } else { $CPAN::Frontend->mywarn("Invalid reftype $reftype for Build.PL 'script_files'\n"); } } elsif (defined $sf) { push @exe_files, $sf; } } } return \@exe_files; } #-> sub CPAN::Distribution::test ; sub test { my($self) = @_; $self->pre_test(); if (exists $self->{cleanup_after_install_done}) { $self->post_test(); return $self->make; } $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG; if (my $goto = $self->prefs->{goto}) { $self->post_test(); return $self->goto($goto); } unless ($self->make){ $self->post_test(); return; } if ( defined( my $sc = $self->shortcut_test ) ) { $self->post_test(); return $sc; } if ($CPAN::Signal) { delete $self->{force_update}; $self->post_test(); return; } # warn "XDEBUG: checking for notest: $self->{notest} $self"; my $make = $self->{modulebuild} ? "Build" : "make"; local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) ? $ENV{PERL5LIB} : ($ENV{PERLLIB} || ""); local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : ""; local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} && defined $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # test $CPAN::META->set_perl5lib; local $ENV{MAKEFLAGS}; # protect us from outer make calls local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default}; local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default}; if ($run_allow_installing_within_test) { my($allow_installing, $why) = $self->_allow_installing; if (! $allow_installing) { $CPAN::Frontend->mywarn("Testing/Installation stopped: $why\n"); $self->introduce_myself; $self->{make_test} = CPAN::Distrostatus->new("NO -- testing/installation stopped due $why"); $CPAN::Frontend->mywarn(" [testing] -- NOT OK\n"); delete $self->{force_update}; $self->post_test(); return; } } $CPAN::Frontend->myprint(sprintf "Running %s test for %s\n", $make, $self->pretty_id); my $builddir = $self->dir or $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n"); unless (chdir $builddir) { $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!"); $self->post_test(); return; } $self->debug("Changed directory to $self->{build_dir}") if $CPAN::DEBUG; if ($^O eq 'MacOS') { Mac::BuildTools::make_test($self); $self->post_test(); return; } if ($self->{modulebuild}) { my $thm = CPAN::Shell->expand("Module","Test::Harness"); my $v = $thm->inst_version; if (CPAN::Version->vlt($v,2.62)) { # XXX Eric Wilhelm reported this as a bug: klapperl: # Test::Harness 3.0 self-tests, so that should be 'unless # installing Test::Harness' unless ($self->id eq $thm->distribution->id) { $CPAN::Frontend->mywarn(qq{The version of your Test::Harness is only '$v', you need at least '2.62'. Please upgrade your Test::Harness.\n}); $self->{make_test} = CPAN::Distrostatus->new("NO Test::Harness too old"); $self->post_test(); return; } } } if ( ! $self->{force_update} ) { # bypass actual tests if "trust_test_report_history" and have a report my $have_tested_fcn; if ( $CPAN::Config->{trust_test_report_history} && $CPAN::META->has_inst("CPAN::Reporter::History") && ( $have_tested_fcn = CPAN::Reporter::History->can("have_tested" ))) { if ( my @reports = $have_tested_fcn->( dist => $self->base_id ) ) { # Do nothing if grade was DISCARD if ( $reports[-1]->{grade} =~ /^(?:PASS|UNKNOWN)$/ ) { $self->{make_test} = CPAN::Distrostatus->new("YES"); # if global "is_tested" has been cleared, we need to mark this to # be added to PERL5LIB if not already installed if ($self->tested_ok_but_not_installed) { $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME}); } $CPAN::Frontend->myprint("Found prior test report -- OK\n"); $self->post_test(); return; } elsif ( $reports[-1]->{grade} =~ /^(?:FAIL|NA)$/ ) { $self->{make_test} = CPAN::Distrostatus->new("NO"); $self->{badtestcnt}++; $CPAN::Frontend->mywarn("Found prior test report -- NOT OK\n"); $self->post_test(); return; } } } } my $system; my $prefs_test = $self->prefs->{test}; if (my $commandline = exists $prefs_test->{commandline} ? $prefs_test->{commandline} : "") { $system = $commandline; $ENV{PERL} = CPAN::find_perl(); } elsif ($self->{modulebuild}) { $system = sprintf "%s test", $self->_build_command(); unless (-e "Build" || ($^O eq 'VMS' && -e "Build.com")) { my $id = $self->pretty_id; $CPAN::Frontend->mywarn("Alert: no 'Build' file found while trying to test '$id'"); } } else { $system = join " ", $self->_make_command(), "test"; } my $make_test_arg = $self->_make_phase_arg("test"); $system = sprintf("%s%s", $system, $make_test_arg ? " $make_test_arg" : "", ); my($tests_ok); my $test_env; if ($self->prefs->{test}) { $test_env = $self->prefs->{test}{env}; } local @ENV{keys %$test_env} = values %$test_env if $test_env; my $expect_model = $self->_prefs_with_expect("test"); my $want_expect = 0; if ( $expect_model && @{$expect_model->{talk}} ) { my $can_expect = $CPAN::META->has_inst("Expect"); if ($can_expect) { $want_expect = 1; } else { $CPAN::Frontend->mywarn("Expect not installed, falling back to ". "testing without\n"); } } FORK: { my $pid = fork; if (! defined $pid) { # contention warn "Contention '$!', sleeping 2"; sleep 2; redo FORK; } elsif ($pid) { # parent if ($^O eq "MSWin32") { wait; } else { SUPERVISE: while (waitpid($pid, WNOHANG) <= 0) { if ($CPAN::Signal) { kill 9, -$pid; } sleep 1; } } $tests_ok = !$?; } else { # child POSIX::setsid() unless $^O eq "MSWin32"; my $c_ok; $|=1; if ($want_expect) { if ($self->_should_report('test')) { $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is currently ". "not supported when distroprefs specify ". "an interactive test\n"); } $c_ok = $self->_run_via_expect($system,'test',$expect_model) == 0; } elsif ( $self->_should_report('test') ) { $c_ok = CPAN::Reporter::test($self, $system); } else { $c_ok = system($system) == 0; } exit !$c_ok; } } # FORK $self->introduce_myself; my $but = $self->_make_test_illuminate_prereqs(); if ( $tests_ok ) { if ($but) { $CPAN::Frontend->mywarn("Tests succeeded but $but\n"); $self->{make_test} = CPAN::Distrostatus->new("NO $but"); $self->store_persistent_state; $self->post_test(); return $self->goodbye("[dependencies] -- NA"); } $CPAN::Frontend->myprint(" $system -- OK\n"); $self->{make_test} = CPAN::Distrostatus->new("YES"); $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME}); # probably impossible to need the next line because badtestcnt # has a lifespan of one command delete $self->{badtestcnt}; } else { if ($but) { $but .= "; additionally test harness failed"; $CPAN::Frontend->mywarn("$but\n"); $self->{make_test} = CPAN::Distrostatus->new("NO $but"); } elsif ( $self->{force_update} ) { $self->{make_test} = CPAN::Distrostatus->new( "NO but failure ignored because 'force' in effect" ); } elsif ($CPAN::Signal) { $self->{make_test} = CPAN::Distrostatus->new("NO -- Interrupted"); } else { $self->{make_test} = CPAN::Distrostatus->new("NO"); } $self->{badtestcnt}++; $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); CPAN::Shell->optprint ("hint", sprintf ("//hint// to see the cpan-testers results for installing this module, try: reports %s\n", $self->pretty_id)); } $self->store_persistent_state; $self->post_test(); return $self->{force_update} ? 1 : !! $tests_ok; } sub _make_test_illuminate_prereqs { my($self) = @_; my @prereq; # local $CPAN::DEBUG = 16; # Distribution for my $m (sort keys %{$self->{sponsored_mods}}) { next unless $self->{sponsored_mods}{$m} > 0; my $m_obj = CPAN::Shell->expand("Module",$m) or next; # XXX we need available_version which reflects # $ENV{PERL5LIB} so that already tested but not yet # installed modules are counted. my $available_version = $m_obj->available_version; my $available_file = $m_obj->available_file; if ($available_version && !CPAN::Version->vlt($available_version,$self->{prereq_pm}{$m}) ) { CPAN->debug("m[$m] good enough available_version[$available_version]") if $CPAN::DEBUG; } elsif ($available_file && ( !$self->{prereq_pm}{$m} || $self->{prereq_pm}{$m} == 0 ) ) { # lex Class::Accessor::Chained::Fast which has no $VERSION CPAN->debug("m[$m] have available_file[$available_file]") if $CPAN::DEBUG; } else { push @prereq, $m unless $self->is_locally_optional(undef, $m); } } my $but; if (@prereq) { my $cnt = @prereq; my $which = join ",", @prereq; $but = $cnt == 1 ? "one dependency not OK ($which)" : "$cnt dependencies missing ($which)"; } $but; } sub _prefs_with_expect { my($self,$where) = @_; return unless my $prefs = $self->prefs; return unless my $where_prefs = $prefs->{$where}; if ($where_prefs->{expect}) { return { mode => "deterministic", timeout => 15, talk => $where_prefs->{expect}, }; } elsif ($where_prefs->{"eexpect"}) { return $where_prefs->{"eexpect"}; } return; } #-> sub CPAN::Distribution::clean ; sub clean { my($self) = @_; my $make = $self->{modulebuild} ? "Build" : "make"; $CPAN::Frontend->myprint(sprintf "Running %s clean for %s\n", $make, $self->pretty_id); unless (exists $self->{archived}) { $CPAN::Frontend->mywarn("Distribution seems to have never been unzipped". "/untarred, nothing done\n"); return 1; } unless (exists $self->{build_dir}) { $CPAN::Frontend->mywarn("Distribution has no own directory, nothing to do.\n"); return 1; } if (exists $self->{writemakefile} and $self->{writemakefile}->failed ) { $CPAN::Frontend->mywarn("No Makefile, don't know how to 'make clean'\n"); return 1; } EXCUSE: { my @e; exists $self->{make_clean} and $self->{make_clean} eq "YES" and push @e, "make clean already called once"; $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e; } chdir "$self->{build_dir}" or Carp::confess("Couldn't chdir to $self->{build_dir}: $!"); $self->debug("Changed directory to $self->{build_dir}") if $CPAN::DEBUG; if ($^O eq 'MacOS') { Mac::BuildTools::make_clean($self); return; } my $system; if ($self->{modulebuild}) { unless (-f "Build") { my $cwd = CPAN::anycwd(); $CPAN::Frontend->mywarn("Alert: no Build file available for 'clean $self->{id}". " in cwd[$cwd]. Danger, Will Robinson!"); $CPAN::Frontend->mysleep(5); } $system = sprintf "%s clean", $self->_build_command(); } else { $system = join " ", $self->_make_command(), "clean"; } my $system_ok = system($system) == 0; $self->introduce_myself; if ( $system_ok ) { $CPAN::Frontend->myprint(" $system -- OK\n"); # $self->force; # Jost Krieger pointed out that this "force" was wrong because # it has the effect that the next "install" on this distribution # will untar everything again. Instead we should bring the # object's state back to where it is after untarring. for my $k (qw( force_update install writemakefile make make_test )) { delete $self->{$k}; } $self->{make_clean} = CPAN::Distrostatus->new("YES"); } else { # Hmmm, what to do if make clean failed? $self->{make_clean} = CPAN::Distrostatus->new("NO"); $CPAN::Frontend->mywarn(qq{ $system -- NOT OK\n}); # 2006-02-27: seems silly to me to force a make now # $self->force("make"); # so that this directory won't be used again } $self->store_persistent_state; } #-> sub CPAN::Distribution::check_disabled ; sub check_disabled { my ($self) = @_; $self->debug("checking disabled id[$self->{ID}]") if $CPAN::DEBUG; if ($self->prefs->{disabled} && ! $self->{force_update}) { return sprintf( "Disabled via prefs file '%s' doc %d", $self->{prefs_file}, $self->{prefs_file_doc}, ); } return; } #-> sub CPAN::Distribution::goto ; sub goto { my($self,$goto) = @_; $goto = $self->normalize($goto); my $why = sprintf( "Goto '$goto' via prefs file '%s' doc %d", $self->{prefs_file}, $self->{prefs_file_doc}, ); $self->{unwrapped} = CPAN::Distrostatus->new("NO $why"); # 2007-07-16 akoenig : Better than NA would be if we could inherit # the status of the $goto distro but given the exceptional nature # of 'goto' I feel reluctant to implement it my $goodbye_message = "[goto] -- NA $why"; $self->goodbye($goodbye_message); # inject into the queue CPAN::Queue->delete($self->id); CPAN::Queue->jumpqueue({qmod => $goto, reqtype => $self->{reqtype}}); # and run where we left off my($method) = (caller(1))[3]; my $goto_do = CPAN->instance("CPAN::Distribution",$goto); $goto_do->called_for($self->called_for) unless $goto_do->called_for; $goto_do->{mandatory} ||= $self->{mandatory}; $goto_do->{reqtype} ||= $self->{reqtype}; $goto_do->{coming_from} = $self->pretty_id; $goto_do->$method(); CPAN::Queue->delete_first($goto); # XXX delete_first returns undef; is that what this should return # up the call stack, eg. return $sefl->goto($goto) -- xdg, 2012-04-04 } #-> sub CPAN::Distribution::shortcut_install ; # return values: undef means don't shortcut; 0 means shortcut as fail; # and 1 means shortcut as success sub shortcut_install { my ($self) = @_; $self->debug("checking previous install results[$self->{ID}]") if $CPAN::DEBUG; if (exists $self->{install}) { my $text = UNIVERSAL::can($self->{install},"text") ? $self->{install}->text : $self->{install}; if ($text =~ /^YES/) { $CPAN::META->is_installed($self->{build_dir}); return $self->success("Already done"); } elsif ($text =~ /is only/) { # e.g. 'is only build_requires': may be overruled later return $self->goodbye($text); } else { # comment in Todo on 2006-02-11; maybe retry? return $self->goodbye("Already tried without success"); } } for my $slot ( qw/later configure_requires_later/ ) { return $self->success($self->{$slot}) if $self->{$slot}; } return undef; } #-> sub CPAN::Distribution::is_being_sponsored ; # returns true if we find a distro object in the queue that has # sponsored this one sub is_being_sponsored { my($self) = @_; my $iterator = CPAN::Queue->iterator; QITEM: while (my $q = $iterator->()) { my $s = $q->as_string; my $obj = CPAN::Shell->expandany($s) or next QITEM; my $type = ref $obj; if ( $type eq 'CPAN::Distribution' ){ for my $module (sort keys %{$obj->{sponsored_mods} || {}}) { return 1 if grep { $_ eq $module } $self->containsmods; } } } return 0; } #-> sub CPAN::Distribution::install ; sub install { my($self) = @_; $self->pre_install(); if (exists $self->{cleanup_after_install_done}) { return $self->test; } $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG; if (my $goto = $self->prefs->{goto}) { $self->goto($goto); $self->post_install(); return; } unless ($self->test) { $self->post_install(); return; } if ( defined( my $sc = $self->shortcut_install ) ) { $self->post_install(); return $sc; } if ($CPAN::Signal) { delete $self->{force_update}; $self->post_install(); return; } my $builddir = $self->dir or $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n"); unless (chdir $builddir) { $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!"); $self->post_install(); return; } $self->debug("Changed directory to $self->{build_dir}") if $CPAN::DEBUG; my $make = $self->{modulebuild} ? "Build" : "make"; $CPAN::Frontend->myprint(sprintf "Running %s install for %s\n", $make, $self->pretty_id); if ($^O eq 'MacOS') { Mac::BuildTools::make_install($self); $self->post_install(); return; } my $system; if (my $commandline = $self->prefs->{install}{commandline}) { $system = $commandline; $ENV{PERL} = CPAN::find_perl(); } elsif ($self->{modulebuild}) { my($mbuild_install_build_command) = exists $CPAN::HandleConfig::keys{mbuild_install_build_command} && $CPAN::Config->{mbuild_install_build_command} ? $CPAN::Config->{mbuild_install_build_command} : $self->_build_command(); my $install_directive = $^O eq 'VMS' ? '"install"' : 'install'; $system = sprintf("%s %s %s", $mbuild_install_build_command, $install_directive, $CPAN::Config->{mbuild_install_arg}, ); } else { my($make_install_make_command) = $self->_make_install_make_command(); $system = sprintf("%s install %s", $make_install_make_command, $CPAN::Config->{make_install_arg}, ); } my($stderr) = $^O eq "MSWin32" || $^O eq 'VMS' ? "" : " 2>&1 "; my $brip = CPAN::HandleConfig->prefs_lookup($self, q{build_requires_install_policy}); $brip ||="ask/yes"; my $id = $self->id; my $reqtype = $self->{reqtype} ||= "c"; # in doubt it was a command my $want_install = "yes"; if ($reqtype eq "b") { if ($brip eq "no") { $want_install = "no"; } elsif ($brip =~ m|^ask/(.+)|) { my $default = $1; $default = "yes" unless $default =~ /^(y|n)/i; $want_install = CPAN::Shell::colorable_makemaker_prompt ("$id is just needed temporarily during building or testing. ". "Do you want to install it permanently?", $default); } } unless ($want_install =~ /^y/i) { my $is_only = "is only 'build_requires'"; $self->{install} = CPAN::Distrostatus->new("NO -- $is_only"); delete $self->{force_update}; $self->goodbye("Not installing because $is_only"); $self->post_install(); return; } local $ENV{PERL5LIB} = defined($ENV{PERL5LIB}) ? $ENV{PERL5LIB} : ($ENV{PERLLIB} || ""); local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : ""; local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} && defined $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # install $CPAN::META->set_perl5lib; local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default}; local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default}; my $install_env; if ($self->prefs->{install}) { $install_env = $self->prefs->{install}{env}; } local @ENV{keys %$install_env} = values %$install_env if $install_env; if (! $run_allow_installing_within_test) { my($allow_installing, $why) = $self->_allow_installing; if (! $allow_installing) { $CPAN::Frontend->mywarn("Installation stopped: $why\n"); $self->introduce_myself; $self->{install} = CPAN::Distrostatus->new("NO -- installation stopped due $why"); $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); delete $self->{force_update}; $self->post_install(); return; } } my($pipe) = FileHandle->new("$system $stderr |"); unless ($pipe) { $CPAN::Frontend->mywarn("Can't execute $system: $!"); $self->introduce_myself; $self->{install} = CPAN::Distrostatus->new("NO"); $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); delete $self->{force_update}; $self->post_install(); return; } my($makeout) = ""; while (<$pipe>) { print $_; # intentionally NOT use Frontend->myprint because it # looks irritating when we markup in color what we # just pass through from an external program $makeout .= $_; } $pipe->close; my $close_ok = $? == 0; $self->introduce_myself; if ( $close_ok ) { $CPAN::Frontend->myprint(" $system -- OK\n"); $CPAN::META->is_installed($self->{build_dir}); $self->{install} = CPAN::Distrostatus->new("YES"); if ($CPAN::Config->{'cleanup_after_install'} && ! $self->is_dot_dist && ! $self->is_being_sponsored) { my $parent = File::Spec->catdir( $self->{build_dir}, File::Spec->updir ); chdir $parent or $CPAN::Frontend->mydie("Couldn't chdir to $parent: $!\n"); File::Path::rmtree($self->{build_dir}); my $yml = "$self->{build_dir}.yml"; if (-e $yml) { unlink $yml or $CPAN::Frontend->mydie("Couldn't unlink $yml: $!\n"); } $self->{cleanup_after_install_done}=1; } } else { $self->{install} = CPAN::Distrostatus->new("NO"); $CPAN::Frontend->mywarn(" $system -- NOT OK\n"); my $mimc = CPAN::HandleConfig->prefs_lookup($self, q{make_install_make_command}); if ( $makeout =~ /permission/s && $> > 0 && ( ! $mimc || $mimc eq (CPAN::HandleConfig->prefs_lookup($self, q{make})) ) ) { $CPAN::Frontend->myprint( qq{----\n}. qq{ You may have to su }. qq{to root to install the package\n}. qq{ (Or you may want to run something like\n}. qq{ o conf make_install_make_command 'sudo make'\n}. qq{ to raise your permissions.} ); } } delete $self->{force_update}; unless ($CPAN::Config->{'cleanup_after_install'}) { $self->store_persistent_state; } $self->post_install(); return !! $close_ok; } sub blib_pm_walk { my @queue = grep { -e $_ } File::Spec->catdir("blib","lib"), File::Spec->catdir("blib","arch"); return sub { LOOP: { if (@queue) { my $file = shift @queue; if (-d $file) { my $dh; opendir $dh, $file or next; my @newfiles = map { my @ret; my $maybedir = File::Spec->catdir($file, $_); if (-d $maybedir) { unless (File::Spec->catdir("blib","arch","auto") eq $maybedir) { # prune the blib/arch/auto directory, no pm files there @ret = $maybedir; } } elsif (/\.pm$/) { my $mustbefile = File::Spec->catfile($file, $_); if (-f $mustbefile) { @ret = $mustbefile; } } @ret; } grep { $_ ne "." && $_ ne ".." } readdir $dh; push @queue, @newfiles; redo LOOP; } else { return $file; } } else { return; } } }; } sub _allow_installing { my($self) = @_; my $id = my $pretty_id = $self->pretty_id; if ($self->{CALLED_FOR}) { $id .= " (called for $self->{CALLED_FOR})"; } my $allow_down = CPAN::HandleConfig->prefs_lookup($self,q{allow_installing_module_downgrades}); $allow_down ||= "ask/yes"; my $allow_outdd = CPAN::HandleConfig->prefs_lookup($self,q{allow_installing_outdated_dists}); $allow_outdd ||= "ask/yes"; return 1 if $allow_down eq "yes" && $allow_outdd eq "yes"; if (($allow_outdd ne "yes") && ! $CPAN::META->has_inst('CPAN::DistnameInfo')) { return 1 if grep { $_ eq 'CPAN::DistnameInfo'} $self->containsmods; if ($allow_outdd ne "yes") { $CPAN::Frontend->mywarn("The current configuration of allow_installing_outdated_dists is '$allow_outdd', but for this option we would need 'CPAN::DistnameInfo' installed. Please install 'CPAN::DistnameInfo' as soon as possible. As long as we are not equipped with 'CPAN::DistnameInfo' this option does not take effect\n"); $allow_outdd = "yes"; } } return 1 if $allow_down eq "yes" && $allow_outdd eq "yes"; my($dist_version, $dist_dist); if ($allow_outdd ne "yes"){ my $dni = CPAN::DistnameInfo->new($pretty_id); $dist_version = $dni->version; $dist_dist = $dni->dist; } my $iterator = blib_pm_walk(); my(@down,@outdd); while (my $file = $iterator->()) { my $version = CPAN::Module->parse_version($file); my($volume, $directories, $pmfile) = File::Spec->splitpath( $file ); my @dirs = File::Spec->splitdir( $directories ); my(@blib_plus1) = splice @dirs, 0, 2; my($pmpath) = File::Spec->catfile(grep { length($_) } @dirs, $pmfile); unless ($allow_down eq "yes") { if (my $inst_file = $self->_file_in_path($pmpath, \@INC)) { my $inst_version = CPAN::Module->parse_version($inst_file); my $cmp = CPAN::Version->vcmp($version, $inst_version); if ($cmp) { if ($cmp < 0) { push @down, { pmpath => $pmpath, version => $version, inst_version => $inst_version }; } } if (@down) { my $why = "allow_installing_module_downgrades: $id contains downgrading module(s) (e.g. '$down[0]{pmpath}' would downgrade installed '$down[0]{inst_version}' to '$down[0]{version}')"; if (my($default) = $allow_down =~ m|^ask/(.+)|) { $default = "yes" unless $default =~ /^(y|n)/i; my $answer = CPAN::Shell::colorable_makemaker_prompt ("$why. Do you want to allow installing it?", $default, "colorize_warn"); $allow_down = $answer =~ /^\s*y/i ? "yes" : "no"; } if ($allow_down eq "no") { return (0, $why); } } } } unless ($allow_outdd eq "yes") { my @pmpath = (@dirs, $pmfile); $pmpath[-1] =~ s/\.pm$//; my $mo = CPAN::Shell->expand("Module",join "::", grep { length($_) } @pmpath); if ($mo) { my $cpan_version = $mo->cpan_version; my $is_lower = CPAN::Version->vlt($version, $cpan_version); my $other_dist; if (my $mo_dist = $mo->distribution) { $other_dist = $mo_dist->pretty_id; my $dni = CPAN::DistnameInfo->new($other_dist); if ($dni->dist eq $dist_dist){ if (CPAN::Version->vgt($dni->version, $dist_version)) { push @outdd, { pmpath => $pmpath, cpan_path => $dni->pathname, dist_version => $dni->version, dist_dist => $dni->dist, }; } } } } if (@outdd && $allow_outdd ne "yes") { my $why = "allow_installing_outdated_dists: $id contains module(s) that are indexed on the CPAN with a different distro: (e.g. '$outdd[0]{pmpath}' is indexed with '$outdd[0]{cpan_path}')"; if ($outdd[0]{dist_dist} eq $dist_dist) { $why .= ", and this has a higher distribution-version, i.e. version '$outdd[0]{dist_version}' is higher than '$dist_version')"; } if (my($default) = $allow_outdd =~ m|^ask/(.+)|) { $default = "yes" unless $default =~ /^(y|n)/i; my $answer = CPAN::Shell::colorable_makemaker_prompt ("$why. Do you want to allow installing it?", $default, "colorize_warn"); $allow_outdd = $answer =~ /^\s*y/i ? "yes" : "no"; } if ($allow_outdd eq "no") { return (0, $why); } } } } return 1; } sub _file_in_path { # similar to CPAN::Module::_file_in_path my($self,$pmpath,$incpath) = @_; my($dir,@packpath); foreach $dir (@$incpath) { my $pmfile = File::Spec->catfile($dir,$pmpath); if (-f $pmfile) { return $pmfile; } } return; } sub introduce_myself { my($self) = @_; $CPAN::Frontend->myprint(sprintf(" %s\n",$self->pretty_id)); } #-> sub CPAN::Distribution::dir ; sub dir { shift->{build_dir}; } #-> sub CPAN::Distribution::perldoc ; sub perldoc { my($self) = @_; my($dist) = $self->id; my $package = $self->called_for; if ($CPAN::META->has_inst("Pod::Perldocs")) { my($perl) = $self->perl or $CPAN::Frontend->mydie("Couldn't find executable perl\n"); my @args = ($perl, q{-MPod::Perldocs}, q{-e}, q{Pod::Perldocs->run()}, $package); my($wstatus); unless ( ($wstatus = system(@args)) == 0 ) { my $estatus = $wstatus >> 8; $CPAN::Frontend->myprint(qq{ Function system("@args") returned status $estatus (wstat $wstatus) }); } } else { $self->_display_url( $CPAN::Defaultdocs . $package ); } } #-> sub CPAN::Distribution::_check_binary ; sub _check_binary { my ($dist,$shell,$binary) = @_; my ($pid,$out); $CPAN::Frontend->myprint(qq{ + _check_binary($binary)\n}) if $CPAN::DEBUG; if ($CPAN::META->has_inst("File::Which")) { return File::Which::which($binary); } else { local *README; $pid = open README, "which $binary|" or $CPAN::Frontend->mywarn(qq{Could not fork 'which $binary': $!\n}); return unless $pid; while (<README>) { $out .= $_; } close README or $CPAN::Frontend->mywarn("Could not run 'which $binary': $!\n") and return; } $CPAN::Frontend->myprint(qq{ + $out \n}) if $CPAN::DEBUG && $out; return $out; } #-> sub CPAN::Distribution::_display_url ; sub _display_url { my($self,$url) = @_; my($res,$saved_file,$pid,$out); $CPAN::Frontend->myprint(qq{ + _display_url($url)\n}) if $CPAN::DEBUG; # should we define it in the config instead? my $html_converter = "html2text.pl"; my $web_browser = $CPAN::Config->{'lynx'} || undef; my $web_browser_out = $web_browser ? CPAN::Distribution->_check_binary($self,$web_browser) : undef; if ($web_browser_out) { # web browser found, run the action my $browser = CPAN::HandleConfig->safe_quote($CPAN::Config->{'lynx'}); $CPAN::Frontend->myprint(qq{system[$browser $url]}) if $CPAN::DEBUG; $CPAN::Frontend->myprint(qq{ Displaying URL $url with browser $browser }); $CPAN::Frontend->mysleep(1); system("$browser $url"); if ($saved_file) { 1 while unlink($saved_file) } } else { # web browser not found, let's try text only my $html_converter_out = CPAN::Distribution->_check_binary($self,$html_converter); $html_converter_out = CPAN::HandleConfig->safe_quote($html_converter_out); if ($html_converter_out ) { # html2text found, run it $saved_file = CPAN::Distribution->_getsave_url( $self, $url ); $CPAN::Frontend->mydie(qq{ERROR: problems while getting $url\n}) unless defined($saved_file); local *README; $pid = open README, "$html_converter $saved_file |" or $CPAN::Frontend->mydie(qq{ Could not fork '$html_converter $saved_file': $!}); my($fh,$filename); if ($CPAN::META->has_usable("File::Temp")) { $fh = File::Temp->new( dir => File::Spec->tmpdir, template => 'cpan_htmlconvert_XXXX', suffix => '.txt', unlink => 0, ); $filename = $fh->filename; } else { $filename = "cpan_htmlconvert_$$.txt"; $fh = FileHandle->new(); open $fh, ">$filename" or die; } while (<README>) { $fh->print($_); } close README or $CPAN::Frontend->mydie(qq{Could not run '$html_converter $saved_file': $!}); my $tmpin = $fh->filename; $CPAN::Frontend->myprint(sprintf(qq{ Run '%s %s' and saved output to %s\n}, $html_converter, $saved_file, $tmpin, )) if $CPAN::DEBUG; close $fh; local *FH; open FH, $tmpin or $CPAN::Frontend->mydie(qq{Could not open "$tmpin": $!}); my $fh_pager = FileHandle->new; local($SIG{PIPE}) = "IGNORE"; my $pager = $CPAN::Config->{'pager'} || "cat"; $fh_pager->open("|$pager") or $CPAN::Frontend->mydie(qq{ Could not open pager '$pager': $!}); $CPAN::Frontend->myprint(qq{ Displaying URL $url with pager "$pager" }); $CPAN::Frontend->mysleep(1); $fh_pager->print(<FH>); $fh_pager->close; } else { # coldn't find the web browser or html converter $CPAN::Frontend->myprint(qq{ You need to install lynx or $html_converter to use this feature.}); } } } #-> sub CPAN::Distribution::_getsave_url ; sub _getsave_url { my($dist, $shell, $url) = @_; $CPAN::Frontend->myprint(qq{ + _getsave_url($url)\n}) if $CPAN::DEBUG; my($fh,$filename); if ($CPAN::META->has_usable("File::Temp")) { $fh = File::Temp->new( dir => File::Spec->tmpdir, template => "cpan_getsave_url_XXXX", suffix => ".html", unlink => 0, ); $filename = $fh->filename; } else { $fh = FileHandle->new; $filename = "cpan_getsave_url_$$.html"; } my $tmpin = $filename; if ($CPAN::META->has_usable('LWP')) { $CPAN::Frontend->myprint("Fetching with LWP: $url "); my $Ua; CPAN::LWP::UserAgent->config; eval { $Ua = CPAN::LWP::UserAgent->new; }; if ($@) { $CPAN::Frontend->mywarn("ERROR: CPAN::LWP::UserAgent->new dies with $@\n"); return; } else { my($var); $Ua->proxy('http', $var) if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy}; $Ua->no_proxy($var) if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy}; } my $req = HTTP::Request->new(GET => $url); $req->header('Accept' => 'text/html'); my $res = $Ua->request($req); if ($res->is_success) { $CPAN::Frontend->myprint(" + request successful.\n") if $CPAN::DEBUG; print $fh $res->content; close $fh; $CPAN::Frontend->myprint(qq{ + saved content to $tmpin \n}) if $CPAN::DEBUG; return $tmpin; } else { $CPAN::Frontend->myprint(sprintf( "LWP failed with code[%s], message[%s]\n", $res->code, $res->message, )); return; } } else { $CPAN::Frontend->mywarn(" LWP not available\n"); return; } } #-> sub CPAN::Distribution::_build_command sub _build_command { my($self) = @_; if ($^O eq "MSWin32") { # special code needed at least up to # Module::Build 0.2611 and 0.2706; a fix # in M:B has been promised 2006-01-30 my($perl) = $self->perl or $CPAN::Frontend->mydie("Couldn't find executable perl\n"); return "$perl ./Build"; } elsif ($^O eq 'VMS') { return "$^X Build.com"; } return "./Build"; } #-> sub CPAN::Distribution::_should_report sub _should_report { my($self, $phase) = @_; die "_should_report() requires a 'phase' argument" if ! defined $phase; return unless $CPAN::META->has_usable("CPAN::Reporter"); # configured my $test_report = CPAN::HandleConfig->prefs_lookup($self, q{test_report}); return unless $test_report; # don't repeat if we cached a result return $self->{should_report} if exists $self->{should_report}; # don't report if we generated a Makefile.PL if ( $self->{had_no_makefile_pl} ) { $CPAN::Frontend->mywarn( "Will not send CPAN Testers report with generated Makefile.PL.\n" ); return $self->{should_report} = 0; } # available if ( ! $CPAN::META->has_inst("CPAN::Reporter")) { $CPAN::Frontend->mywarnonce( "CPAN::Reporter not installed. No reports will be sent.\n" ); return $self->{should_report} = 0; } # capable my $crv = CPAN::Reporter->VERSION; if ( CPAN::Version->vlt( $crv, 0.99 ) ) { # don't cache $self->{should_report} -- need to check each phase if ( $phase eq 'test' ) { return 1; } else { $CPAN::Frontend->mywarn( "Reporting on the '$phase' phase requires CPAN::Reporter 0.99, but \n" . "you only have version $crv\. Only 'test' phase reports will be sent.\n" ); return; } } # appropriate if ($self->is_dot_dist) { $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ". "for local directories\n"); return $self->{should_report} = 0; } if ($self->prefs->{patches} && @{$self->prefs->{patches}} && $self->{patched} ) { $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ". "when the source has been patched\n"); return $self->{should_report} = 0; } # proceed and cache success return $self->{should_report} = 1; } #-> sub CPAN::Distribution::reports sub reports { my($self) = @_; my $pathname = $self->id; $CPAN::Frontend->myprint("Distribution: $pathname\n"); unless ($CPAN::META->has_inst("CPAN::DistnameInfo")) { $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue"); } unless ($CPAN::META->has_usable("LWP")) { $CPAN::Frontend->mydie("LWP not installed; cannot continue"); } unless ($CPAN::META->has_usable("File::Temp")) { $CPAN::Frontend->mydie("File::Temp not installed; cannot continue"); } my $format; if ($CPAN::META->has_inst("YAML::XS") || $CPAN::META->has_inst("YAML::Syck")){ $format = 'yaml'; } elsif (!$format && $CPAN::META->has_inst("JSON::PP") ) { $format = 'json'; } else { $CPAN::Frontend->mydie("JSON::PP not installed, cannot continue"); } my $d = CPAN::DistnameInfo->new($pathname); my $dist = $d->dist; # "CPAN-DistnameInfo" my $version = $d->version; # "0.02" my $maturity = $d->maturity; # "released" my $filename = $d->filename; # "CPAN-DistnameInfo-0.02.tar.gz" my $cpanid = $d->cpanid; # "GBARR" my $distvname = $d->distvname; # "CPAN-DistnameInfo-0.02" my $url = sprintf "http://www.cpantesters.org/show/%s.%s", $dist, $format; CPAN::LWP::UserAgent->config; my $Ua; eval { $Ua = CPAN::LWP::UserAgent->new; }; if ($@) { $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n"); } $CPAN::Frontend->myprint("Fetching '$url'..."); my $resp = $Ua->get($url); unless ($resp->is_success) { $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code); } $CPAN::Frontend->myprint("DONE\n\n"); my $unserialized; if ( $format eq 'yaml' ) { my $yaml = $resp->content; # what a long way round! my $fh = File::Temp->new( dir => File::Spec->tmpdir, template => 'cpan_reports_XXXX', suffix => '.yaml', unlink => 0, ); my $tfilename = $fh->filename; print $fh $yaml; close $fh or $CPAN::Frontend->mydie("Could not close '$tfilename': $!"); $unserialized = CPAN->_yaml_loadfile($tfilename)->[0]; unlink $tfilename or $CPAN::Frontend->mydie("Could not unlink '$tfilename': $!"); } else { require JSON::PP; $unserialized = JSON::PP->new->utf8->decode($resp->content); } my %other_versions; my $this_version_seen; for my $rep (@$unserialized) { my $rversion = $rep->{version}; if ($rversion eq $version) { unless ($this_version_seen++) { $CPAN::Frontend->myprint ("$rep->{version}:\n"); } my $arch = $rep->{archname} || $rep->{platform} || '????'; my $grade = $rep->{action} || $rep->{status} || '????'; my $ostext = $rep->{ostext} || ucfirst($rep->{osname}) || '????'; $CPAN::Frontend->myprint (sprintf("%1s%1s%-4s %s on %s %s (%s)\n", $arch eq $Config::Config{archname}?"*":"", $grade eq "PASS"?"+":$grade eq"FAIL"?"-":"", $grade, $rep->{perl}, $ostext, $rep->{osvers}, $arch, )); } else { $other_versions{$rep->{version}}++; } } unless ($this_version_seen) { $CPAN::Frontend->myprint("No reports found for version '$version' Reports for other versions:\n"); for my $v (sort keys %other_versions) { $CPAN::Frontend->myprint(" $v\: $other_versions{$v}\n"); } } $url = substr($url,0,-4) . 'html'; $CPAN::Frontend->myprint("See $url for details\n"); } 1; �������������������������������������perl5/CPAN/Debug.pm���������������������������������������������������������������������������������0000444�����������������00000004066�15253012307�0007702 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- package CPAN::Debug; use strict; use vars qw($VERSION); $VERSION = "5.5001"; # module is internal to CPAN.pm %CPAN::DEBUG = qw[ CPAN 1 Index 2 InfoObj 4 Author 8 Distribution 16 Bundle 32 Module 64 CacheMgr 128 Complete 256 FTP 512 Shell 1024 Eval 2048 HandleConfig 4096 Tarzip 8192 Version 16384 Queue 32768 FirstTime 65536 ]; $CPAN::DEBUG ||= 0; #-> sub CPAN::Debug::debug ; sub debug { my($self,$arg) = @_; my @caller; my $i = 0; while () { my(@c) = (caller($i))[0 .. ($i ? 3 : 2)]; last unless defined $c[0]; push @caller, \@c; for (0,3) { last if $_ > $#c; $c[$_] =~ s/.*:://; } for (1) { $c[$_] =~ s|.*/||; } last if ++$i>=3; } pop @caller; if ($CPAN::DEBUG{$caller[0][0]} & $CPAN::DEBUG) { if ($arg and ref $arg) { eval { require Data::Dumper }; if ($@) { $CPAN::Frontend->myprint("Debug(\n" . $arg->as_string . ")\n"); } else { $CPAN::Frontend->myprint("Debug(\n" . Data::Dumper::Dumper($arg) . ")\n"); } } else { my $outer = ""; local $" = ","; if (@caller>1) { $outer = ",[@{$caller[1]}]"; } $CPAN::Frontend->myprint("Debug(@{$caller[0]}$outer): $arg\n"); } } } 1; __END__ =head1 NAME CPAN::Debug - internal debugging for CPAN.pm =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/LWP/Protocol/https.pm�������������������������������������������������������������������������0000444�����������������00000012645�15253012307�0011542 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package LWP::Protocol::https; use strict; use warnings; our $VERSION = '6.14'; use parent 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 { if ( $Net::HTTPS::SSL_SOCKET_CLASS eq 'Net::SSL' ) { $ssl_opts{SSL_verifycn_scheme} = ''; } else { $ssl_opts{SSL_verifycn_scheme} = 'none'; } } if ($ssl_opts{SSL_verify_mode}) { unless (exists $ssl_opts{SSL_ca_file} || exists $ssl_opts{SSL_ca_path}) { if ($Net::HTTPS::SSL_SOCKET_CLASS eq 'IO::Socket::SSL' && defined &IO::Socket::SSL::default_ca && IO::Socket::SSL::default_ca() ) { # IO::Socket::SSL has a usable default CA } elsif ( my $cafile = eval { require Mozilla::CA; Mozilla::CA::SSL_ca_file() }) { # use Mozilla::CA $ssl_opts{SSL_ca_file} = $cafile; } else { die <<'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 to the file where your trusted CA are, or by installing the Mozilla::CA module for set of commonly trusted CAs. To completely disable the verification that you talk to the correct SSL peer you can set SSL_verify_mode to 0 within ssl_opts. But, if you do this you can't be sure that you communicate with the expected peer. EOT } } } $self->{ssl_opts} = \%ssl_opts; return (%ssl_opts, MultiHomed => 1, $self->SUPER::_extra_sock_opts); } # This is a subclass of LWP::Protocol::http. # That parent class calls ->_check_sock() during the # request method. This allows us to hook in and run checks # sub _check_sock # { # my($self, $req, $sock) = @_; # } 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) = @_; # SNI should be passed there only if it is not an IP address. # Details: https://github.com/libwww-perl/libwww-perl/issues/449#issuecomment-1896175509 my $host = $url->host() =~ m/:|^[\d.]+$/s ? undef : $url->host(); $sock = LWP::Protocol::https::Socket->start_SSL( $sock, SSL_verifycn_name => $url->host, SSL_hostname => $host, $self->_extra_sock_opts, ); $@ = LWP::Protocol::https::Socket->errstr if ! $sock; return $sock; } } #----------------------------------------------------------- package LWP::Protocol::https::Socket; use parent -norequire, 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<ssl_opts>, and neither C<SSL_ca_file> nor C<SSL_ca_path> is set, then C<SSL_ca_file> is implied to be the one provided by L<Mozilla::CA>. If the Mozilla::CA module isn't available SSL requests will fail. Either install this module, set up an alternative C<SSL_ca_file> 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<IO::Socket::SSL>, L<Crypt::SSLeay>, L<Mozilla::CA> =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/cPanelUserConfig.pm���������������������������������������������������������������������������0000644�����������������00000001061�15253012307�0011314 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 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/Canary/Stability.pm���������������������������������������������������������������������������0000444�����������������00000015452�15253012307�0011315 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=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<Makefile.PL> in L<Coro> or L<AnyEvent> 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 <<EOF; *** *** Canary::Stability COMPATIBILITY AND SUPPORT CHECK *** ================================================= *** *** Hi! *** *** I do my best to provide predictable and reliable software. *** *** However, in recent releases, P5P (who maintain perl) have been *** introducing regressions that are sometimes subtle and at other times *** catastrophic, often for personal preferences with little or no concern *** for existing code, most notably CPAN. *** *** For this reason, it has become very hard for me to maintain the level *** of reliability and support I have committed myself to in the past, at *** least with some perl versions: I simply can't keep up working around new *** bugs or gratituous incompatibilities, and in turn you might suffer from *** unanticipated problems. *** *** Therefore I have introduced a support and compatibility check, the results *** of which follow below, together with a FAQ and some recommendations. *** *** This check is just to let you know that there might be a risk, so you can *** make judgement calls on how to proceed - it will not keep the module from *** installing or working. *** EOF if ($minvers > $VERSION) { sgr 33; print <<EOF; *** The stability canary says: (nothing, it died of old age). *** *** Your Canary::Stability module (used by $distname) is too old. *** This is not a fatal problem - while you might want to upgrade to version *** $minvers (currently installed version: $VERSION) to get better support *** status testing, you might also not want to care at all, and all will *** be well as long $distname works well enough for you, as the stability *** canary is only used when installing the distribution. *** EOF } elsif ($] < $minperl) { sgr 33; print <<EOF; *** The stability canary says: chirp (it seems concerned about something). *** *** Your perl version ($]) is older than the $distname distribution *** likes ($minperl). This is not a fatal problem - the module might work *** well with your version of perl, but it does mean the author likely *** won't do anything to make it work if it breaks. *** EOF if ($ENV{AUTOMATED_TESTING}) { print <<EOF; *** Since this is an AUTOMATED_TESTING environment, the stability canary *** decided to fail cleanly here, rather than to generate a false test *** result. *** EOF exit 0; } } elsif (defined $Internals::StabilityBranchVersion) { # note to people studying this modules sources: # the above test is not considered a clean or stable way to # test for the stability branch. sgr 32; print <<EOF; *** The stability canary says: chirp! chirp! (it seems to be quite excited) *** *** It seems you are running schmorp's stability branch of perl. *** All should be well, and if it isn't, you should report this as a bug *** to the $distname author. *** EOF } elsif ($] < 5.021) { #sgr 32; print <<EOF; *** The stability canary says: chirp! chirp! (it seems to be quite happy) *** *** Your version of perl ($]) is quite supported by $distname, nothing *** else to be said, hope it comes in handy. *** EOF } else { sgr 31; print <<EOF; *** The stability canary says: (nothing, it was driven away by harsh weather) *** *** It seems you are running perl version $], likely the "official" or *** "standard" version. While there is nothing wrong with doing that, *** standard perl versions 5.022 and up are not supported by $distname. *** While this might be fatal, it might also be all right - if you run into *** problems, you might want to downgrade your perl or switch to the *** stability branch. *** *** If everything works fine, you can ignore this message. *** EOF sgr 0; print <<EOF; *** *** Stability canary mini-FAQ: *** *** Do I need to do anything? *** With luck, no. While some distributions are known to fail *** already, most should probably work. This message is here *** to alert you that your perl is not supported by $distname, *** and if things go wrong, you either need to downgrade, or *** sidegrade to the stability variant of your perl version, *** or simply live with the consequences. *** *** What is this canary thing? *** It's purpose is to check support status of $distname with *** respect to your perl version. *** *** What is this "stability branch"? *** It's a branch or fork of the official perl, by schmorp, to *** improve stability and compatibility with existing modules. *** *** How can I skip this prompt on automated installs? *** Set PERL_CANARY_STABILITY_NOPROMPT=1 in your environment. *** More info is in the Canary::Stability manpage. *** *** Long version of this FAQ: http://stableperl.schmorp.de/faq.html *** Stability Branch homepage: http://stableperl.schmorp.de/ *** EOF unless ($ENV{PERL_CANARY_STABILITY_NOPROMPT}) { require ExtUtils::MakeMaker; ExtUtils::MakeMaker::prompt ("Continue anyways? ", "y") =~ /^y/i or die "FATAL: User aborted configuration of $distname.\n"; } } sgr 0; } =head1 ENVIRONMENT VARIABLES =over 4 =item C<PERL_CANARY_STABILITY_NOPROMPT=1> Do not prompt the user on alert messages. =item C<PERL_CANARY_STABILITY_COLOUR=0> Disable use of colour. =item C<PERL_CANARY_STABILITY_COLOUR=1> Force use of colour. =item C<PERL_CANARY_STABILITY_DISABLE=1> Disable this modules functionality completely. =item C<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. 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 <schmorp@schmorp.de> http://software.schmorp.de/pkg/Canary-Stability.html =cut 1 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/Switch.pm�������������������������������������������������������������������������������������0000444�����������������00000070215�15253012307�0007373 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Switch; use 5.005; use strict; use vars qw($VERSION); use Carp; use if $] >= 5.011, 'deprecate'; $VERSION = '2.17'; # LOAD FILTERING MODULE... use Filter::Util::Call; sub __(); # CATCH ATTEMPTS TO CALL case OUTSIDE THE SCOPE OF ANY switch $::_S_W_I_T_C_H = sub { croak "case/when statement not in switch/given block" }; my $offset; my $fallthrough; my ($Perl5, $Perl6) = (0,0); sub import { $fallthrough = grep /\bfallthrough\b/, @_; $offset = (caller)[2]+1; filter_add({}) unless @_>1 && $_[1] eq 'noimport'; my $pkg = caller; no strict 'refs'; for ( qw( on_defined on_exists ) ) { *{"${pkg}::$_"} = \&$_; } *{"${pkg}::__"} = \&__ if grep /__/, @_; $Perl6 = 1 if grep(/Perl\s*6/i, @_); $Perl5 = 1 if grep(/Perl\s*5/i, @_) || !grep(/Perl\s*6/i, @_); 1; } sub unimport { filter_del() } sub filter { my($self) = @_ ; local $Switch::file = (caller)[1]; my $status = 1; $status = filter_read(1_000_000); return $status if $status<0; $_ = filter_blocks($_,$offset); $_ = "# line $offset\n" . $_ if $offset; undef $offset; return $status; } use Text::Balanced ':ALL'; sub line { my ($pretext,$offset) = @_; ($pretext=~tr/\n/\n/)+($offset||0); } sub is_block { local $SIG{__WARN__}=sub{die$@}; local $^W=1; my $ishash = defined eval 'my $hr='.$_[0]; undef $@; return !$ishash; } my $pod_or_DATA = qr/ ^=[A-Za-z] .*? ^=cut (?![A-Za-z]) .*? $ | ^__(DATA|END)__\n.* /smx; my $casecounter = 1; sub filter_blocks { my ($source, $line) = @_; return $source unless $Perl5 && $source =~ /case|switch/ || $Perl6 && $source =~ /when|given|default/; pos $source = 0; my $text = ""; component: while (pos $source < length $source) { if ($source =~ m/(\G\s*use\s+Switch\b)/gc) { $text .= q{use Switch 'noimport'}; next component; } my @pos = Text::Balanced::_match_quotelike(\$source,qr/\s*/,1,0); if (defined $pos[0]) { my $pre = substr($source,$pos[0],$pos[1]); # matched prefix my $iEol; if( substr($source,$pos[4],$pos[5]) eq '/' && # 1st delimiter substr($source,$pos[2],$pos[3]) eq '' && # no op like 'm' index( substr($source,$pos[16],$pos[17]), 'x' ) == -1 && # no //x ($iEol = index( $source, "\n", $pos[4] )) > 0 && $iEol < $pos[8] ){ # embedded newlines # If this is a pattern, it isn't compatible with Switch. Backup past 1st '/'. pos( $source ) = $pos[6]; $text .= $pre . substr($source,$pos[2],$pos[6]-$pos[2]); } else { $text .= $pre . substr($source,$pos[2],$pos[18]-$pos[2]); } next component; } if ($source =~ m/(\G\s*$pod_or_DATA)/gc) { $text .= $1; next component; } @pos = Text::Balanced::_match_variable(\$source,qr/\s*/); if (defined $pos[0]) { $text .= " " if $pos[0] < $pos[2]; $text .= substr($source,$pos[0],$pos[4]-$pos[0]); next component; } if ($Perl5 && $source =~ m/\G(\n*)(\s*)(switch)\b(?=\s*[(])/gc || $Perl6 && $source =~ m/\G(\n*)(\s*)(given)\b(?=\s*[(])/gc || $Perl6 && $source =~ m/\G(\n*)(\s*)(given)\b(.*)(?=\{)/gc) { my $keyword = $3; my $arg = $4; $text .= $1.$2.'S_W_I_T_C_H: while (1) '; unless ($arg) { @pos = Text::Balanced::_match_codeblock(\$source,qr/\s*/,qr/\(/,qr/\)/,qr/[[{(<]/,qr/[]})>]/,undef) or do { die "Bad $keyword statement (problem in the parentheses?) near $Switch::file line ", line(substr($source,0,pos $source),$line), "\n"; }; $arg = filter_blocks(substr($source,$pos[0],$pos[4]-$pos[0]),line(substr($source,0,$pos[0]),$line)); } $arg =~ s {^\s*[(]\s*%} { ( \\\%} || $arg =~ s {^\s*[(]\s*m\b} { ( qr} || $arg =~ s {^\s*[(]\s*/} { ( qr/} || $arg =~ s {^\s*[(]\s*qw} { ( \\qw}; @pos = Text::Balanced::_match_codeblock(\$source,qr/\s*/,qr/\{/,qr/\}/,qr/\{/,qr/\}/,undef) or do { die "Bad $keyword statement (problem in the code block?) near $Switch::file line ", line(substr($source,0, pos $source), $line), "\n"; }; my $code = filter_blocks(substr($source,$pos[0],$pos[4]-$pos[0]),line(substr($source,0,$pos[0]),$line)); $code =~ s/{/{ local \$::_S_W_I_T_C_H; Switch::switch($arg);/; $text .= $code . 'continue {last}'; next component; } elsif ($Perl5 && $source =~ m/\G(\s*)(case\b)(?!\s*=>)/gc || $Perl6 && $source =~ m/\G(\s*)(when\b)(?!\s*=>)/gc || $Perl6 && $source =~ m/\G(\s*)(default\b)(?=\s*\{)/gc) { my $keyword = $2; $text .= $1 . ($keyword eq "default" ? "if (1)" : "if (Switch::case"); if ($keyword eq "default") { # Nothing to do } elsif (@pos = Text::Balanced::_match_codeblock(\$source,qr/\s*/,qr/\{/,qr/\}/,qr/\{/,qr/\}/,undef)) { my $code = substr($source,$pos[0],$pos[4]-$pos[0]); $text .= " " if $pos[0] < $pos[2]; $text .= "sub " if is_block $code; $text .= filter_blocks($code,line(substr($source,0,$pos[0]),$line)) . ")"; } elsif (@pos = Text::Balanced::_match_codeblock(\$source,qr/\s*/,qr/[[(]/,qr/[])]/,qr/[[({]/,qr/[])}]/,undef)) { my $code = filter_blocks(substr($source,$pos[0],$pos[4]-$pos[0]),line(substr($source,0,$pos[0]),$line)); $code =~ s {^\s*[(]\s*%} { ( \\\%} || $code =~ s {^\s*[(]\s*m\b} { ( qr} || $code =~ s {^\s*[(]\s*/} { ( qr/} || $code =~ s {^\s*[(]\s*qw} { ( \\qw}; $text .= " " if $pos[0] < $pos[2]; $text .= "$code)"; } elsif ($Perl6 && do{@pos = Text::Balanced::_match_variable(\$source,qr/\s*/)}) { my $code = filter_blocks(substr($source,$pos[0],$pos[4]-$pos[0]),line(substr($source,0,$pos[0]),$line)); $code =~ s {^\s*%} { \%} || $code =~ s {^\s*@} { \@}; $text .= " " if $pos[0] < $pos[2]; $text .= "$code)"; } elsif ( @pos = Text::Balanced::_match_quotelike(\$source,qr/\s*/,1,0)) { my $code = substr($source,$pos[2],$pos[18]-$pos[2]); $code = filter_blocks($code,line(substr($source,0,$pos[2]),$line)); $code =~ s {^\s*m} { qr} || $code =~ s {^\s*/} { qr/} || $code =~ s {^\s*qw} { \\qw}; $text .= " " if $pos[0] < $pos[2]; $text .= "$code)"; } elsif ($Perl5 && $source =~ m/\G\s*(([^\$\@{])[^\$\@{]*)(?=\s*{)/gc || $Perl6 && $source =~ m/\G\s*([^;{]*)()/gc) { my $code = filter_blocks($1,line(substr($source,0,pos $source),$line)); $text .= ' \\' if $2 eq '%'; $text .= " $code)"; } else { die "Bad $keyword statement (invalid $keyword value?) near $Switch::file line ", line(substr($source,0,pos $source), $line), "\n"; } die "Missing opening brace or semi-colon after 'when' value near $Switch::file line ", line(substr($source,0,pos $source), $line), "\n" unless !$Perl6 || $source =~ m/\G(\s*)(?=;|\{)/gc; do{@pos = Text::Balanced::_match_codeblock(\$source,qr/\s*/,qr/\{/,qr/\}/,qr/\{/,qr/\}/,undef)} or do { if ($source =~ m/\G\s*(?=([};]|\Z))/gc) { $casecounter++; next component; } die "Bad $keyword statement (problem in the code block?) near $Switch::file line ", line(substr($source,0,pos $source),$line), "\n"; }; my $code = filter_blocks(substr($source,$pos[0],$pos[4]-$pos[0]),line(substr($source,0,$pos[0]),$line)); $code =~ s/}(?=\s*\Z)/;last S_W_I_T_C_H }/ unless $fallthrough; $text .= "{ while (1) $code continue { goto C_A_S_E_$casecounter } last S_W_I_T_C_H; C_A_S_E_$casecounter: }"; $casecounter++; next component; } $source =~ m/\G(\s*(-[sm]\s+|\w+|#.*\n|\W))/gc; $text .= $1; } $text; } sub in { my ($x,$y) = @_; my @numy; for my $nextx ( @$x ) { my $numx = ref($nextx) || defined $nextx && (~$nextx&$nextx) eq 0; for my $j ( 0..$#$y ) { my $nexty = $y->[$j]; push @numy, ref($nexty) || defined $nexty && (~$nexty&$nexty) eq 0 if @numy <= $j; return 1 if $numx && $numy[$j] && $nextx==$nexty || $nextx eq $nexty; } } return ""; } sub on_exists { my $ref = @_==1 && ref($_[0]) eq 'HASH' ? $_[0] : { @_ }; [ keys %$ref ] } sub on_defined { my $ref = @_==1 && ref($_[0]) eq 'HASH' ? $_[0] : { @_ }; [ grep { defined $ref->{$_} } keys %$ref ] } sub switch(;$) { my ($s_val) = @_ ? $_[0] : $_; my $s_ref = ref $s_val; if ($s_ref eq 'CODE') { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; return $s_val == $c_val if ref $c_val eq 'CODE'; return $s_val->(@$c_val) if ref $c_val eq 'ARRAY'; return $s_val->($c_val); }; } elsif ($s_ref eq "" && defined $s_val && (~$s_val&$s_val) eq 0) # NUMERIC SCALAR { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; my $c_ref = ref $c_val; return $s_val == $c_val if $c_ref eq "" && defined $c_val && (~$c_val&$c_val) eq 0; return $s_val eq $c_val if $c_ref eq ""; return in([$s_val],$c_val) if $c_ref eq 'ARRAY'; return $c_val->($s_val) if $c_ref eq 'CODE'; return $c_val->call($s_val) if $c_ref eq 'Switch'; return scalar $s_val=~/$c_val/ if $c_ref eq 'Regexp'; return scalar $c_val->{$s_val} if $c_ref eq 'HASH'; return; }; } elsif ($s_ref eq "") # STRING SCALAR { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; my $c_ref = ref $c_val; return $s_val eq $c_val if $c_ref eq ""; return in([$s_val],$c_val) if $c_ref eq 'ARRAY'; return $c_val->($s_val) if $c_ref eq 'CODE'; return $c_val->call($s_val) if $c_ref eq 'Switch'; return scalar $s_val=~/$c_val/ if $c_ref eq 'Regexp'; return scalar $c_val->{$s_val} if $c_ref eq 'HASH'; return; }; } elsif ($s_ref eq 'ARRAY') { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; my $c_ref = ref $c_val; return in($s_val,[$c_val]) if $c_ref eq ""; return in($s_val,$c_val) if $c_ref eq 'ARRAY'; return $c_val->(@$s_val) if $c_ref eq 'CODE'; return $c_val->call(@$s_val) if $c_ref eq 'Switch'; return scalar grep {$_=~/$c_val/} @$s_val if $c_ref eq 'Regexp'; return scalar grep {$c_val->{$_}} @$s_val if $c_ref eq 'HASH'; return; }; } elsif ($s_ref eq 'Regexp') { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; my $c_ref = ref $c_val; return $c_val=~/s_val/ if $c_ref eq ""; return scalar grep {$_=~/s_val/} @$c_val if $c_ref eq 'ARRAY'; return $c_val->($s_val) if $c_ref eq 'CODE'; return $c_val->call($s_val) if $c_ref eq 'Switch'; return $s_val eq $c_val if $c_ref eq 'Regexp'; return grep {$_=~/$s_val/ && $c_val->{$_}} keys %$c_val if $c_ref eq 'HASH'; return; }; } elsif ($s_ref eq 'HASH') { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; my $c_ref = ref $c_val; return $s_val->{$c_val} if $c_ref eq ""; return scalar grep {$s_val->{$_}} @$c_val if $c_ref eq 'ARRAY'; return $c_val->($s_val) if $c_ref eq 'CODE'; return $c_val->call($s_val) if $c_ref eq 'Switch'; return grep {$_=~/$c_val/ && $s_val->{"$_"}} keys %$s_val if $c_ref eq 'Regexp'; return $s_val==$c_val if $c_ref eq 'HASH'; return; }; } elsif ($s_ref eq 'Switch') { $::_S_W_I_T_C_H = sub { my $c_val = $_[0]; return $s_val == $c_val if ref $c_val eq 'Switch'; return $s_val->call(@$c_val) if ref $c_val eq 'ARRAY'; return $s_val->call($c_val); }; } else { croak "Cannot switch on $s_ref"; } return 1; } sub case($) { local $SIG{__WARN__} = \&carp; $::_S_W_I_T_C_H->(@_); } # IMPLEMENT __ my $placeholder = bless { arity=>1, impl=>sub{$_[1+$_[0]]} }; sub __() { $placeholder } sub __arg($) { my $index = $_[0]+1; bless { arity=>0, impl=>sub{$_[$index]} }; } sub hosub(&@) { # WRITE THIS } sub call { my ($self,@args) = @_; return $self->{impl}->(0,@args); } sub meta_bop(&) { my ($op) = @_; sub { my ($left, $right, $reversed) = @_; ($right,$left) = @_ if $reversed; my $rop = ref $right eq 'Switch' ? $right : bless { arity=>0, impl=>sub{$right} }; my $lop = ref $left eq 'Switch' ? $left : bless { arity=>0, impl=>sub{$left} }; my $arity = $lop->{arity} + $rop->{arity}; return bless { arity => $arity, impl => sub { my $start = shift; return $op->($lop->{impl}->($start,@_), $rop->{impl}->($start+$lop->{arity},@_)); } }; }; } sub meta_uop(&) { my ($op) = @_; sub { my ($left) = @_; my $lop = ref $left eq 'Switch' ? $left : bless { arity=>0, impl=>sub{$left} }; my $arity = $lop->{arity}; return bless { arity => $arity, impl => sub { $op->($lop->{impl}->(@_)) } }; }; } use overload "+" => meta_bop {$_[0] + $_[1]}, "-" => meta_bop {$_[0] - $_[1]}, "*" => meta_bop {$_[0] * $_[1]}, "/" => meta_bop {$_[0] / $_[1]}, "%" => meta_bop {$_[0] % $_[1]}, "**" => meta_bop {$_[0] ** $_[1]}, "<<" => meta_bop {$_[0] << $_[1]}, ">>" => meta_bop {$_[0] >> $_[1]}, "x" => meta_bop {$_[0] x $_[1]}, "." => meta_bop {$_[0] . $_[1]}, "<" => meta_bop {$_[0] < $_[1]}, "<=" => meta_bop {$_[0] <= $_[1]}, ">" => meta_bop {$_[0] > $_[1]}, ">=" => meta_bop {$_[0] >= $_[1]}, "==" => meta_bop {$_[0] == $_[1]}, "!=" => meta_bop {$_[0] != $_[1]}, "<=>" => meta_bop {$_[0] <=> $_[1]}, "lt" => meta_bop {$_[0] lt $_[1]}, "le" => meta_bop {$_[0] le $_[1]}, "gt" => meta_bop {$_[0] gt $_[1]}, "ge" => meta_bop {$_[0] ge $_[1]}, "eq" => meta_bop {$_[0] eq $_[1]}, "ne" => meta_bop {$_[0] ne $_[1]}, "cmp" => meta_bop {$_[0] cmp $_[1]}, "\&" => meta_bop {$_[0] & $_[1]}, "^" => meta_bop {$_[0] ^ $_[1]}, "|" => meta_bop {$_[0] | $_[1]}, "atan2" => meta_bop {atan2 $_[0], $_[1]}, "neg" => meta_uop {-$_[0]}, "!" => meta_uop {!$_[0]}, "~" => meta_uop {~$_[0]}, "cos" => meta_uop {cos $_[0]}, "sin" => meta_uop {sin $_[0]}, "exp" => meta_uop {exp $_[0]}, "abs" => meta_uop {abs $_[0]}, "log" => meta_uop {log $_[0]}, "sqrt" => meta_uop {sqrt $_[0]}, "bool" => sub { croak "Can't use && or || in expression containing __" }, # "&()" => sub { $_[0]->{impl} }, # "||" => meta_bop {$_[0] || $_[1]}, # "&&" => meta_bop {$_[0] && $_[1]}, # fallback => 1, ; 1; __END__ =head1 NAME Switch - A switch statement for Perl, do not use if you can use given/when =head1 SYNOPSIS use Switch; switch ($val) { case 1 { print "number 1" } case "a" { print "string a" } case [1..10,42] { print "number in list" } case (\@array) { print "number in list" } case /\w+/ { print "pattern" } case qr/\w+/ { print "pattern" } case (\%hash) { print "entry in hash" } case (\&sub) { print "arg to subroutine" } else { print "previous case not true" } } =head1 BACKGROUND [Skip ahead to L<"DESCRIPTION"> if you don't care about the whys and wherefores of this control structure] In seeking to devise a "Swiss Army" case mechanism suitable for Perl, it is useful to generalize this notion of distributed conditional testing as far as possible. Specifically, the concept of "matching" between the switch value and the various case values need not be restricted to numeric (or string or referential) equality, as it is in other languages. Indeed, as Table 1 illustrates, Perl offers at least eighteen different ways in which two values could generate a match. Table 1: Matching a switch value ($s) with a case value ($c) Switch Case Type of Match Implied Matching Code Value Value ====== ===== ===================== ============= number same numeric or referential match if $s == $c; or ref equality object method result of method call match if $s->$c(); ref name match if defined $s->$c(); or ref other other string equality match if $s eq $c; non-ref non-ref scalar scalar string regexp pattern match match if $s =~ /$c/; array scalar array entry existence match if 0<=$c && $c<@$s; ref array entry definition match if defined $s->[$c]; array entry truth match if $s->[$c]; array array array intersection match if intersects(@$s, @$c); ref ref (apply this table to all pairs of elements $s->[$i] and $c->[$j]) array regexp array grep match if grep /$c/, @$s; ref hash scalar hash entry existence match if exists $s->{$c}; ref hash entry definition match if defined $s->{$c}; hash entry truth match if $s->{$c}; hash regexp hash grep match if grep /$c/, keys %$s; ref sub scalar return value defn match if defined $s->($c); ref return value truth match if $s->($c); sub array return value defn match if defined $s->(@$c); ref ref return value truth match if $s->(@$c); In reality, Table 1 covers 31 alternatives, because only the equality and intersection tests are commutative; in all other cases, the roles of the C<$s> and C<$c> variables could be reversed to produce a different test. For example, instead of testing a single hash for the existence of a series of keys (C<match if exists $s-E<gt>{$c}>), one could test for the existence of a single key in a series of hashes (C<match if exists $c-E<gt>{$s}>). =head1 DESCRIPTION The Switch.pm module implements a generalized case mechanism that covers most (but not all) of the numerous possible combinations of switch and case values described above. The module augments the standard Perl syntax with two new control statements: C<switch> and C<case>. The C<switch> statement takes a single scalar argument of any type, specified in parentheses. C<switch> stores this value as the current switch value in a (localized) control variable. The value is followed by a block which may contain one or more Perl statements (including the C<case> statement described below). The block is unconditionally executed once the switch value has been cached. A C<case> statement takes a single scalar argument (in mandatory parentheses if it's a variable; otherwise the parens are optional) and selects the appropriate type of matching between that argument and the current switch value. The type of matching used is determined by the respective types of the switch value and the C<case> argument, as specified in Table 1. If the match is successful, the mandatory block associated with the C<case> statement is executed. In most other respects, the C<case> statement is semantically identical to an C<if> statement. For example, it can be followed by an C<else> clause, and can be used as a postfix statement qualifier. However, when a C<case> block has been executed control is automatically transferred to the statement after the immediately enclosing C<switch> block, rather than to the next statement within the block. In other words, the success of any C<case> statement prevents other cases in the same scope from executing. But see L<"Allowing fall-through"> below. Together these two new statements provide a fully generalized case mechanism: use Switch; # AND LATER... %special = ( woohoo => 1, d'oh => 1 ); while (<>) { chomp; switch ($_) { case (%special) { print "homer\n"; } # if $special{$_} case /[a-z]/i { print "alpha\n"; } # if $_ =~ /a-z/i case [1..9] { print "small num\n"; } # if $_ in [1..9] case { $_[0] >= 10 } { print "big num\n"; } # if $_ >= 10 print "must be punctuation\n" case /\W/; # if $_ ~= /\W/ } } Note that C<switch>es can be nested within C<case> (or any other) blocks, and a series of C<case> statements can try different types of matches -- hash membership, pattern match, array intersection, simple equality, etc. -- against the same switch value. The use of intersection tests against an array reference is particularly useful for aggregating integral cases: sub classify_digit { switch ($_[0]) { case 0 { return 'zero' } case [2,4,6,8] { return 'even' } case [1,3,5,7,9] { return 'odd' } case /[A-F]/i { return 'hex' } } } =head2 Allowing fall-through Fall-though (trying another case after one has already succeeded) is usually a Bad Idea in a switch statement. However, this is Perl, not a police state, so there I<is> a way to do it, if you must. If a C<case> block executes an untargeted C<next>, control is immediately transferred to the statement I<after> the C<case> statement (i.e. usually another case), rather than out of the surrounding C<switch> block. For example: switch ($val) { case 1 { handle_num_1(); next } # and try next case... case "1" { handle_str_1(); next } # and try next case... case [0..9] { handle_num_any(); } # and we're done case /\d/ { handle_dig_any(); next } # and try next case... case /.*/ { handle_str_any(); next } # and try next case... } If $val held the number C<1>, the above C<switch> block would call the first three C<handle_...> subroutines, jumping to the next case test each time it encountered a C<next>. After the third C<case> block was executed, control would jump to the end of the enclosing C<switch> block. On the other hand, if $val held C<10>, then only the last two C<handle_...> subroutines would be called. Note that this mechanism allows the notion of I<conditional fall-through>. For example: switch ($val) { case [0..9] { handle_num_any(); next if $val < 7; } case /\d/ { handle_dig_any(); } } If an untargeted C<last> statement is executed in a case block, this immediately transfers control out of the enclosing C<switch> block (in other words, there is an implicit C<last> at the end of each normal C<case> block). Thus the previous example could also have been written: switch ($val) { case [0..9] { handle_num_any(); last if $val >= 7; next; } case /\d/ { handle_dig_any(); } } =head2 Automating fall-through In situations where case fall-through should be the norm, rather than an exception, an endless succession of terminal C<next>s is tedious and ugly. Hence, it is possible to reverse the default behaviour by specifying the string "fallthrough" when importing the module. For example, the following code is equivalent to the first example in L<"Allowing fall-through">: use Switch 'fallthrough'; switch ($val) { case 1 { handle_num_1(); } case "1" { handle_str_1(); } case [0..9] { handle_num_any(); last } case /\d/ { handle_dig_any(); } case /.*/ { handle_str_any(); } } Note the explicit use of a C<last> to preserve the non-fall-through behaviour of the third case. =head2 Alternative syntax Perl 6 will provide a built-in switch statement with essentially the same semantics as those offered by Switch.pm, but with a different pair of keywords. In Perl 6 C<switch> will be spelled C<given>, and C<case> will be pronounced C<when>. In addition, the C<when> statement will not require switch or case values to be parenthesized. This future syntax is also (largely) available via the Switch.pm module, by importing it with the argument C<"Perl6">. For example: use Switch 'Perl6'; given ($val) { when 1 { handle_num_1(); } when ($str1) { handle_str_1(); } when [0..9] { handle_num_any(); last } when /\d/ { handle_dig_any(); } when /.*/ { handle_str_any(); } default { handle anything else; } } Note that scalars still need to be parenthesized, since they would be ambiguous in Perl 5. Note too that you can mix and match both syntaxes by importing the module with: use Switch 'Perl5', 'Perl6'; =head2 Higher-order Operations One situation in which C<switch> and C<case> do not provide a good substitute for a cascaded C<if>, is where a switch value needs to be tested against a series of conditions. For example: sub beverage { switch (shift) { case { $_[0] < 10 } { return 'milk' } case { $_[0] < 20 } { return 'coke' } case { $_[0] < 30 } { return 'beer' } case { $_[0] < 40 } { return 'wine' } case { $_[0] < 50 } { return 'malt' } case { $_[0] < 60 } { return 'Moet' } else { return 'milk' } } } (This is equivalent to writing C<case (sub { $_[0] < 10 })>, etc.; C<$_[0]> is the argument to the anonymous subroutine.) The need to specify each condition as a subroutine block is tiresome. To overcome this, when importing Switch.pm, a special "placeholder" subroutine named C<__> [sic] may also be imported. This subroutine converts (almost) any expression in which it appears to a reference to a higher-order function. That is, the expression: use Switch '__'; __ < 2 is equivalent to: sub { $_[0] < 2 } With C<__>, the previous ugly case statements can be rewritten: case __ < 10 { return 'milk' } case __ < 20 { return 'coke' } case __ < 30 { return 'beer' } case __ < 40 { return 'wine' } case __ < 50 { return 'malt' } case __ < 60 { return 'Moet' } else { return 'milk' } The C<__> subroutine makes extensive use of operator overloading to perform its magic. All operations involving __ are overloaded to produce an anonymous subroutine that implements a lazy version of the original operation. The only problem is that operator overloading does not allow the boolean operators C<&&> and C<||> to be overloaded. So a case statement like this: case 0 <= __ && __ < 10 { return 'digit' } doesn't act as expected, because when it is executed, it constructs two higher order subroutines and then treats the two resulting references as arguments to C<&&>: sub { 0 <= $_[0] } && sub { $_[0] < 10 } This boolean expression is inevitably true, since both references are non-false. Fortunately, the overloaded C<'bool'> operator catches this situation and flags it as an error. =head1 DEPENDENCIES The module is implemented using Filter::Util::Call and Text::Balanced and requires both these modules to be installed. =head1 AUTHOR Damian Conway (damian@conway.org). This module is now maintained by Alexandr Ciornii (alexchorny@gmail.com). Previously was maintained by Rafael Garcia-Suarez and perl5 porters. =head1 BUGS There are undoubtedly serious bugs lurking somewhere in code this funky :-) Bug reports and other feedback are most welcome. May create syntax errors in other parts of code. On perl 5.10.x may cause syntax error if "case" is present inside heredoc. In general, use given/when instead. It were introduced in perl 5.10.0. Perl 5.10.0 was released in 2007. =head1 LIMITATIONS Due to the heuristic nature of Switch.pm's source parsing, the presence of regexes with embedded newlines that are specified with raw C</.../> delimiters and don't have a modifier C<//x> are indistinguishable from code chunks beginning with the division operator C</>. As a workaround you must use C<m/.../> or C<m?...?> for such patterns. Also, the presence of regexes specified with raw C<?...?> delimiters may cause mysterious errors. The workaround is to use C<m?...?> instead. Due to the way source filters work in Perl, you can't use Switch inside an string C<eval>. May not work if sub prototypes are used (RT#33988). Regex captures in when are not available to code. If your source file is longer then 1 million characters and you have a switch statement that crosses the 1 million (or 2 million, etc.) character boundary you will get mysterious errors. The workaround is to use smaller source files. =head1 COPYRIGHT Copyright (c) 1997-2008, Damian Conway. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/POD2/DE/local/lib.pod�������������������������������������������������������������������������0000444�����������������00000040357�15253012307�0011140 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=encoding utf8 =head1 NAME local::lib~[de] - Erschaffen und benutzen von Perl Modulen in einem lokalen lib/ Verzeichnis mit PERL5LIB =head1 SYNOPSIS Im Code - use local::lib; # Benutzt das Verzeichnis ~/perl5 zum anlegen des lokalen lib/ Verzeichnisses use local::lib '~/foo'; # das selbe, aber mit ~/foo # Oder... use FindBin; use local::lib "$FindBin::Bin/../support"; # Applikationsspezifische Sammlung von Modulen Von der Shell - # Installiert LWP und alle notwendigen Abhängigkeiten in das '~/perl5' Verzeichnis perl -MCPAN -Mlocal::lib -e 'CPAN::install(LWP)' # Gibt die Shell Kommandos aus um die Umgebung vorzubereiten $ perl -Mlocal::lib export PERL_MB_OPT='--install_base /home/username/perl5' export PERL_MM_OPT='INSTALL_BASE=/home/username/perl5' export PERL5LIB='/home/username/perl5/lib/perl5/i386-linux:/home/username/perl5/lib/perl5' export PATH="/home/username/perl5/bin:$PATH" =head2 Die Bootstrapping Methode Ein typischer Weg um local::lib zu benutzen ist die sogenannte "Bootstrapping" Methode. Diese Methode wird benutzt wenn noch kein local::lib auf dem System installiert ist. In diesem Fall kannst du einfach local::lib direkt in deinem Home-Verzeichnis installieren. Selbst wenn du administrative Rechte hast, ist es wichtig das die Umgebungsvariablen von Schritt 4 in deinem Shell Startup Skript gesetzt werden. Ohne diesen Schritt werden die Module von CPAN weiterhin im System installiert und auch Perl Skripte die du startest würden das von local::lib erstellte lib/ Verzeichnis nicht nutzen. Standardmäßig installiert sich local::lib in ~/perl5. Windows Benutzern müssen ausserdem dies hier lesen: L</Unterschiede bei Benutzung dieses Module mit Win32>. 1. Lade das Tar-Archiv von CPAN runter (Suche nach "Download" auf der CPAN Seite von local::lib) und entpacke es in einem beliebigem Verzeichnis. Um das obige Problem zu vermeiden, sollte man dies als normaler User tun und nicht als root oder Administrator. 2. Starte in dem entstandenen Verzeichnis folgenden Befehl: perl Makefile.PL --bootstrap Wenn das System dir vorschlägt gewisse Dinge eigenständig zu konfigurieren ist es in fast allen Fällen vollkommen in Ordnung einfach "yes" zu antworten. Falls du local::lib nicht in das Standard Verzeichnis installieren willst, musst du dieses Verzeichnis als Parameter angeben: perl Makefile.PL --bootstrap=~/foo 3. Danach folgenden Befehl starten: (local::lib erwartet make auf dem System) make test && make install 4. Nun müssen wir die benötigten Umgebungsvariablen, damit Perl unser neu generiertes lib/ Verzeichnis benutzt. Wenn du bash oder eine andere Bourne Shell benutzt, kannst du es über diesen Weg zu deinem Shell Startup Skript hinzufügen: echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >>~/.bashrc Wenn du C Shell benutzt, du kannst das gleiche hiermit erreichen: /bin/csh echo $SHELL /bin/csh perl -I$HOME/perl5/lib/perl5 -Mlocal::lib >> ~/.cshrc Wenn du beim bootstrappen ein anderes Verzeichnis benutzt als das Standardverzeichnis, dann musst du dieses Verzeichnis als Parameter beim Laden des Modules local::lib angeben: echo 'eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)' >>~/.bashrc Nachdem diese Änderungen in deinem Shell Startup Skript gemacht wurden, ist es nun wichtig das diese Umgebungsvariablen auch gesetzt sind in deiner aktuellen Umgebung. In Bourne Shells macht man dies z.B. mit C<. ~/.bashrc>, und in C Shell würde man es mit: C<source ~/.cshrc> mit. Wenn du eine sehr langsames System hast, oder du unter drakonischen Regulierungen des Plattenplatz leben musst, kann man die automatische Generierung der manpages vom POD bei der Installation des Moduls deaktivieren beim bootstrapping mit dem C<--no-manpages> Parameter: perl Makefile.PL --bootstrap --no-manpages Um zu vermeiden das man mehrere bootstraps macht um z.B. für verschiedene Applikationen eigene local::lib Installationen zu nutzen, kann man eine dieser Umgebungen benutzen um einfach in beliebigen anderen Verzeichnis Module zu installieren und somit weitere eigenständige lib/ Umgebungen zu bekommen: cd ~/mydir1 perl -Mlocal::lib=./ eval $(perl -Mlocal::lib=./) ### Um die Umgebungsvariablen für die ### aktuelle Shell zusetzen printenv ### Hier kannst du sehen das ~/mydir1 ### in der PERL5LIB Umgebungsvariable ### steht perl -MCPAN -e install ... ### welche Module auch immer ... cd ../mydir2 ... WIEDERHOLEN ... Für mehrere Umgebungen in dieser Form brauch man eine Modifikation in der Benutzung von C<< use FindBin >> in dem "Im Code" Beispiel oben. Wenn du sowas machst, und du hast damit z.B. Perl Module nach C<< ~/mydir1/lib >> installiert und du hast ein Script in C<< ~/mydir1/scripts/myscript.pl >>, du musst dort angeben das die Module die es braucht im Verzeichnis C<< ~/mydir1/lib >> liegen. In C<< ~/mydir1/scripts/myscript.pl >> steht dann: use strict; use warnings; use local::lib "$FindBin::Bin/.."; ### zeigt auf ~/mydir1 und local::lib ### findet dort lib use lib "$FindBin::Bin/../lib"; ### zeigt auf ~/mydir1/lib Setze das vor jeden BEGIN { ... } Block der die Module braucht die du installiert hast. =head2 Unterschiede bei Benutzung dieses Module mit Win32 Um die nötigen Umgebungsvariablen für diese Variablen in der derzeitigen Sitzung mit C<CMD.EXE> zu setzen, kann man folgendes kommando nutzen: C:\>perl -Mlocal::lib set PERL_MB_OPT=--install_base C:\DOCUME~1\ADMINI~1\perl5 set PERL_MM_OPT=INSTALL_BASE=C:\DOCUME~1\ADMINI~1\perl5 set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5;C:\DOCUME~1\ADMINI~1\perl5\lib\perl5\MSWin32-x86-multi-thread set PATH=C:\DOCUME~1\ADMINI~1\perl5\bin;%PATH% ### Um die Umgebungsvariablen für diese Shell alleine zu setzen C:\>perl -Mlocal::lib > %TEMP%\tmp.bat && %TEMP%\tmp.bat && del %TEMP%\temp.bat ### anstelle von $(perl -Mlocal::lib=./) in bash. Wenn du willst das die Umgebungsvariablen dauerhaft gesetzt sind, musst du diese in Systemsteuerung / System dauerhaft selber eintragen oder L<App::local::lib::Win32Helper> benutzen. Die "~" wird übersetzt zu dem Benutzer Profil Verzeichnis (das Verzeichnis was beim User als "Dokumente und Einstellungen" bekannt ist unter Windows XP und vorher oder das "Benutzer" Verzeichnis bei Windows Vista und später), solange $ENV{HOME} nicht gesetzt ist. Das Verzeichnis wird hierbei zu dem korrekten Kurznamen umgewandelt, und muss daher definitiv existieren, und wird um die nötigen Unterverzeichnise erweitert. =head1 GRUNDPRINZIP Die Version von den Perl Paketen die man benötigt für spezifische Aufgaben sind sehr häufig nicht die richtigen oder korrekten Versionen auf dem System vorinstalliert. Ein Updaten von diesen Modulen ist in vielen Fällen einfach nicht möglich weil die nötigen Rechte fehlen. Ausserdem ist es generell nicht gut eigenständig die Versionen der Module auf dem System auszutauschen, weil natürlich der Rest des Systems genau die Version erwartet die von der Systemverwaltung auch installiert wurde. local::lib löst dieses Problem, es erlaubt dir dein komplett eigenes Verzeichnis für deine CPAN Module zu haben und bist so nicht genötigt die Module vom System zu nutzen oder andersrum andere User nicht mit individuellen Modulwünschen zu Überarbeitung ihres Codes zu zwingen, weil bestimmte Module zentral für alle auf neuere Version upgedatet werden. Die Installation findet hierbei dann z.B. im Home Verzeichnis statt. Es werden nur Umgebungsvariablen gesetzt die das installierte Perl dazu bewegen die im Homeverzeichnis installierten Module zu benutzen, zusätzlich und vorgezogen zu denen auf dem System. Daher muss man sich wenn man ein Paket System benutzt, wie z.b. Debian, garnicht mehr Sorgen machen, irgendwas auf dem System zu verletzten nur durch die Installation von Perl Modulen. =head1 BESCHREIBUNG Dieses Modul bietet eine schnelle und legitime Art und Weise ein sogenanntes bootstrapping zu machen um in einem User Homeverzeichnis eine Sammlung von Modulen zu installieren. Es erstellt auch die nötigen Umgebungsvariablen die benötigt werden um diese Module zu nutzen, passend zu der Shell die der User in der Umgebungsvariable C<SHELL> angegeben hat, um dann direkt passend in die entsprechenden Konfigurationsdateien der Shell einfügt zu werden. Weitergehend ist local::lib in der Lage Module zu nutzen die nicht im standardmäßigen C<@INC> Pfad von Perl enthalten sind. Das macht es einfacher für bestimmte Applikationen ein bestimmtes Set von Modulen zu installieren ohne die anderen Module auf dem System in irgendeiner Art anzufassen. Damit es z.B. auch sicherer Module zu installieren die vom Maintainer noch nicht als Release verfügbar sind. Beim Import setzt local::lib die folgenden Umgebungsvariablen zu den nötigen Werten: =over 4 =item PERL_MB_OPT =item PERL_MM_OPT =item PERL5LIB =item PATH Am PATH wird natürlich angehangen, und nicht ersetzt. =back Diese Werte sind dann verfügbar für jeden Code der danach importiert wurde. =head1 ERSTELLEN EINES EIGENSTÄNDIGE SAMMLUNG VON MODULEN Mit L<lib::core::only> besteht eine Möglichkeit dieses zutun, aber beachte das hier eine Menge von Fallstricken und Problemen existieren, und man sollte immer darauf achten das man auf einem Perl aufbaut was sowenig wie möglich verändert wurde (d.h. site und vendor Verzeichnis so leer wie möglich). =head1 METHODEN =head2 ensure_dir_structure_for =over 4 =item Parameter: $path =item Rückgabewert: Keiner =back Versucht den angegebenen Pfad anzulegen, mit allen nötigen drüberliegenden Verzeichnissen. Im Fehlerfall wird eine Exception geworfen. =head2 print_environment_vars_for =over 4 =item Parameter: $pfad =item Rückgabewert: Keiner =back Gibt die Umgebungsvariablen aus, die benötigt werden um den angegebenen Pfad als Basis Verzeichnis zu nutzen. =head2 build_environment_vars_for =over 4 =item Parameter: $pfad, $interpolate =item Rückgabewert: \%umgebungs_variablen =back Gibt ein Hash zurück mit den Variablen die nötig sind in den Umgebungsvariablen um eine Installation in dem gegebenen Pfad zu benutzen. =head2 setup_env_hash_for =over 4 =item Parameter: $pfad =item Rückgabewert: Keiner =back Setzt die C<%ENV> Einträge basierend auf dem Aufruf von L</build_environment_vars_for>. =head2 install_base_perl_path =over 4 =item Parameter: $pfad =item Rückgabewert: $module_installations_pfad =back Gibt den Pfad zurück der benutzt wird um Perl Module zu installieren bei dem gegebenen Pfad als Basis. Prinzipiell wird nur C<lib> und C<perl5> als Pfadelemente angehangen. =head2 install_base_arch_path =over 4 =item Parameter: $pfad =item Rückgabewert: $architektur_module_installations_pfad =back Gibt den Pfad zurück der benutzt wird um die Architektur-abhängigen Perl Module zu installieren basirend auf dem angegebenen Pfad als Basis. Basierend auf dem was L</install_base_perl_path> zurückgibt, and appends the value of C<$Config{archname}>.asis. =head2 install_base_bin_path =over 4 =item Parameter: $pfad =item Rückgabewert: $ausfuehrbare_programme_installations_pfad =back Gibt den Pfad zurück, wo ausführbare Programme installiert werden, basierend auf der Basis des angegebenen Pfad. Basierend auf L</install_base_perl_path> Rückgabewert, hängt diese Methode noch C<bin> an. =head2 resolve_empty_path =over 4 =item Parameter: $pfad =item Rückgabewert: $basis_pfad =back Erstellt und gibt zurück den Pfad der benutzt wird als Basis zur Installation der Module. Standardmäßig dies ist C<~/perl5>. =head2 resolve_home_path( $path ) =over 4 =item Parameter: $pfad =item Rückgabewert: $home =back Versucht das Home Verzeichnis vom aktullen User zu finden. Es wird eine Exception geworfen, wenn kein Home Verzeichnis ermittelt werden konnte. =head2 resolve_relative_path =over 4 =item Parameter: $pfad =item Rückgabewert: $absoluter_pfad =back Macht aus dem angegebenen Pfad einen absoluten Pfad. =head2 resolve_path =over 4 =item Parameter: $pfad =item Rückgabewert: $absoluter_pfad =back Hierbei wird der Pfad durch die folgende Methoden gegeben, wobei der Rückgabewert der ersten an die nächste weitergeben wird, um die Umgebung zu konfigurieren für die lokale Bibliotheks Installation: L</resolve_empty_path>, L</resolve_home_path>, L</resolve_relative_path>. Der daraus resultierende Pfad wird zu L</resolve_empty_path> übergeben, dessen Resultat dann weitergegeben wird an L</resolve_home_path>, wessen Resultat dann weitergegeben wird an L</resolve_relative_path>. Dieses Resultat wird dann final an L</resolve_path> übergeben, welches dann den Rückgabewert stellt. =head1 EINE WARNUNG VOR UNINST=1 Wenn man local::lib in Kombination mit "make install UNINST=1" benutzt, muss man vorsichtig sein über die Tatsache das der Prozess über die Neuinstallation eine nicht ausreichende Sicherheit hat bezüglich wo er nun installieren muss. Hierdurch mann es passieren das beim deinstallieren eines Modul u.U. das globale Modul deinstalliert wird (wenn die Rechte vorhanden sind) aber die neue Version nur in der lokalen Version installiert ist. Es ist hier also sehr wichtig das man "make install UNINST=1" und local::lib nur gleichzeitig benutzt wenn man sehr sicher darüber ist welche Konsequenzen einem entgegenkommen. =head1 EINSCHRÄNKUNGEN Die Werkzeuge von perl, die benutzt werden um die Pakete zu installieren (die sogenannte toolchain), sind leider nicht in der Lage sauber mit Verzeichnissen umzugehen die Leerzeichen enthalten und können daher local::lib nicht direkt in ein solches Verzeichnis installieren. Was du machen kannst ist B<nach> der Installation von local::lib und der Module die du in deiner local::lib haben willst, das gesamte Verzeichnis dahin zu bewegen. local::lib kann mit dem Verzeichnis mit Leerzeichen umgehen. Bitte aufpassen das natürlich eine weitere Installation oder ein Erneuern von Paketen mit dem CPAN Programm nicht mehr möglich ist. Die Shell Erkennung ist sehr primitiv. Derzeit ist es so das alles was "csh" im Namen hat auch als C Shell eingeordnet wird, und alles andere wird als Bourne Shell betrachet, ausser auf Win32 Systemen. Wenn die C<SHELL> Variable nicht gesetzt ist, eine Bourne Shell wird angenommen. Bootstrap ist leider ein Hack, und wird auf jedenfall CPAN.pm benutzen für ExtUtils::MakeMaker, auch wenn CPANPLUS installiert ist. Es setzt definitiv PERL5LIB, PERL_MM_OPT und PERL_MB_OPT neu und vernichtet jeden Wert der vorher gesetzt war. Es sollte vielleicht eine automatische Korrektur der CPAN Config machen, wenn das nicht schon gemacht wurde. "Patches Welcome" - Patches sind immer willkommen beim Autor oder den anderen Mitwirkenden. Auf Win32 Systemen werden die Umgebungsvariablen nicht direkt in die Registrierung geschrieben damit sie auch nach dem Neustarten erhalten bleiben. =head1 FEHLERANALYSE Wenn du local::lib konfiguriert hast CPAN Module in deinem Home Verzeichnis zu installieren, und du danach versuchst mit C<cpan -i Foo::Bar> ein Modul zu installieren, und dabei einen Fehler bekommst, wie: C<Warning: You do not have permissions to install into /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux at /usr/lib64/perl5/5.8.8/Foo/Bar.pm> und in der installationsausgabe steht irgendwo ein Fehler der sagt C<'INSTALL_BASE' is not a known MakeMaker parameter name>, dann hast du aus irgendeinem Grund dein neue Version von ExtUtils::MakeMaker verloren. Um dies zu korrigieren, einfach nochmal die bootstrapping Methode laufen lassen, wie oben beschrieben. Dann starte C<rm -r ~/.cpan/build/Foo-Bar*> Abschliessend dann nochmal mit C<cpan -i Foo::Bar> installieren und die Probleme sollten verschwunden sein. =head1 UMGEBUNGSVARIABLEN =over 4 =item SHELL =item COMSPEC local::lib schaut in die C<SHELL> Umgebungsvariable um die korrekten Kommandos zu der Shell Konfiguration hinzuzufügen. Auf Win32 Systemen, C<COMSPEC> wird auch analysiert. =back =head1 SUPPORT IRC: Wir sind im Channel #local-lib auf dem Server irc.perl.org. =head1 AUTOR DER ÜBERSETZUNG Torsten Raudssus <torsten@raudssus.de> http://www.raudssus.de/ =head1 URHEBERRECHT Copyright (c) 2007 - 2010 von den local::lib L<local::lib/"AUTHOR"> und L<local::lib/"CONTRIBUTORS"> aufgelistet in L<local::lib|local::lib>. =head1 LIZENZ Diese Sammlung ist freie Software und kann unter der selben Lizenz verbreitet werden wie Perl selber. =cut 1; ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/POD2/PT_BR/local/lib.pod����������������������������������������������������������������������0000444�����������������00000037241�15253012307�0011554 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������=encoding utf8 =head1 NAME local::lib~[pt_br] - crie e use um diretório lib/ local para módulos perl com PERL5LIB =head1 SINOPSE No código - use local::lib; # configura um lib local em ~/perl5 use local::lib '~/foo'; # idem, mas ~/foo # Ou... use FindBin; use local::lib "$FindBin::Bin/../suporte"; # bibliotecas de suporte locais à aplicação Pela linha de comando (shell) - # Instala o LWP e suas dependências não encontradas no diretório '~/perl5' perl -MCPAN -Mlocal::lib -e 'CPAN::install(LWP)' # Apenas exibe alguns comandos úteis para a shell $ perl -Mlocal::lib export PERL_MB_OPT='--install_base /home/username/perl5' export PERL_MM_OPT='INSTALL_BASE=/home/username/perl5' export PERL5LIB='/home/username/perl5/lib/perl5/i386-linux:/home/username/perl5/lib/perl5' export PATH="/home/username/perl5/bin:$PATH" =head2 A técnica de 'bootstrapping' Uma forma comum de instalar o local::lib é usando o que é conhecido como técnica de "bootstrapping". É uma boa abordagem caso seu administrador de sistemas não tenha instalado o local::lib. Nesse caso, você precisará instalar o local::lib em seu diretório de usuário. Caso você tenha privilégios de administrador, ainda assim deverá configurar suas variáveis de ambiente, como discutido no passo 4, abaixo. Sem elas, você ainda instalará módulos no CPAN do sistema e seus scripts Perl não utilizarão o caminho para o lib/ que você definiu com o local::lib. Por padrão, o local::lib instala os módulos do CPAN e a si próprio em ~/perl5. Usuários do Windows devem ler L</Diferenças ao usar esse módulo em Win32>. 1. Baixe e descompacte o local::lib do CPAN (procure por "Download" na página do CPAN sobre o local::lib). Faça isso como um usuário comum, não como root ou administrador. Descompacte o arquivo em seu diretório de usuário ou em qualquer outro local conveniente. 2. Execute isso: perl Makefile.PL --bootstrap Caso o sistema pergunte se deve configurar tudo que puder automaticamente, você provavelmente deve responder que sim (yes). Para instalar o local::lib em um diretório que não o padrão, você precisará especificá-lo ao chamar o bootstrap, da seguinte forma: perl Makefile.PL --bootstrap=~/foo 3. Execute isso: (local::lib assume que você possui o comando 'make' instalado em seu sistema) make test && make install 4. Agora precisamos configurar as variáveis de ambiente apropriadas para que o Perl use nosso recém-criado diretório lib/. Caso esteja usando bash ou outra shell Bourne, você pode fazer isso adicionando a seguinte linha em seu script de inicialização da shell: echo 'eval $(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)' >>~/.bashrc Caso esteja usando a shell C, pode fazer da seguinte forma: /bin/csh echo $SHELL /bin/csh perl -I$HOME/perl5/lib/perl5 -Mlocal::lib >> ~/.cshrc Caso tenha passado para o bootstrap um diretório que não o padrão, você precisará indicá-lo na chamada ao local::lib, dessa forma: echo 'eval $(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)' >>~/.bashrc Após atualizar seu arquivo de configuração da shell, certifique-se de processá-lo novamente para obter as modificações em sua shell atual. Shells Bourne usam C<. ~/.bashrc> para isso, enquanto shells C usam C<source ~/.cshrc>. Se estiver em uma máquina lenta ou operando com grandes limitações de espaço em disco, você pode desativar a geração automática de manpages a partir do POD ao instalar módulos. Para isso, basta passar o argumento C<--no-manpages> durante o bootstrap: perl Makefile.PL --bootstrap --no-manpages Para evitar ter que fazer vários bootstraps para vários ambientes de módulos Perl na mesma conta de usuário - por exemplo se você usa o local::lib para desenvolver diferentes aplicativos independentes - você pode utilizar uma única instalação bootstrap do local::lib para instalar módulos em diretórios diferentes da seguinte forma: cd ~/meudir1 perl -Mlocal::lib=./ eval $(perl -Mlocal::lib=./) ### Para configurar o ambiente apenas nessa shell printenv ### Veja que o ~/meudir1 está na PERL5LIB perl -MCPAN -e install ... ### Os módulos que quiser cd ../meudir2 ... REPITA ... Para múltiplos ambientes destinados a múltiplos aplicativos, você pode precisar incluir uma versão modificada das instruções de C<< use FindBin >> no exemplo "No código" acima. Caso tenha feito algo como o que foi descrito acima, terá um conjunto de módulos Perl em C<< ~/meudir1/lib >>. Caso tenha um script em C<< ~/meudir1/scripts/meuscript.pl >>, você precisará indicar a ele onde encontrar os módulos que instalou para ele em C<< ~/meudir1/lib >>. Em C<< ~/meudir1/scripts/meuscript.pl >>: use strict; use warnings; use local::lib "$FindBin::Bin/.."; ### aponta para ~/meudir1 e o local::lib acha o lib/ use lib "$FindBin::Bin/../lib"; ### aponta para ~/meudir1/lib Coloque isso antes de qualquer bloco BEGIN { ... } que precise dos módulos instalados. =head2 Diferenças ao usar esse módulo em Win32 Para configurar as variáveis de ambiente apropriadas para sua sessão atual do C<CMD.exe>, você pode fazer assim: C:\>perl -Mlocal::lib set PERL_MB_OPT=--install_base C:\DOCUME~1\ADMINI~1\perl5 set PERL_MM_OPT=INSTALL_BASE=C:\DOCUME~1\ADMINI~1\perl5 set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5;C:\DOCUME~1\ADMINI~1\perl5\lib\perl5\MSWin32-x86-multi-thread set PATH=C:\DOCUME~1\ADMINI~1\perl5\bin;%PATH% ### Para configurar o ambiente apenas dessa shell C:\>perl -Mlocal::lib > %TEMP%\tmp.bat && %TEMP%\tmp.bat && del %TEMP%\temp.bat ### em vez de $(perl -Mlocal::lib=./) Caso queira que as configurações do ambiente persistam, você precisará adicioná-las em Painel de Controle -> Sistema, ou usar o L<App::local::lib::Win32Helper>. O "~" é transformado no diretório do perfil do usuário (o diretório com o nome do usuário dentro de "Documents and Settings" (Windows XP ou anterior) ou "Usuários" (Windows Vista e mais recentes)) a menos que $ENV{HOME} exista. Após isso, o nome do diretório é encurtado e os subdiretórios são criados (o que significa que o diretório deve existir). =head1 MOTIVAÇÃO A versão de um pacote Perl na sua máquina nem sempre é a que você precisa. Obviamente, a melhor coisa a fazer seria atualizá-la para a versão desejada. No entanto, você pode estar em uma situação que o impede de fazer isso. Talvez você não tenha privilégios de administrador do sistema; ou talvez esteja usando um sistema de gerenciamento de pacotes como o do Debian, e ainda não exista um pacote disponível na versão desejada. local::lib resolve esse problema possibilitando a criação de seu próprio diretório de pacotes Perl obtidos do CPAN (em sistemas multi-usuário, isso normalmente fica dentro do diretório de seu usuário). A instalação do Perl no sistema permanece inalterada; você simplesmente chama o Perl com opções especiais para que ele use os pacotes em seu diretório local em vez dos pacotes do sistema. O local::lib organiza as coisas para que versões dos pacotes Perl instalados localmente tenham precedência sobre as do sistema. Caso esteja usando um sistema de gerenciamento de pacote (como em sistemas Debian), não precisará se preocupar com conflitos entre o Debian e o CPAN. Sua versão local dos pacotes será instalada em um diretório completamente diferente das versões instaladas pelo gerenciador de pacotes do sistema. =head1 DESCRIÇÃO Este módulo oferece uma forma rápida e conveniente para criar um repositório de módulos locais ao usuário, dentro do diretório do mesmo. Ele também monta e exibe para o usuário uma lista de variáveis de ambiente utilizando a sintaxe da shell atual do usuário (conforme especificado pela variável de ambiente C<SHELL>), pronta para ser adicionada diretamente no arquivo de configuração da shell. Generalizando, o local::lib permite a criação e uso de um diretório contendo módulos Perl fora do C<@INC> do Perl. Isso facilita a produção de aplicações com uma versão específica de determinado módulo, ou coleção de módulos. Também é útil quando o mantenedor de um módulo não aplicou determinado patch que você precisa para seu aplicativo. Durante o C<import>, o local::lib define valores apropriados para as seguintes variáveis de ambiente: =over 4 =item PERL_MB_OPT =item PERL_MM_OPT =item PERL5LIB =item PATH valores serão anexados ao PATH, em vez de substituí-lo. =back Esses valores são então disponibilizados para referência por qualquer outro código após o C<import>. =head1 CRIANDO UM CONJUNTO AUTO-CONTIDO DE MÓDULOS Veja L<lib::core::only|lib::core::only> para uma maneira de fazer isso - mas note que há uma série de ressalvas na abordagem, e a melhor forma é sempre fazer o 'build' contra uma versão limpa do perl (i.e. com 'site' e 'vendor' o mais vazios possível). =head1 MÉTODOS =head2 ensure_dir_structure_for =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: Nenhum =back Tenta criar o caminho fornecido, e todos os diretórios superiores necessários. Gera uma exceção em caso de falha. =head2 print_environment_vars_for =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: Nenhum =back Exibe na saída padrão as variáveis listadas acima, devidamente ajustadas para utilizar o caminho fornecido como diretório base. =head2 build_environment_vars_for =over 4 =item Argumentos: $caminho_do_diretorio, $interpolar =item Valor de Retorno: %variaveis_de_ambiente =back Retorna hash contendo as variáveis de ambiente listadas acima, devidamente ajustadas para utilizar o caminho fornecido como diretório base. =head2 setup_env_hash_for =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: Nenhum =back Constrói as chaves no C<%ENV> para o caminho fornecido, chamando C<build_environment_vars_for>. =head2 install_base_perl_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_base_de_instalacao =back Retorna um caminho de diretório indicando onde instalar os módulos Perl para essa instalação local de bibliotecas. Adiciona os diretórios C<lib> e C<perl5> ao final do caminho fornecido. =head2 install_base_arch_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_base_de_instalacao_arch =back Retorna um caminho de diretório indicando onde instalar os módulos Perl de arquiteturas específicas para essa instalação local de bibliotecas. Baseia-se no valor de retorno do método L</install_base_perl_path>, adicionando o valor de C<$Config{archname}>. =head2 install_base_bin_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_base_de_instalacao_bin =back Retorna um caminho de diretório indicando onde instalar programas executáveis para essa instalação local de bibliotecas. Baseia-se no valor de retorno do método L</install_base_perl_path>, adicionando o diretório C<bin>. =head2 resolve_empty_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_base_de_instalacao =back Cria e retorna o caminho de diretório raiz em que a instalação local de módulos deve ser feita. O padrão é C<~/perl5>. =head2 resolve_home_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_para_home =back Procura pelo diretório padrão (home) do usuário. Gera uma exceção caso não encontre resultado definitivo. =head2 resolve_relative_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_absoluto =back Transforma o caminho fornecido em um caminho absoluto. =head2 resolve_path =over 4 =item Argumentos: $caminho_do_diretorio =item Valor de Retorno: $caminho_absoluto =back Invoca os seguintes métodos em sequência, passando o resultado do método anterior para o seguinte, na tentativa de descobrir onde configurar o ambiente para a instalação local de bibliotecas: L</resolve_empty_path>, L</resolve_home_path>, L</resolve_relative_path>. Passa o caminho de diretório fornecido para L</resolve_empty_path> que retorna um resultado que é passado para L</resolve_home_path>, que então tem seu resultado passado para L</resolve_relative_path>. O resultado dessa chamada final é então retornado pelo L</resolve_path>. =head1 UM AVISO SOBRE UNINST=1 Tenha cuidado ao usar o local::lib em conjunto com "make install UNINST=1". A idéia dessa opção é desinstalar a versão anterior de um módulo antes de instalar a mais recente. No entanto ela não possui uma verificação de segurança de que a versão antiga e a nova referem-se ao mesmo diretório. Usada em combinação com o local::lib, você pode potencialmente apagar uma versão globalmente acessível de um módulo e instalar a versão mais nova no diretório local. Apenas utilize "make install UNINST=1" junto com o local::lib se você entende essas possíveis consequências. =head1 LIMITAÇÕES As ferramentas auxiliares do perl não conseguem lidar com nomes de diretórios contendo espaços, então não é possível fazer seu bootstrap do local::lib em um diretório com espaços. O que você pode fazer é mover seu local::lib para um diretório com espaços B<após> ter instalado todos os módulos dentro dele. Mas esteja ciente que você não poderá atualizar ou instalar outros módulos do CPAN nesse diretório local após a mudança. A detecção da shell é relativamente básica. Neste momento, qualquer coisa com csh no nome será tratada como a C shell ou compatível, e todo o resto será tratado como Bourne, exceto em sistemas Win32. Caso a variável de ambiente C<SHELL> não esteja disponível, assumiremos tratar-se de uma shell compatível com a Bourne. A técnica de bootstrap é um hack e usará o CPAN.pm para o ExtUtils::MakeMaker mesmo que você tenha o CPANPLUS instalado. Destrói qualquer valor pré-existente nas variáveis de ambiente PERL5LIB, PERL_MM_OPT e PERL_MB_OPT. Provavelmente deveria auto-configurar o CPAN caso isso ainda não tenha sido feito. Correções (patches) são muito bem-vindos para quaisquer dos itens acima. Em sistemas Win32, não há uma forma de escrever no registro as variáveis de ambiente criadas, para que elas persistam a uma reinicialização. =head1 SOLUÇÃO DE PROBLEMAS Se você configurou o local::lib para instalar módulos do CPAN em algum lugar do seu 'home', e mais tarde tentou instalar um módulo fazendo C<cpan -i Foo::Bar>, mas ele falhou com um erro como: C<Warning: You do not have permissions to install into /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux at /usr/lib64/perl5/5.8.8/Foo/Bar.pm> e em algum lugar no seu log de instalação houver um erro dizendo C<'INSTALL_BASE' is not a known MakeMaker parameter name>, então você de alguma forma perdeu seu ExtUtils::MakeMaker atualizado. Para remediar a situação, execute novamente o procedimento de bootstrap descrito acima. Então, execute C<rm -r ~/.cpan/build/Foo-Bar*> Finalmente, execute novamente o C<cpan -i Foo::Bar> e ele deve instalar sem problemas. =head1 AMBIENTE =over 4 =item SHELL =item COMSPEC O local::lib procura pela variável de ambiente C<SHELL> do usuário ao processar e exibir os comandos a serem adicionados no arquivo de configuração da shell. Em sistemas Win32, C<COMSPEC> também será examinado. =back =head1 SUPORTE IRC: Acesse #local-lib em irc.perl.org. =head1 AUTOR DA TRADUÇÃO Breno G. de Oliveira, C<< <garu at cpan.org> >>, após ter perdido uma aposta para o L<Getty|http://search.cpan.org/~getty/> durante a Copa de 2010. =head1 COPYRIGHT Copyright (c) 2007 - 2010 L<local::lib/"AUTHOR"> e L<local::lib/"CONTRIBUTORS"> do local::lib como listados em L<local::lib>. =head1 LICENÇA Esta biblioteca é software livre e pode ser distribuída sob os mesmo termos do perl. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/Try/Tiny.pm�����������������������������������������������������������������������������������0000444�����������������00000051227�15253012307�0007635 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Try::Tiny; # git description: v0.30-11-g1b81d0a use 5.006; # ABSTRACT: Minimal try/catch with proper preservation of $@ our $VERSION = '0.31'; use strict; use warnings; use Exporter 5.57 'import'; our @EXPORT = our @EXPORT_OK = qw(try catch finally); use Carp; $Carp::Internal{+__PACKAGE__}++; BEGIN { my $su = $INC{'Sub/Util.pm'} && defined &Sub::Util::set_subname; my $sn = $INC{'Sub/Name.pm'} && eval { Sub::Name->VERSION(0.08) }; unless ($su || $sn) { $su = eval { require Sub::Util; } && defined &Sub::Util::set_subname; unless ($su) { $sn = eval { require Sub::Name; Sub::Name->VERSION(0.08) }; } } *_subname = $su ? \&Sub::Util::set_subname : $sn ? \&Sub::Name::subname : sub { $_[1] }; *_HAS_SUBNAME = ($su || $sn) ? sub(){1} : sub(){0}; } my %_finally_guards; # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list # context & not a scalar one sub try (&;@) { my ( $try, @code_refs ) = @_; # we need to save this here, the eval block will be in scalar context due # to $failed my $wantarray = wantarray; # work around perl bug by explicitly initializing these, due to the likelyhood # this will be used in global destruction (perl rt#119311) my ( $catch, @finally ) = (); # find labeled blocks in the argument list. # catch and finally tag the blocks by blessing a scalar reference to them. foreach my $code_ref (@code_refs) { if ( ref($code_ref) eq 'Try::Tiny::Catch' ) { croak 'A try() may not be followed by multiple catch() blocks' if $catch; $catch = ${$code_ref}; } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) { push @finally, ${$code_ref}; } else { croak( 'try() encountered an unexpected argument (' . ( defined $code_ref ? $code_ref : 'undef' ) . ') - perhaps a missing semi-colon before or' ); } } # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's # not perfect, but we could provide a list of additional errors for # $catch->(); # name the blocks if we have Sub::Name installed _subname(caller().'::try {...} ' => $try) if _HAS_SUBNAME; # set up scope guards to invoke the finally blocks at the end. # this should really be a function scope lexical variable instead of # file scope + local but that causes issues with perls < 5.20 due to # perl rt#119311 local $_finally_guards{guards} = [ map Try::Tiny::ScopeGuard->_new($_), @finally ]; # save the value of $@ so we can set $@ back to it in the beginning of the eval # and restore $@ after the eval finishes my $prev_error = $@; my ( @ret, $error ); # failed will be true if the eval dies, because 1 will not be returned # from the eval body my $failed = not eval { $@ = $prev_error; # evaluate the try block in the correct context if ( $wantarray ) { @ret = $try->(); } elsif ( defined $wantarray ) { $ret[0] = $try->(); } else { $try->(); }; return 1; # properly set $failed to false }; # preserve the current error and reset the original value of $@ $error = $@; $@ = $prev_error; # at this point $failed contains a true value if the eval died, even if some # destructor overwrote $@ as the eval was unwinding. if ( $failed ) { # pass $error to the finally blocks push @$_, $error for @{$_finally_guards{guards}}; # if we got an error, invoke the catch block. if ( $catch ) { # This works like given($error), but is backwards compatible and # sets $_ in the dynamic scope for the body of C<$catch> for ($error) { return $catch->($error); } # in case when() was used without an explicit return, the C<for> # loop will be aborted and there's no useful return value } return; } else { # no failure, $@ is back to what it was, everything is fine return $wantarray ? @ret : $ret[0]; } } sub catch (&;@) { my ( $block, @rest ) = @_; croak 'Useless bare catch()' unless wantarray; _subname(caller().'::catch {...} ' => $block) if _HAS_SUBNAME; return ( bless(\$block, 'Try::Tiny::Catch'), @rest, ); } sub finally (&;@) { my ( $block, @rest ) = @_; croak 'Useless bare finally()' unless wantarray; _subname(caller().'::finally {...} ' => $block) if _HAS_SUBNAME; return ( bless(\$block, 'Try::Tiny::Finally'), @rest, ); } { package # hide from PAUSE Try::Tiny::ScopeGuard; use constant UNSTABLE_DOLLARAT => ("$]" < '5.013002') ? 1 : 0; sub _new { shift; bless [ @_ ]; } sub DESTROY { my ($code, @args) = @{ $_[0] }; local $@ if UNSTABLE_DOLLARAT; eval { $code->(@args); 1; } or do { warn "Execution of finally() block $code resulted in an exception, which " . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. ' . 'Your program will continue as if this event never took place. ' . "Original exception text follows:\n\n" . (defined $@ ? $@ : '$@ left undefined...') . "\n" ; } } } __PACKAGE__ __END__ =pod =encoding UTF-8 =head1 NAME Try::Tiny - Minimal try/catch with proper preservation of $@ =head1 VERSION version 0.31 =head1 SYNOPSIS You can use Try::Tiny's C<try> and C<catch> to expect and handle exceptional conditions, avoiding quirks in Perl and common mistakes: # handle errors with a catch handler try { die "foo"; } catch { warn "caught error: $_"; # not $@ }; You can also use it like a standalone C<eval> to catch and ignore any error conditions. Obviously, this is an extreme measure not to be undertaken lightly: # just silence errors try { die "foo"; }; =head1 DESCRIPTION This module provides bare bones C<try>/C<catch>/C<finally> statements that are designed to minimize common mistakes with eval blocks, and NOTHING else. This is unlike L<TryCatch> which provides a nice syntax and avoids adding another call stack layer, and supports calling C<return> from the C<try> block to return from the parent subroutine. These extra features come at a cost of a few dependencies, namely L<Devel::Declare> and L<Scope::Upper> which are occasionally problematic, and the additional catch filtering uses L<Moose> type constraints which may not be desirable either. The main focus of this module is to provide simple and reliable error handling for those having a hard time installing L<TryCatch>, but who still want to write correct C<eval> blocks without 5 lines of boilerplate each time. It's designed to work as correctly as possible in light of the various pathological edge cases (see L</BACKGROUND>) and to be compatible with any style of error values (simple strings, references, objects, overloaded objects, etc). If the C<try> block dies, it returns the value of the last statement executed in the C<catch> block, if there is one. Otherwise, it returns C<undef> in scalar context or the empty list in list context. The following examples all assign C<"bar"> to C<$x>: my $x = try { die "foo" } catch { "bar" }; my $x = try { die "foo" } || "bar"; my $x = (try { die "foo" }) // "bar"; my $x = eval { die "foo" } || "bar"; You can add C<finally> blocks, yielding the following: my $x; try { die 'foo' } finally { $x = 'bar' }; try { die 'foo' } catch { warn "Got a die: $_" } finally { $x = 'bar' }; C<finally> blocks are always executed making them suitable for cleanup code which cannot be handled using local. You can add as many C<finally> blocks to a given C<try> block as you like. Note that adding a C<finally> block without a preceding C<catch> block suppresses any errors. This behaviour is consistent with using a standalone C<eval>, but it is not consistent with C<try>/C<finally> patterns found in other programming languages, such as Java, Python, Javascript or C#. If you learned the C<try>/C<finally> pattern from one of these languages, watch out for this. =head1 EXPORTS All functions are exported by default using L<Exporter>. If you need to rename the C<try>, C<catch> or C<finally> keyword consider using L<Sub::Import> to get L<Sub::Exporter>'s flexibility. =over 4 =item try (&;@) Takes one mandatory C<try> subroutine, an optional C<catch> subroutine and C<finally> subroutine. The mandatory subroutine is evaluated in the context of an C<eval> block. If no error occurred the value from the first block is returned, preserving list/scalar context. If there was an error and the second subroutine was given it will be invoked with the error in C<$_> (localized) and as that block's first and only argument. C<$@> does B<not> contain the error. Inside the C<catch> block it has the same value it had before the C<try> block was executed. Note that the error may be false, but if that happens the C<catch> block will still be invoked. Once all execution is finished then the C<finally> block, if given, will execute. =item catch (&;@) Intended to be used in the second argument position of C<try>. Returns a reference to the subroutine it was given but blessed as C<Try::Tiny::Catch> which allows try to decode correctly what to do with this code reference. catch { ... } Inside the C<catch> block the caught error is stored in C<$_>, while previous value of C<$@> is still available for use. This value may or may not be meaningful depending on what happened before the C<try>, but it might be a good idea to preserve it in an error stack. For code that captures C<$@> when throwing new errors (i.e. L<Class::Throwable>), you'll need to do: local $@ = $_; =item finally (&;@) try { ... } catch { ... } finally { ... }; Or try { ... } finally { ... }; Or even try { ... } finally { ... } catch { ... }; Intended to be the second or third element of C<try>. C<finally> blocks are always executed in the event of a successful C<try> or if C<catch> is run. This allows you to locate cleanup code which cannot be done via C<local()> e.g. closing a file handle. When invoked, the C<finally> block is passed the error that was caught. If no error was caught, it is passed nothing. (Note that the C<finally> block does not localize C<$_> with the error, since unlike in a C<catch> block, there is no way to know if C<$_ == undef> implies that there were no errors.) In other words, the following code does just what you would expect: try { die_sometimes(); } catch { # ...code run in case of error } finally { if (@_) { print "The try block died with: @_\n"; } else { print "The try block ran without error.\n"; } }; B<You must always do your own error handling in the C<finally> block>. C<Try::Tiny> will not do anything about handling possible errors coming from code located in these blocks. Furthermore B<exceptions in C<finally> blocks are not trappable and are unable to influence the execution of your program>. This is due to limitation of C<DESTROY>-based scope guards, which C<finally> is implemented on top of. This may change in a future version of Try::Tiny. In the same way C<catch()> blesses the code reference this subroutine does the same except it bless them as C<Try::Tiny::Finally>. =back =head1 BACKGROUND There are a number of issues with C<eval>. =head2 Clobbering $@ When you run an C<eval> block and it succeeds, C<$@> will be cleared, potentially clobbering an error that is currently being caught. This causes action at a distance, clearing previous errors your caller may have not yet handled. C<$@> must be properly localized before invoking C<eval> in order to avoid this issue. More specifically, L<before Perl version 5.14.0|perl5140delta/"Exception Handling"> C<$@> was clobbered at the beginning of the C<eval>, which also made it impossible to capture the previous error before you die (for instance when making exception objects with error stacks). For this reason C<try> will actually set C<$@> to its previous value (the one available before entering the C<try> block) in the beginning of the C<eval> block. =head2 Localizing $@ silently masks errors Inside an C<eval> block, C<die> behaves sort of like: sub die { $@ = $_[0]; return_undef_from_eval(); } This means that if you were polite and localized C<$@> you can't die in that scope, or your error will be discarded (printing "Something's wrong" instead). The workaround is very ugly: my $error = do { local $@; eval { ... }; $@; }; ... die $error; =head2 $@ might not be a true value This code is wrong: if ( $@ ) { ... } because due to the previous caveats it may have been unset. C<$@> could also be an overloaded error object that evaluates to false, but that's asking for trouble anyway. The classic failure mode (fixed in L<Perl 5.14.0|perl5140delta/"Exception Handling">) is: sub Object::DESTROY { eval { ... } } eval { my $obj = Object->new; die "foo"; }; if ( $@ ) { } In this case since C<Object::DESTROY> is not localizing C<$@> but still uses C<eval>, it will set C<$@> to C<"">. The destructor is called when the stack is unwound, after C<die> sets C<$@> to C<"foo at Foo.pm line 42\n">, so by the time C<if ( $@ )> is evaluated it has been cleared by C<eval> in the destructor. The workaround for this is even uglier than the previous ones. Even though we can't save the value of C<$@> from code that doesn't localize, we can at least be sure the C<eval> was aborted due to an error: my $failed = not eval { ... return 1; }; This is because an C<eval> that caught a C<die> will always return a false value. =head1 ALTERNATE SYNTAX Using Perl 5.10 you can use L<perlsyn/"Switch statements"> (but please don't, because that syntax has since been deprecated because there was too much unexpected magical behaviour). =for stopwords topicalizer The C<catch> block is invoked in a topicalizer context (like a C<given> block), but note that you can't return a useful value from C<catch> using the C<when> blocks without an explicit C<return>. This is somewhat similar to Perl 6's C<CATCH> blocks. You can use it to concisely match errors: try { require Foo; } catch { when (/^Can't locate .*?\.pm in \@INC/) { } # ignore default { die $_ } }; =head1 CAVEATS =over 4 =item * C<@_> is not available within the C<try> block, so you need to copy your argument list. In case you want to work with argument values directly via C<@_> aliasing (i.e. allow C<$_[1] = "foo">), you need to pass C<@_> by reference: sub foo { my ( $self, @args ) = @_; try { $self->bar(@args) } } or sub bar_in_place { my $self = shift; my $args = \@_; try { $_ = $self->bar($_) for @$args } } =item * C<return> returns from the C<try> block, not from the parent sub (note that this is also how C<eval> works, but not how L<TryCatch> works): sub parent_sub { try { die; } catch { return; }; say "this text WILL be displayed, even though an exception is thrown"; } Instead, you should capture the return value: sub parent_sub { my $success = try { die; 1; }; return unless $success; say "This text WILL NEVER appear!"; } # OR sub parent_sub_with_catch { my $success = try { die; 1; } catch { # do something with $_ return undef; #see note }; return unless $success; say "This text WILL NEVER appear!"; } Note that if you have a C<catch> block, it must return C<undef> for this to work, since if a C<catch> block exists, its return value is returned in place of C<undef> when an exception is thrown. =item * C<try> introduces another caller stack frame. L<Sub::Uplevel> is not used. L<Carp> will not report this when using full stack traces, though, because C<%Carp::Internal> is used. This lack of magic is considered a feature. =for stopwords unhygienically =item * The value of C<$_> in the C<catch> block is not guaranteed to be the value of the exception thrown (C<$@>) in the C<try> block. There is no safe way to ensure this, since C<eval> may be used unhygienically in destructors. The only guarantee is that the C<catch> will be called if an exception is thrown. =item * The return value of the C<catch> block is not ignored, so if testing the result of the expression for truth on success, be sure to return a false value from the C<catch> block: my $obj = try { MightFail->new; } catch { ... return; # avoid returning a true value; }; return unless $obj; =item * C<$SIG{__DIE__}> is still in effect. Though it can be argued that C<$SIG{__DIE__}> should be disabled inside of C<eval> blocks, since it isn't people have grown to rely on it. Therefore in the interests of compatibility, C<try> does not disable C<$SIG{__DIE__}> for the scope of the error throwing code. =item * Lexical C<$_> may override the one set by C<catch>. For example Perl 5.10's C<given> form uses a lexical C<$_>, creating some confusing behavior: given ($foo) { when (...) { try { ... } catch { warn $_; # will print $foo, not the error warn $_[0]; # instead, get the error like this } } } Note that this behavior was changed once again in L<Perl5 version 18|https://metacpan.org/module/perldelta#given-now-aliases-the-global-_>. However, since the entirety of lexical C<$_> is now L<considered experimental |https://metacpan.org/module/perldelta#Lexical-_-is-now-experimental>, it is unclear whether the new version 18 behavior is final. =back =head1 SEE ALSO =over 4 =item L<Syntax::Keyword::Try> Only available on perls >= 5.14, with a slightly different syntax (e.g. no trailing C<;> because it's actually a keyword, not a sub, but this means you can C<return> and C<next> within it). Use L<Feature::Compat::Try> to automatically switch to the native C<try> syntax in newer perls (when available). See also L<Try Catch Exception Handling|perlsyn/Try-Catch-Exception-Handling>. =item L<TryCatch> Much more feature complete, more convenient semantics, but at the cost of implementation complexity. =item L<autodie> Automatic error throwing for builtin functions and more. Also designed to work well with C<given>/C<when>. =item L<Throwable> A lightweight role for rolling your own exception classes. =item L<Error> Exception object implementation with a C<try> statement. Does not localize C<$@>. =item L<Exception::Class::TryCatch> Provides a C<catch> statement, but properly calling C<eval> is your responsibility. The C<try> keyword pushes C<$@> onto an error stack, avoiding some of the issues with C<$@>, but you still need to localize to prevent clobbering. =back =head1 LIGHTNING TALK I gave a lightning talk about this module, you can see the slides (Firefox only): L<http://web.archive.org/web/20100628040134/http://nothingmuch.woobling.org/talks/takahashi.xul> Or read the source: L<http://web.archive.org/web/20100305133605/http://nothingmuch.woobling.org/talks/yapc_asia_2009/try_tiny.yml> =head1 SUPPORT Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Try-Tiny> (or L<bug-Try-Tiny@rt.cpan.org|mailto:bug-Try-Tiny@rt.cpan.org>). =head1 AUTHORS =over 4 =item * יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org> =item * Jesse Luehrs <doy@tozt.net> =back =head1 CONTRIBUTORS =for stopwords Karen Etheridge Peter Rabbitson Ricardo Signes Mark Fowler Graham Knop Aristotle Pagaltzis Dagfinn Ilmari Mannsåker Lukas Mai Alex anaxagoras Andrew Yates awalker chromatic cm-perl David Lowe Glenn Hans Dieter Pearcey Jens Berthold Jonathan Yu Marc Mims Stosberg Pali Paul Howarth Rudolf Leermakers =over 4 =item * Karen Etheridge <ether@cpan.org> =item * Peter Rabbitson <ribasushi@cpan.org> =item * Ricardo Signes <rjbs@cpan.org> =item * Mark Fowler <mark@twoshortplanks.com> =item * Graham Knop <haarg@haarg.org> =item * Aristotle Pagaltzis <pagaltzis@gmx.de> =item * Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> =item * Lukas Mai <l.mai@web.de> =item * Alex <alex@koban.(none)> =item * anaxagoras <walkeraj@gmail.com> =item * Andrew Yates <ayates@haddock.local> =item * awalker <awalker@sourcefire.com> =item * chromatic <chromatic@wgz.org> =item * cm-perl <cm-perl@users.noreply.github.com> =item * David Lowe <davidl@lokku.com> =item * Glenn Fowler <cebjyre@cpan.org> =item * Hans Dieter Pearcey <hdp@weftsoar.net> =item * Jens Berthold <jens@jebecs.de> =item * Jonathan Yu <JAWNSY@cpan.org> =item * Marc Mims <marc@questright.com> =item * Mark Stosberg <mark@stosberg.com> =item * Pali <pali@cpan.org> =item * Paul Howarth <paul@city-fan.org> =item * Rudolf Leermakers <rudolf@hatsuseno.org> =back =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2009 by יובל קוג'מן (Yuval Kogman). This is free software, licensed under: The MIT (X11) License =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/App/Cpan.pm�����������������������������������������������������������������������������������0000444�����������������00000117273�15253012307�0007541 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package App::Cpan; use strict; use warnings; use vars qw($VERSION); use if $] < 5.008 => 'IO::Scalar'; $VERSION = '1.678'; =head1 NAME App::Cpan - easily interact with CPAN from the command line =head1 SYNOPSIS # with arguments and no switches, installs specified modules cpan module_name [ module_name ... ] # with switches, installs modules with extra behavior cpan [-cfFimtTw] module_name [ module_name ... ] # use local::lib cpan -I module_name [ module_name ... ] # one time mirror override for faster mirrors cpan -p ... # with just the dot, install from the distribution in the # current directory cpan . # without arguments, starts CPAN.pm shell cpan # without arguments, but some switches cpan [-ahpruvACDLOPX] =head1 DESCRIPTION This script provides a command interface (not a shell) to CPAN. At the moment it uses CPAN.pm to do the work, but it is not a one-shot command runner for CPAN.pm. =head2 Options =over 4 =item -a Creates a CPAN.pm autobundle with CPAN::Shell->autobundle. =item -A module [ module ... ] Shows the primary maintainers for the specified modules. =item -c module Runs a `make clean` in the specified module's directories. =item -C module [ module ... ] Show the F<Changes> files for the specified modules =item -D module [ module ... ] Show the module details. This prints one line for each out-of-date module (meaning, modules locally installed but have newer versions on CPAN). Each line has three columns: module name, local version, and CPAN version. =item -f Force the specified action, when it normally would have failed. Use this to install a module even if its tests fail. When you use this option, -i is not optional for installing a module when you need to force it: % cpan -f -i Module::Foo =item -F Turn off CPAN.pm's attempts to lock anything. You should be careful with this since you might end up with multiple scripts trying to muck in the same directory. This isn't so much of a concern if you're loading a special config with C<-j>, and that config sets up its own work directories. =item -g module [ module ... ] Downloads to the current directory the latest distribution of the module. =item -G module [ module ... ] UNIMPLEMENTED Download to the current directory the latest distribution of the modules, unpack each distribution, and create a git repository for each distribution. If you want this feature, check out Yanick Champoux's C<Git::CPAN::Patch> distribution. =item -h Print a help message and exit. When you specify C<-h>, it ignores all of the other options and arguments. =item -i module [ module ... ] Install the specified modules. With no other switches, this switch is implied. =item -I Load C<local::lib> (think like C<-I> for loading lib paths). Too bad C<-l> was already taken. =item -j Config.pm Load the file that has the CPAN configuration data. This should have the same format as the standard F<CPAN/Config.pm> file, which defines C<$CPAN::Config> as an anonymous hash. If the file does not exist, C<cpan> dies. =item -J Dump the configuration in the same format that CPAN.pm uses. This is useful for checking the configuration as well as using the dump as a starting point for a new, custom configuration. =item -l List all installed modules with their versions =item -L author [ author ... ] List the modules by the specified authors. =item -m Make the specified modules. =item -M mirror1,mirror2,... A comma-separated list of mirrors to use for just this run. The C<-P> option can find them for you automatically. =item -n Do a dry run, but don't actually install anything. (unimplemented) =item -O Show the out-of-date modules. =item -p Ping the configured mirrors and print a report =item -P Find the best mirrors you could be using and use them for the current session. =item -r Recompiles dynamically loaded modules with CPAN::Shell->recompile. =item -s Drop in the CPAN.pm shell. This command does this automatically if you don't specify any arguments. =item -t module [ module ... ] Run a `make test` on the specified modules. =item -T Do not test modules. Simply install them. =item -u Upgrade all installed modules. Blindly doing this can really break things, so keep a backup. =item -v Print the script version and CPAN.pm version then exit. =item -V Print detailed information about the cpan client. =item -w UNIMPLEMENTED Turn on cpan warnings. This checks various things, like directory permissions, and tells you about problems you might have. =item -x module [ module ... ] Find close matches to the named modules that you think you might have mistyped. This requires the optional installation of Text::Levenshtein or Text::Levenshtein::Damerau. =item -X Dump all the namespaces to standard output. =back =head2 Examples # print a help message cpan -h # print the version numbers cpan -v # create an autobundle cpan -a # recompile modules cpan -r # upgrade all installed modules cpan -u # install modules ( sole -i is optional ) cpan -i Netscape::Booksmarks Business::ISBN # force install modules ( must use -i ) cpan -fi CGI::Minimal URI # install modules but without testing them cpan -Ti CGI::Minimal URI =head2 Environment variables There are several components in CPAN.pm that use environment variables. The build tools, L<ExtUtils::MakeMaker> and L<Module::Build> use some, while others matter to the levels above them. Some of these are specified by the Perl Toolchain Gang: Lancaster Consensus: L<https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md> Oslo Consensus: L<https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/oslo-consensus.md> =over 4 =item NONINTERACTIVE_TESTING Assume no one is paying attention and skips prompts for distributions that do that correctly. C<cpan(1)> sets this to C<1> unless it already has a value (even if that value is false). =item PERL_MM_USE_DEFAULT Use the default answer for a prompted questions. C<cpan(1)> sets this to C<1> unless it already has a value (even if that value is false). =item CPAN_OPTS As with C<PERL5OPT>, a string of additional C<cpan(1)> options to add to those you specify on the command line. =item CPANSCRIPT_LOGLEVEL The log level to use, with either the embedded, minimal logger or L<Log::Log4perl> if it is installed. Possible values are the same as the C<Log::Log4perl> levels: C<TRACE>, C<DEBUG>, C<INFO>, C<WARN>, C<ERROR>, and C<FATAL>. The default is C<INFO>. =item GIT_COMMAND The path to the C<git> binary to use for the Git features. The default is C</usr/local/bin/git>. =back =head2 Methods =over 4 =cut use autouse Carp => qw(carp croak cluck); use CPAN 1.80 (); # needs no test use Config; use autouse Cwd => qw(cwd); use autouse 'Data::Dumper' => qw(Dumper); use File::Spec::Functions qw(catfile file_name_is_absolute rel2abs); use File::Basename; use Getopt::Std; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Internal constants use constant TRUE => 1; use constant FALSE => 0; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # The return values use constant HEY_IT_WORKED => 0; use constant I_DONT_KNOW_WHAT_HAPPENED => 1; # 0b0000_0001 use constant ITS_NOT_MY_FAULT => 2; use constant THE_PROGRAMMERS_AN_IDIOT => 4; use constant A_MODULE_FAILED_TO_INSTALL => 8; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # set up the order of options that we layer over CPAN::Shell BEGIN { # most of this should be in methods use vars qw( @META_OPTIONS $Default %CPAN_METHODS @CPAN_OPTIONS @option_order %Method_table %Method_table_index ); @META_OPTIONS = qw( h v V I g G M: C A D O l L a r p P j: J w x X ); $Default = 'default'; %CPAN_METHODS = ( # map switches to method names in CPAN::Shell $Default => 'install', 'c' => 'clean', 'f' => 'force', 'i' => 'install', 'm' => 'make', 't' => 'test', 'u' => 'upgrade', 'T' => 'notest', 's' => 'shell', ); @CPAN_OPTIONS = grep { $_ ne $Default } sort keys %CPAN_METHODS; @option_order = ( @META_OPTIONS, @CPAN_OPTIONS ); # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # map switches to the subroutines in this script, along with other information. # use this stuff instead of hard-coded indices and values sub NO_ARGS () { 0 } sub ARGS () { 1 } sub GOOD_EXIT () { 0 } %Method_table = ( # key => [ sub ref, takes args?, exit value, description ] # options that do their thing first, then exit h => [ \&_print_help, NO_ARGS, GOOD_EXIT, 'Printing help' ], v => [ \&_print_version, NO_ARGS, GOOD_EXIT, 'Printing version' ], V => [ \&_print_details, NO_ARGS, GOOD_EXIT, 'Printing detailed version' ], X => [ \&_list_all_namespaces, NO_ARGS, GOOD_EXIT, 'Listing all namespaces' ], # options that affect other options j => [ \&_load_config, ARGS, GOOD_EXIT, 'Use specified config file' ], J => [ \&_dump_config, NO_ARGS, GOOD_EXIT, 'Dump configuration to stdout' ], F => [ \&_lock_lobotomy, NO_ARGS, GOOD_EXIT, 'Turn off CPAN.pm lock files' ], I => [ \&_load_local_lib, NO_ARGS, GOOD_EXIT, 'Loading local::lib' ], M => [ \&_use_these_mirrors, ARGS, GOOD_EXIT, 'Setting per session mirrors' ], P => [ \&_find_good_mirrors, NO_ARGS, GOOD_EXIT, 'Finding good mirrors' ], w => [ \&_turn_on_warnings, NO_ARGS, GOOD_EXIT, 'Turning on warnings' ], # options that do their one thing g => [ \&_download, ARGS, GOOD_EXIT, 'Download the latest distro' ], G => [ \&_gitify, ARGS, GOOD_EXIT, 'Down and gitify the latest distro' ], C => [ \&_show_Changes, ARGS, GOOD_EXIT, 'Showing Changes file' ], A => [ \&_show_Author, ARGS, GOOD_EXIT, 'Showing Author' ], D => [ \&_show_Details, ARGS, GOOD_EXIT, 'Showing Details' ], O => [ \&_show_out_of_date, NO_ARGS, GOOD_EXIT, 'Showing Out of date' ], l => [ \&_list_all_mods, NO_ARGS, GOOD_EXIT, 'Listing all modules' ], L => [ \&_show_author_mods, ARGS, GOOD_EXIT, 'Showing author mods' ], a => [ \&_create_autobundle, NO_ARGS, GOOD_EXIT, 'Creating autobundle' ], p => [ \&_ping_mirrors, NO_ARGS, GOOD_EXIT, 'Pinging mirrors' ], r => [ \&_recompile, NO_ARGS, GOOD_EXIT, 'Recompiling' ], u => [ \&_upgrade, NO_ARGS, GOOD_EXIT, 'Running `make test`' ], 's' => [ \&_shell, NO_ARGS, GOOD_EXIT, 'Drop into the CPAN.pm shell' ], 'x' => [ \&_guess_namespace, ARGS, GOOD_EXIT, 'Guessing namespaces' ], c => [ \&_default, ARGS, GOOD_EXIT, 'Running `make clean`' ], f => [ \&_default, ARGS, GOOD_EXIT, 'Installing with force' ], i => [ \&_default, ARGS, GOOD_EXIT, 'Running `make install`' ], 'm' => [ \&_default, ARGS, GOOD_EXIT, 'Running `make`' ], t => [ \&_default, ARGS, GOOD_EXIT, 'Running `make test`' ], T => [ \&_default, ARGS, GOOD_EXIT, 'Installing with notest' ], ); %Method_table_index = ( code => 0, takes_args => 1, exit_value => 2, description => 3, ); } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # finally, do some argument processing sub _stupid_interface_hack_for_non_rtfmers { no warnings 'uninitialized'; shift @ARGV if( $ARGV[0] eq 'install' and @ARGV > 1 ) } sub _process_options { my %options; push @ARGV, grep $_, split /\s+/, $ENV{CPAN_OPTS} || ''; # if no arguments, just drop into the shell if( 0 == @ARGV ) { CPAN::shell(); exit 0 } elsif (Getopt::Std::getopts( join( '', @option_order ), \%options )) { \%options; } else { exit 1 } } sub _process_setup_options { my( $class, $options ) = @_; if( $options->{j} ) { $Method_table{j}[ $Method_table_index{code} ]->( $options->{j} ); delete $options->{j}; } elsif ( ! $options->{h} ) { # h "ignores all of the other options and arguments" # this is what CPAN.pm would do otherwise local $CPAN::Be_Silent = 1; CPAN::HandleConfig->load( # be_silent => 1, deprecated write_file => 0, ); } $class->_turn_off_testing if $options->{T}; foreach my $o ( qw(F I w P M) ) { next unless exists $options->{$o}; $Method_table{$o}[ $Method_table_index{code} ]->( $options->{$o} ); delete $options->{$o}; } if( $options->{o} ) { my @pairs = map { [ split /=/, $_, 2 ] } split /,/, $options->{o}; foreach my $pair ( @pairs ) { my( $setting, $value ) = @$pair; $CPAN::Config->{$setting} = $value; # $logger->debug( "Setting [$setting] to [$value]" ); } delete $options->{o}; } my $option_count = grep { $options->{$_} } @option_order; no warnings 'uninitialized'; # don't count options that imply installation foreach my $opt ( qw(f T) ) { # don't count force or notest $option_count -= $options->{$opt}; } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if there are no options, set -i (this line fixes RT ticket 16915) $options->{i}++ unless $option_count; } sub _setup_environment { # should we override or set defaults? If this were a true interactive # session, we'd be in the CPAN shell. # https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md $ENV{NONINTERACTIVE_TESTING} = 1 unless defined $ENV{NONINTERACTIVE_TESTING}; $ENV{PERL_MM_USE_DEFAULT} = 1 unless defined $ENV{PERL_MM_USE_DEFAULT}; } =item run( ARGS ) Just do it. The C<run> method returns 0 on success and a positive number on failure. See the section on EXIT CODES for details on the values. =cut my $logger; sub run { my( $class, @args ) = @_; local @ARGV = @args; my $return_value = HEY_IT_WORKED; # assume that things will work $logger = $class->_init_logger; $logger->debug( "Using logger from @{[ref $logger]}" ); $class->_hook_into_CPANpm_report; $logger->debug( "Hooked into output" ); $class->_stupid_interface_hack_for_non_rtfmers; $logger->debug( "Patched cargo culting" ); my $options = $class->_process_options; $logger->debug( "Options are @{[Dumper($options)]}" ); $class->_process_setup_options( $options ); $class->_setup_environment( $options ); OPTION: foreach my $option ( @option_order ) { next unless $options->{$option}; my( $sub, $takes_args, $description ) = map { $Method_table{$option}[ $Method_table_index{$_} ] } qw( code takes_args description ); unless( ref $sub eq ref sub {} ) { $return_value = THE_PROGRAMMERS_AN_IDIOT; last OPTION; } $logger->info( "[$option] $description -- ignoring other arguments" ) if( @ARGV && ! $takes_args ); $return_value = $sub->( \ @ARGV, $options ); last; } return $return_value; } my $LEVEL; { package Local::Null::Logger; # hide from PAUSE my @LOGLEVELS = qw(TRACE DEBUG INFO WARN ERROR FATAL); $LEVEL = uc($ENV{CPANSCRIPT_LOGLEVEL} || 'INFO'); my %LL = map { $LOGLEVELS[$_] => $_ } 0..$#LOGLEVELS; unless (defined $LL{$LEVEL}){ warn "Unsupported loglevel '$LEVEL', setting to INFO"; $LEVEL = 'INFO'; } sub new { bless \ my $x, $_[0] } sub AUTOLOAD { my $autoload = our $AUTOLOAD; $autoload =~ s/.*://; return if $LL{uc $autoload} < $LL{$LEVEL}; $CPAN::Frontend->mywarn(">($autoload): $_\n") for split /[\r\n]+/, $_[1]; } sub DESTROY { 1 } } # load a module without searching the default entry for the current # directory sub _safe_load_module { my $name = shift; local @INC = @INC; pop @INC if $INC[-1] eq '.'; eval "require $name; 1"; } sub _init_logger { my $log4perl_loaded = _safe_load_module("Log::Log4perl"); unless( $log4perl_loaded ) { print STDOUT "Loading internal logger. Log::Log4perl recommended for better logging\n"; $logger = Local::Null::Logger->new; return $logger; } Log::Log4perl::init( \ <<"HERE" ); log4perl.rootLogger=$LEVEL, A1 log4perl.appender.A1=Log::Log4perl::Appender::Screen log4perl.appender.A1.layout=PatternLayout log4perl.appender.A1.layout.ConversionPattern=%m%n HERE $logger = Log::Log4perl->get_logger( 'App::Cpan' ); } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # sub _default { my( $args, $options ) = @_; my $switch = ''; # choose the option that we're going to use # we'll deal with 'f' (force) later, so skip it foreach my $option ( @CPAN_OPTIONS ) { next if ( $option eq 'f' or $option eq 'T' ); next unless $options->{$option}; $switch = $option; last; } # 1. with no switches, but arguments, use the default switch (install) # 2. with no switches and no args, start the shell # 3. With a switch but no args, die! These switches need arguments. if( not $switch and @$args ) { $switch = $Default; } elsif( not $switch and not @$args ) { return CPAN::shell() } elsif( $switch and not @$args ) { die "Nothing to $CPAN_METHODS{$switch}!\n"; } # Get and check the method from CPAN::Shell my $method = $CPAN_METHODS{$switch}; die "CPAN.pm cannot $method!\n" unless CPAN::Shell->can( $method ); # call the CPAN::Shell method, with force or notest if specified my $action = do { if( $options->{f} ) { sub { CPAN::Shell->force( $method, @_ ) } } elsif( $options->{T} ) { sub { CPAN::Shell->notest( $method, @_ ) } } else { sub { CPAN::Shell->$method( @_ ) } } }; # How do I handle exit codes for multiple arguments? my @errors = (); $options->{x} or _disable_guessers(); foreach my $arg ( @$args ) { # check the argument and perhaps capture typos my $module = _expand_module( $arg ) or do { $logger->error( "Skipping $arg because I couldn't find a matching namespace." ); next; }; _clear_cpanpm_output(); $action->( $arg ); my $error = _cpanpm_output_indicates_failure(); push @errors, $error if $error; } return do { if( @errors ) { $errors[0] } else { HEY_IT_WORKED } }; } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # =for comment CPAN.pm sends all the good stuff either to STDOUT, or to a temp file if $CPAN::Be_Silent is set. I have to intercept that output so I can find out what happened. =cut BEGIN { my $scalar = ''; sub _hook_into_CPANpm_report { no warnings 'redefine'; *CPAN::Shell::myprint = sub { my($self,$what) = @_; $scalar .= $what if defined $what; $self->print_ornamented($what, $CPAN::Config->{colorize_print}||'bold blue on_white', ); }; *CPAN::Shell::mywarn = sub { my($self,$what) = @_; $scalar .= $what if defined $what; $self->print_ornamented($what, $CPAN::Config->{colorize_warn}||'bold red on_white' ); }; } sub _clear_cpanpm_output { $scalar = '' } sub _get_cpanpm_output { $scalar } # These are lines I don't care about in CPAN.pm output. If I can # filter out the informational noise, I have a better chance to # catch the error signal my @skip_lines = ( qr/^\QWarning \(usually harmless\)/, qr/\bwill not store persistent state\b/, qr(//hint//), qr/^\s+reports\s+/, qr/^Try the command/, qr/^\s+$/, qr/^to find objects/, qr/^\s*Database was generated on/, qr/^Going to read/, qr|^\s+i\s+/|, # the i /Foo::Whatever/ line when it doesn't know ); sub _get_cpanpm_last_line { my $fh; if( $] < 5.008 ) { $fh = IO::Scalar->new( \ $scalar ); } else { eval q{ open $fh, '<', \\ $scalar; }; } my @lines = <$fh>; # This is a bit ugly. Once we examine a line, we have to # examine the line before it and go through all of the same # regexes. I could do something fancy, but this works. REGEXES: { foreach my $regex ( @skip_lines ) { if( $lines[-1] =~ m/$regex/ ) { pop @lines; redo REGEXES; # we have to go through all of them for every line! } } } $logger->debug( "Last interesting line of CPAN.pm output is:\n\t$lines[-1]" ); $lines[-1]; } } BEGIN { my $epic_fail_words = join '|', qw( Error stop(?:ping)? problems force not unsupported fail(?:ed)? Cannot\s+install ); sub _cpanpm_output_indicates_failure { my $last_line = _get_cpanpm_last_line(); my $result = $last_line =~ /\b(?:$epic_fail_words)\b/i; return A_MODULE_FAILED_TO_INSTALL if $last_line =~ /\b(?:Cannot\s+install)\b/i; $result || (); } } sub _cpanpm_output_indicates_success { my $last_line = _get_cpanpm_last_line(); my $result = $last_line =~ /\b(?:\s+-- OK|PASS)\b/; $result || (); } sub _cpanpm_output_is_vague { return FALSE if _cpanpm_output_indicates_failure() || _cpanpm_output_indicates_success(); return TRUE; } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # sub _turn_on_warnings { carp "Warnings are implemented yet"; return HEY_IT_WORKED; } sub _turn_off_testing { $logger->debug( 'Trusting test report history' ); $CPAN::Config->{trust_test_report_history} = 1; return HEY_IT_WORKED; } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # sub _print_help { $logger->info( "Use perldoc to read the documentation" ); my $HAVE_PERLDOC = eval { require Pod::Perldoc; 1; }; if ($HAVE_PERLDOC) { system qq{"$^X" -e "require Pod::Perldoc; Pod::Perldoc->run()" $0}; exit; } else { warn "Please install Pod::Perldoc, maybe try 'cpan -i Pod::Perldoc'\n"; return HEY_IT_WORKED; } } sub _print_version # -v { $logger->info( "$0 script version $VERSION, CPAN.pm version " . CPAN->VERSION ); return HEY_IT_WORKED; } sub _print_details # -V { _print_version(); _check_install_dirs(); $logger->info( '-' x 50 . "\nChecking configured mirrors..." ); foreach my $mirror ( @{ $CPAN::Config->{urllist} } ) { _print_ping_report( $mirror ); } $logger->info( '-' x 50 . "\nChecking for faster mirrors..." ); { require CPAN::Mirrors; if ( $CPAN::Config->{connect_to_internet_ok} ) { $CPAN::Frontend->myprint(qq{Trying to fetch a mirror list from the Internet\n}); eval { CPAN::FTP->localize('MIRRORED.BY',File::Spec->catfile($CPAN::Config->{keep_source_where},'MIRRORED.BY'),3,1) } or $CPAN::Frontend->mywarn(<<'HERE'); We failed to get a copy of the mirror list from the Internet. You will need to provide CPAN mirror URLs yourself. HERE $CPAN::Frontend->myprint("\n"); } my $mirrors = CPAN::Mirrors->new( _mirror_file() ); my @continents = $mirrors->find_best_continents; my @mirrors = $mirrors->get_mirrors_by_continents( $continents[0] ); my @timings = $mirrors->get_mirrors_timings( \@mirrors ); foreach my $timing ( @timings ) { $logger->info( sprintf "%s (%0.2f ms)", $timing->hostname, $timing->rtt ); } } return HEY_IT_WORKED; } sub _check_install_dirs { my $makepl_arg = $CPAN::Config->{makepl_arg}; my $mbuildpl_arg = $CPAN::Config->{mbuildpl_arg}; my @custom_dirs; # PERL_MM_OPT push @custom_dirs, $makepl_arg =~ m/INSTALL_BASE\s*=\s*(\S+)/g, $mbuildpl_arg =~ m/--install_base\s*=\s*(\S+)/g; if( @custom_dirs ) { foreach my $dir ( @custom_dirs ) { _print_inc_dir_report( $dir ); } } # XXX: also need to check makepl_args, etc my @checks = ( [ 'core', [ grep $_, @Config{qw(installprivlib installarchlib)} ] ], [ 'vendor', [ grep $_, @Config{qw(installvendorlib installvendorarch)} ] ], [ 'site', [ grep $_, @Config{qw(installsitelib installsitearch)} ] ], [ 'PERL5LIB', _split_paths( $ENV{PERL5LIB} ) ], [ 'PERLLIB', _split_paths( $ENV{PERLLIB} ) ], ); $logger->info( '-' x 50 . "\nChecking install dirs..." ); foreach my $tuple ( @checks ) { my( $label ) = $tuple->[0]; $logger->info( "Checking $label" ); $logger->info( "\tno directories for $label" ) unless @{ $tuple->[1] }; foreach my $dir ( @{ $tuple->[1] } ) { _print_inc_dir_report( $dir ); } } } sub _split_paths { [ map { _expand_filename( $_ ) } split /$Config{path_sep}/, $_[0] || '' ]; } =pod Stolen from File::Path::Expand =cut sub _expand_filename { my( $path ) = @_; no warnings 'uninitialized'; $logger->debug( "Expanding path $path\n" ); $path =~ s{\A~([^/]+)?}{ _home_of( $1 || $> ) || "~$1" }e; return $path; } sub _home_of { require User::pwent; my( $user ) = @_; my $ent = User::pwent::getpw($user) or return; return $ent->dir; } sub _get_default_inc { require Config; [ @Config::Config{ _vars() }, '.' ]; } sub _vars { qw( installarchlib installprivlib installsitearch installsitelib ); } sub _ping_mirrors { my $urls = $CPAN::Config->{urllist}; require URI; foreach my $url ( @$urls ) { my( $obj ) = URI->new( $url ); next unless _is_pingable_scheme( $obj ); my $host = $obj->host; _print_ping_report( $obj ); } } sub _is_pingable_scheme { my( $uri ) = @_; $uri->scheme eq 'file' } sub _mirror_file { my $file = do { my $file = 'MIRRORED.BY'; my $local_path = File::Spec->catfile( $CPAN::Config->{keep_source_where}, $file ); if( -e $local_path ) { $local_path } else { require CPAN::FTP; CPAN::FTP->localize( $file, $local_path, 3, 1 ); $local_path; } }; } sub _find_good_mirrors { require CPAN::Mirrors; my $mirrors = CPAN::Mirrors->new( _mirror_file() ); my @mirrors = $mirrors->best_mirrors( how_many => 5, verbose => 1, ); foreach my $mirror ( @mirrors ) { next unless eval { $mirror->can( 'http' ) }; _print_ping_report( $mirror->http ); } $CPAN::Config->{urllist} = [ map { $_->http } @mirrors ]; } sub _print_inc_dir_report { my( $dir ) = shift; my $writeable = -w $dir ? '+' : '!!! (not writeable)'; $logger->info( "\t$writeable $dir" ); return -w $dir; } sub _print_ping_report { my( $mirror ) = @_; my $rtt = eval { _get_ping_report( $mirror ) }; my $result = $rtt ? sprintf "+ (%4d ms)", $rtt * 1000 : '!'; $logger->info( sprintf "\t%s %s", $result, $mirror ); } sub _get_ping_report { require URI; my( $mirror ) = @_; my( $url ) = ref $mirror ? $mirror : URI->new( $mirror ); #XXX require Net::Ping; my $ping = Net::Ping->new( 'tcp', 1 ); if( $url->scheme eq 'file' ) { return -e $url->file; } my( $port ) = $url->port; return unless $port; if ( $ping->can('port_number') ) { $ping->port_number($port); } else { $ping->{'port_num'} = $port; } $ping->hires(1) if $ping->can( 'hires' ); my( $alive, $rtt ) = eval{ $ping->ping( $url->host ) }; $alive ? $rtt : undef; } sub _load_local_lib # -I { $logger->debug( "Loading local::lib" ); my $rc = _safe_load_module("local::lib"); unless( $rc ) { $logger->logdie( "Could not load local::lib" ); } local::lib->import; return HEY_IT_WORKED; } sub _use_these_mirrors # -M { $logger->debug( "Setting per session mirrors" ); unless( $_[0] ) { $logger->logdie( "The -M switch requires a comma-separated list of mirrors" ); } $CPAN::Config->{urllist} = [ split /,/, $_[0] ]; $logger->debug( "Mirrors are @{$CPAN::Config->{urllist}}" ); } sub _create_autobundle { $logger->info( "Creating autobundle in $CPAN::Config->{cpan_home}/Bundle" ); CPAN::Shell->autobundle; return HEY_IT_WORKED; } sub _recompile { $logger->info( "Recompiling dynamically-loaded extensions" ); CPAN::Shell->recompile; return HEY_IT_WORKED; } sub _upgrade { $logger->info( "Upgrading all modules" ); CPAN::Shell->upgrade(); return HEY_IT_WORKED; } sub _shell { $logger->info( "Dropping into shell" ); CPAN::shell(); return HEY_IT_WORKED; } sub _load_config # -j { my $argument = shift; my $file = file_name_is_absolute( $argument ) ? $argument : rel2abs( $argument ); croak( "cpan config file [$file] for -j does not exist!\n" ) unless -e $file; # should I clear out any existing config here? $CPAN::Config = {}; delete $INC{'CPAN/Config.pm'}; my $rc = eval "require '$file'"; # CPAN::HandleConfig::require_myconfig_or_config looks for this $INC{'CPAN/MyConfig.pm'} = 'fake out!'; # CPAN::HandleConfig::load looks for this $CPAN::Config_loaded = 'fake out'; croak( "Could not load [$file]: $@\n") unless $rc; return HEY_IT_WORKED; } sub _dump_config # -J { my $args = shift; require Data::Dumper; my $fh = $args->[0] || \*STDOUT; local $Data::Dumper::Sortkeys = 1; my $dd = Data::Dumper->new( [$CPAN::Config], ['$CPAN::Config'] ); print $fh $dd->Dump, "\n1;\n__END__\n"; return HEY_IT_WORKED; } sub _lock_lobotomy # -F { no warnings 'redefine'; *CPAN::_flock = sub { 1 }; *CPAN::checklock = sub { 1 }; return HEY_IT_WORKED; } sub _download { my $args = shift; local $CPAN::DEBUG = 1; my %paths; foreach my $arg ( @$args ) { $logger->info( "Checking $arg" ); my $module = _expand_module( $arg ) or next; my $path = $module->cpan_file; $logger->debug( "Inst file would be $path\n" ); $paths{$module} = _get_file( _make_path( $path ) ); $logger->info( "Downloaded [$arg] to [$paths{$arg}]" ); } return \%paths; } sub _make_path { join "/", qw(authors id), $_[0] } sub _get_file { my $path = shift; my $loaded = _safe_load_module("LWP::Simple"); croak "You need LWP::Simple to use features that fetch files from CPAN\n" unless $loaded; my $file = substr $path, rindex( $path, '/' ) + 1; my $store_path = catfile( cwd(), $file ); $logger->debug( "Store path is $store_path" ); foreach my $site ( @{ $CPAN::Config->{urllist} } ) { my $fetch_path = join "/", $site, $path; $logger->debug( "Trying $fetch_path" ); my $status_code = LWP::Simple::getstore( $fetch_path, $store_path ); last if( 200 <= $status_code and $status_code <= 300 ); $logger->warn( "Could not get [$fetch_path]: Status code $status_code" ); } return $store_path; } sub _gitify { my $args = shift; my $loaded = _safe_load_module("Archive::Extract"); croak "You need Archive::Extract to use features that gitify distributions\n" unless $loaded; my $starting_dir = cwd(); foreach my $arg ( @$args ) { $logger->info( "Checking $arg" ); my $store_paths = _download( [ $arg ] ); $logger->debug( "gitify Store path is $store_paths->{$arg}" ); my $dirname = dirname( $store_paths->{$arg} ); my $ae = Archive::Extract->new( archive => $store_paths->{$arg} ); $ae->extract( to => $dirname ); chdir $ae->extract_path; my $git = $ENV{GIT_COMMAND} || '/usr/local/bin/git'; croak "Could not find $git" unless -e $git; croak "$git is not executable" unless -x $git; # can we do this in Pure Perl? system( $git, 'init' ); system( $git, qw( add . ) ); system( $git, qw( commit -a -m ), 'initial import' ); } chdir $starting_dir; return HEY_IT_WORKED; } sub _show_Changes { my $args = shift; foreach my $arg ( @$args ) { $logger->info( "Checking $arg\n" ); my $module = _expand_module( $arg ) or next; my $out = _get_cpanpm_output(); next unless eval { $module->inst_file }; #next if $module->uptodate; ( my $id = $module->id() ) =~ s/::/\-/; my $url = "http://search.cpan.org/~" . lc( $module->userid ) . "/" . $id . "-" . $module->cpan_version() . "/"; #print "URL: $url\n"; _get_changes_file($url); } return HEY_IT_WORKED; } sub _get_changes_file { croak "Reading Changes files requires LWP::Simple and URI\n" unless _safe_load_module("LWP::Simple") && _safe_load_module("URI"); my $url = shift; my $content = LWP::Simple::get( $url ); $logger->info( "Got $url ..." ) if defined $content; #print $content; my( $change_link ) = $content =~ m|<a href="(.*?)">Changes</a>|gi; my $changes_url = URI->new_abs( $change_link, $url ); $logger->debug( "Change link is: $changes_url" ); my $changes = LWP::Simple::get( $changes_url ); print $changes; return HEY_IT_WORKED; } sub _show_Author { my $args = shift; foreach my $arg ( @$args ) { my $module = _expand_module( $arg ) or next; unless( $module ) { $logger->info( "Didn't find a $arg module, so no author!" ); next; } my $author = CPAN::Shell->expand( "Author", $module->userid ); next unless $module->userid; printf "%-25s %-8s %-25s %s\n", $arg, $module->userid, $author->email, $author->name; } return HEY_IT_WORKED; } sub _show_Details { my $args = shift; foreach my $arg ( @$args ) { my $module = _expand_module( $arg ) or next; my $author = CPAN::Shell->expand( "Author", $module->userid ); next unless $module->userid; print "$arg\n", "-" x 73, "\n\t"; print join "\n\t", $module->description ? $module->description : "(no description)", $module->cpan_file ? $module->cpan_file : "(no cpanfile)", $module->inst_file ? $module->inst_file :"(no installation file)" , 'Installed: ' . ($module->inst_version ? $module->inst_version : "not installed"), 'CPAN: ' . $module->cpan_version . ' ' . ($module->uptodate ? "" : "Not ") . "up to date", $author->fullname . " (" . $module->userid . ")", $author->email; print "\n\n"; } return HEY_IT_WORKED; } BEGIN { my $modules; sub _get_all_namespaces { return $modules if $modules; $modules = [ map { $_->id } CPAN::Shell->expand( "Module", "/./" ) ]; } } sub _show_out_of_date { my $modules = _get_all_namespaces(); printf "%-40s %6s %6s\n", "Module Name", "Local", "CPAN"; print "-" x 73, "\n"; foreach my $module ( @$modules ) { next unless $module = _expand_module($module); next unless $module->inst_file; next if $module->uptodate; printf "%-40s %.4f %.4f\n", $module->id, $module->inst_version ? $module->inst_version : '', $module->cpan_version; } return HEY_IT_WORKED; } sub _show_author_mods { my $args = shift; my %hash = map { lc $_, 1 } @$args; my $modules = _get_all_namespaces(); foreach my $module ( @$modules ) { next unless exists $hash{ lc $module->userid }; print $module->id, "\n"; } return HEY_IT_WORKED; } sub _list_all_mods # -l { require File::Find; my $args = shift; my $fh = \*STDOUT; INC: foreach my $inc ( @INC ) { my( $wanted, $reporter ) = _generator(); File::Find::find( { wanted => $wanted }, $inc ); my $count = 0; FILE: foreach my $file ( @{ $reporter->() } ) { my $version = _parse_version_safely( $file ); my $module_name = _path_to_module( $inc, $file ); next FILE unless defined $module_name; print $fh "$module_name\t$version\n"; #last if $count++ > 5; } } return HEY_IT_WORKED; } sub _generator { my @files = (); sub { push @files, File::Spec->canonpath( $File::Find::name ) if m/\A\w+\.pm\z/ }, sub { \@files }, } sub _parse_version_safely # stolen from PAUSE's mldistwatch, but refactored { my( $file ) = @_; local $/ = "\n"; local $_; # don't mess with the $_ in the map calling this return unless open FILE, "<$file"; my $in_pod = 0; my $version; while( <FILE> ) { chomp; $in_pod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $in_pod; next if $in_pod || /^\s*#/; next unless /([\$*])(([\w\:\']*)\bVERSION)\b.*\=/; my( $sigil, $var ) = ( $1, $2 ); $version = _eval_version( $_, $sigil, $var ); last; } close FILE; return 'undef' unless defined $version; return $version; } sub _eval_version { my( $line, $sigil, $var ) = @_; # split package line to hide from PAUSE my $eval = qq{ package ExtUtils::MakeMaker::_version; local $sigil$var; \$$var=undef; do { $line }; \$$var }; my $version = do { local $^W = 0; no strict; eval( $eval ); }; return $version; } sub _path_to_module { my( $inc, $path ) = @_; return if length $path < length $inc; my $module_path = substr( $path, length $inc ); $module_path =~ s/\.pm\z//; # XXX: this is cheating and doesn't handle everything right my @dirs = grep { ! /\W/ } File::Spec->splitdir( $module_path ); shift @dirs; my $module_name = join "::", @dirs; return $module_name; } sub _expand_module { my( $module ) = @_; my $expanded = CPAN::Shell->expandany( $module ); return $expanded if $expanded; $expanded = CPAN::Shell->expand( "Module", $module ); unless( defined $expanded ) { $logger->error( "Could not expand [$module]. Check the module name." ); my $threshold = ( grep { int } sort { length $a <=> length $b } length($module)/4, 4 )[0]; my $guesses = _guess_at_module_name( $module, $threshold ); if( defined $guesses and @$guesses ) { $logger->info( "Perhaps you meant one of these:" ); foreach my $guess ( @$guesses ) { $logger->info( "\t$guess" ); } } return; } return $expanded; } my $guessers = [ [ qw( Text::Levenshtein::XS distance 7 1 ) ], [ qw( Text::Levenshtein::Damerau::XS xs_edistance 7 1 ) ], [ qw( Text::Levenshtein distance 7 1 ) ], [ qw( Text::Levenshtein::Damerau::PP pp_edistance 7 1 ) ], ]; sub _disable_guessers { $_->[-1] = 0 for @$guessers; } # for -x sub _guess_namespace { my $args = shift; foreach my $arg ( @$args ) { $logger->debug( "Checking $arg" ); my $guesses = _guess_at_module_name( $arg ); foreach my $guess ( @$guesses ) { print $guess, "\n"; } } return HEY_IT_WORKED; } sub _list_all_namespaces { my $modules = _get_all_namespaces(); foreach my $module ( @$modules ) { print $module, "\n"; } } BEGIN { my $distance; my $_threshold; my $can_guess; my $shown_help = 0; sub _guess_at_module_name { my( $target, $threshold ) = @_; unless( defined $distance ) { foreach my $try ( @$guessers ) { $can_guess = eval "require $try->[0]; 1" or next; $try->[-1] or next; # disabled no strict 'refs'; $distance = \&{ join "::", @$try[0,1] }; $threshold ||= $try->[2]; } } $_threshold ||= $threshold; unless( $distance ) { unless( $shown_help ) { my $modules = join ", ", map { $_->[0] } @$guessers; substr $modules, rindex( $modules, ',' ), 1, ', and'; # Should this be colorized? if( $can_guess ) { $logger->info( "I can suggest names if you provide the -x option on invocation." ); } else { $logger->info( "I can suggest names if you install one of $modules" ); $logger->info( "and you provide the -x option on invocation." ); } $shown_help++; } return; } my $modules = _get_all_namespaces(); $logger->info( "Checking " . @$modules . " namespaces for close match suggestions" ); my %guesses; foreach my $guess ( @$modules ) { my $distance = $distance->( $target, $guess ); next if $distance > $_threshold; $guesses{$guess} = $distance; } my @guesses = sort { $guesses{$a} <=> $guesses{$b} } keys %guesses; return [ grep { defined } @guesses[0..9] ]; } } 1; =back =head1 EXIT VALUES The script exits with zero if it thinks that everything worked, or a positive number if it thinks that something failed. Note, however, that in some cases it has to divine a failure by the output of things it does not control. For now, the exit codes are vague: 1 An unknown error 2 The was an external problem 4 There was an internal problem with the script 8 A module failed to install =head1 TO DO * There is initial support for Log4perl if it is available, but I haven't gone through everything to make the NullLogger work out correctly if Log4perl is not installed. * When I capture CPAN.pm output, I need to check for errors and report them to the user. * Warnings switch * Check then exit =head1 BUGS * none noted =head1 SEE ALSO L<CPAN>, L<App::cpanminus> =head1 SOURCE AVAILABILITY This code is in Github in the CPAN.pm repository: https://github.com/andk/cpanpm The source used to be tracked separately in another GitHub repo, but the canonical source is now in the above repo. =head1 CREDITS Japheth Cleaver added the bits to allow a forced install (C<-f>). Jim Brandt suggested and provided the initial implementation for the up-to-date and Changes features. Adam Kennedy pointed out that C<exit()> causes problems on Windows where this script ends up with a .bat extension David Golden helps integrate this into the C<CPAN.pm> repos. Jim Keenan fixed up various issues with _download =head1 AUTHOR brian d foy, C<< <bdfoy@cpan.org> >> =head1 COPYRIGHT Copyright (c) 2001-2021, brian d foy, All Rights Reserved. You may redistribute this under the same terms as Perl itself. =cut # Local Variables: # mode: cperl # indent-tabs-mode: t # cperl-indent-level: 8 # cperl-continued-statement-offset: 8 # End: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Expect-1.38/install.json��������������������������������������0000444�����������������00000000261�15253012307�0017442 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"Expect-1.38","name":"Expect","target":"Expect","provides":{"Expect":{"version":1.38,"file":"lib/Expect.pm"}},"pathname":"J/JA/JACOBY/Expect-1.38.tar.gz","version":1.38}�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Expect-1.38/MYMETA.json���������������������������������������0000444�����������������00000003066�15253012307�0016776 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "automate interactions with command line programs that expose a text terminal interface.", "author" : [ "Austin Schutz <ASchutz@users.sourceforge.net>", "Roland Giersig <RGiersig@cpan.org>", "Dave Jacoby <jacoby@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.62, 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.38", "x_serialization_backend" : "JSON::PP version 2.97001" } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/IO-Tty-1.20/install.json��������������������������������������0000444�����������������00000000435�15253012307�0017271 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"provides":{"IO::Tty":{"file":"Tty.pm","version":"1.20"},"IO::Tty::Constant":{"version":"1.20","file":"Tty/Constant.pm"},"IO::Pty":{"file":"Pty.pm","version":"1.20"}},"target":"IO::Tty","version":"1.20","pathname":"T/TO/TODDR/IO-Tty-1.20.tar.gz","dist":"IO-Tty-1.20","name":"IO::Tty"}�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/IO-Tty-1.20/MYMETA.json���������������������������������������0000444�����������������00000002101�15253012307�0016607 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "Pseudo ttys and constants", "author" : [ "Roland Giersig <RGiersig@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.64, 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.20", "x_serialization_backend" : "JSON::PP version 2.97001" } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/LWP-Protocol-https-6.14/install.json��������������������������0000444�����������������00000000531�15253012307�0021612 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"name":"LWP::Protocol::https","pathname":"O/OA/OALDERS/LWP-Protocol-https-6.14.tar.gz","version":"6.14","dist":"LWP-Protocol-https-6.14","provides":{"LWP::Protocol::https":{"version":"6.14","file":"lib/LWP/Protocol/https.pm"},"LWP::Protocol::https::Socket":{"version":"6.14","file":"lib/LWP/Protocol/https.pm"}},"target":"LWP::Protocol::https"}�����������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/LWP-Protocol-https-6.14/MYMETA.json���������������������������0000444�����������������00000061661�15253012307�0021153 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "Provide https support for LWP::UserAgent", "author" : [ "Gisle Aas <gisle@activestate.com>" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.031, 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" : { "Capture::Tiny" : "0.48", "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.970", "LWP::Protocol::http" : "0", "LWP::UserAgent" : "6.06", "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.970", "IO::Socket::SSL::Utils" : "0", "LWP::UserAgent" : "6.06", "Socket" : "0", "Test::More" : "0.96", "Test::Needs" : "0.002010", "Test::RequiresInternet" : "0", "warnings" : "0" } } }, "provides" : { "LWP::Protocol::https" : { "file" : "lib/LWP/Protocol/https.pm", "version" : "6.14" }, "LWP::Protocol::https::Socket" : { "file" : "lib/LWP/Protocol/https.pm", "version" : "6.14" } }, "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.14", "x_Dist_Zilla" : { "perl" : { "version" : "5.034000" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "LICENSE", "META.json", "Makefile.PL", "README.md" ], "exclude_match" : [], "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "Git::GatherDir", "version" : "2.049" }, { "class" : "Dist::Zilla::Plugin::PruneCruft", "name" : "PruneCruft", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "MetaConfig", "version" : "6.031" }, { "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.031" } ], "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.031" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "MetaYAML", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "MetaJSON", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "MetaResources", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "LICENSE", "META.json", "Makefile.PL", "README.md" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.34.1", "repo_root" : "." } }, "name" : "Git::Check", "version" : "2.049" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.34.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.031" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "License", "version" : "6.031" }, { "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.031" }, { "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.34.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/release snapshot", "version" : "2.049" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v6.14", "tag_format" : "v%V", "tag_message" : "v%V" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.34.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/Git::Tag", "version" : "2.049" }, { "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.031" }, { "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.34.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Git::VersionManager/post-release commit", "version" : "2.049" }, { "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.031" }, "Dist::Zilla::Role::TestRunner" : { "default_jobs" : "8", "version" : "6.031" } }, "name" : "MakeMaker::Awesome", "version" : "0.49" }, { "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.029" }, { "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.001001" }, { "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.031" }, { "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.031" }, { "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" : "8" } }, "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.031" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "ConfirmRelease", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "UploadToCPAN", "version" : "6.031" }, { "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.34.1", "repo_root" : "." } }, "name" : "Git::Push", "version" : "2.049" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.031" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.031" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.031" } }, "x_contributors" : [ "Adam Kennedy <adamk@cpan.org>", "Adam Sjogren <asjo@koldfront.dk>", "Alexandr Ciornii <alexchorny@gmail.com>", "Alexey Tourbin <at@altlinux.ru>", "Alex Kapranoff <ka@nadoby.ru>", "amire80 <amir.aharoni@gmail.com>", "Andreas J. Koenig <andreas.koenig@anima.de>", "Axel Burri <axel@tty0.ch>", "Bill Mann <wfmann@alum.mit.edu>", "Bron Gondwana <brong@fastmail.fm>", "Chase Whitener <capoeirab@cpan.org>", "Christopher J. Madsen <cjm@cpan.org>", "cpansprout <cpansprout@gmail.com>", "Dan Book <grinnz@grinnz.com>", "Daniel Hedlund <Daniel.Hedlund@eprize.com>", "David E. Wheeler <david@justatheory.com>", "David Golden <dagolden@cpan.org>", "DAVIDRW <davidrw@cpan.org>", "dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>", "Dmitriy Shamatrin <dshamatrin@cloudbees.com>", "drieux <drieux@yahoo-inc.com>", "Father Chrysostomos <sprout@cpan.org>", "FWILES <FWILES@cpan.org>", "Gavin Peters <gpeters@deepsky.com>", "Gianni Ceccarelli <gianni.ceccarelli@broadbean.com>", "Gisle Aas <gisle@aas.no>", "Graeme Thompson <Graeme.Thompson@mobilecohesion.com>", "Hans-H. Froehlich <hfroehlich@co-de-co.de>", "Ian Kilgore <iank@cpan.org>", "Jacob J <waif@chaos2.org>", "Jakub Wilk <jwilk@jwilk.net>", "jefflee <shaohua@gmail.com>", "JJ Merelo <jjmerelo@gmail.com>", "john9art <john9art@yahoo.com>", "Jon Jensen <jon@endpoint.com>", "Karen Etheridge <ether@cpan.org>", "Leo Lapworth <leo@cuckoo.org>", "Marin Tsanov <btg.tsanov.marin@gmail.com>", "Mark Stosberg <mark@stosberg.com>", "Michael G. Schwern <schwern@pobox.com>", "Mike Schilli <github@perlmeister.com>", "Mohammad S Anwar <mohammad.anwar@yahoo.com>", "murphy <murphy@genome.chop.edu>", "Nicolas R <nicolas@atoomic.org>", "Olaf Alders <olaf@wundersolutions.com>", "Ondrej Hanak <ondrej.hanak@ubs.com>", "openstrike <git@openstrike.co.uk>", "Peter Rabbitson <ribasushi@cpan.org>", "phrstbrn <phrstbrn@gmail.com>", "Randy Stauner <randy@magnificent-tears.com>", "Robert Stone <talby@trap.mtview.ca.us>", "Rolf Grossmann <rg@progtech.net>", "ruff <ruff@ukrpost.net>", "sasao <sasao@yugen.org>", "Sean M. Burke <sburke@cpan.org>", "Shoichi Kaji <skaji@cpan.org>", "Slaven Rezic <slaven@rezic.de>", "Spiros Denaxas <s.denaxas@gmail.com>", "Steffen Ullrich <Steffen_Ullrich@genua.de>", "Steve Hay <SteveHay@planit.com>", "Tim Couzins <tim.couzins@sophos.com>", "Todd Lipcon <todd@amiestreet.com>", "Tom Hukins <tom@eborcom.com>", "Tony Finch <dot@dotat.at>", "Toru Yamaguchi <zigorou@cpan.org>", "uid39246 <uid39246>", "Ville Skyttä <ville.skytta@iki.fi>", "Yuri Karaban <tech@askold.net>", "Yury Zavarin <yury.zavarin@gmail.com>", "Zefram <zefram@fysh.org>" ], "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/Switch-2.17/install.json��������������������������������������0000444�����������������00000000255�15253012307�0017454 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"pathname":"C/CH/CHORNY/Switch-2.17.tar.gz","name":"Switch","dist":"Switch-2.17","target":"Switch","provides":{"Switch":{"version":2.17,"file":"Switch.pm"}},"version":2.17}���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Switch-2.17/MYMETA.json���������������������������������������0000444�����������������00000002336�15253012307�0017004 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "A switch statement for Perl, do not use if you can use given/when", "author" : [ "Damian Conway", "Rafael Garcia-Suarez", "Alexandr Ciornii" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 6.78, CPAN::Meta::Converter version 2.131490, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Switch", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Filter::Util::Call" : "0", "Text::Balanced" : "2", "if" : "0", "perl" : "5.005" } } }, "release_status" : "stable", "resources" : { "repository" : { "url" : "http://github.com/chorny/Switch" } }, "version" : "2.17", "x_serialization_backend" : "JSON::PP version 2.97001" } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/HTTP-Tiny-0.088/install.json����������������������������������0000444�����������������00000000320�15253012307�0017772 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"HTTP-Tiny-0.088","name":"HTTP::Tiny","target":"HTTP::Tiny","provides":{"HTTP::Tiny":{"version":"0.088","file":"lib/HTTP/Tiny.pm"}},"pathname":"D/DA/DAGOLDEN/HTTP-Tiny-0.088.tar.gz","version":"0.088"}����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/HTTP-Tiny-0.088/MYMETA.json�����������������������������������0000444�����������������00000013625�15253012307�0017334 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "A small, simple, correct HTTP/1.1 client", "author" : [ "Christian Hansen <chansen@cpan.org>", "David Golden <dagolden@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.030, 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.088" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/Perl-Toolchain-Gang/HTTP-Tiny/issues" }, "homepage" : "https://github.com/Perl-Toolchain-Gang/HTTP-Tiny", "repository" : { "type" : "git", "url" : "https://github.com/Perl-Toolchain-Gang/HTTP-Tiny.git", "web" : "https://github.com/Perl-Toolchain-Gang/HTTP-Tiny" } }, "version" : "0.088", "x_authority" : "cpan:DAGOLDEN", "x_contributors" : [ "Alan Gardner <gardner@pythian.com>", "Alessandro Ghedini <al3xbio@gmail.com>", "A. Sinan Unur <nanis@cpan.org>", "Brad Gilbert <bgills@cpan.org>", "brian m. carlson <sandals@crustytoothpaste.net>", "Chris Nehren <apeiron@cpan.org>", "Chris Weyl <cweyl@alumni.drew.edu>", "Claes Jakobsson <claes@surfar.nu>", "Clinton Gormley <clint@traveljury.com>", "Craig A. Berry <craigberry@mac.com>", "Craig Berry <cberry@cpan.org>", "David Golden <xdg@xdg.me>", "David Mitchell <davem@iabyn.com>", "Dean Pearce <pearce@pythian.com>", "Edward Zborowski <ed@rubensteintech.com>", "Felipe Gasper <felipe@felipegasper.com>", "Graham Knop <haarg@haarg.org>", "Greg Kennedy <kennedy.greg@gmail.com>", "James E Keenan <jkeenan@cpan.org>", "James Raspass <jraspass@gmail.com>", "Jeremy Mates <jmates@cpan.org>", "Jess Robinson <castaway@desert-island.me.uk>", "Karen Etheridge <ether@cpan.org>", "Lukas Eklund <leklund@gmail.com>", "Martin J. Evans <mjegh@ntlworld.com>", "Martin-Louis Bright <mlbright@gmail.com>", "Matthew Horsfall <wolfsage@gmail.com>", "Michael R. Davis <mrdvt92@users.noreply.github.com>", "Mike Doherty <doherty@cpan.org>", "Nicolas Rochelemagne <rochelemagne@cpanel.net>", "Olaf Alders <olaf@wundersolutions.com>", "Olivier Mengué <dolmen@cpan.org>", "Petr Písař <ppisar@redhat.com>", "sanjay-cpu <snjkmr32@gmail.com>", "Serguei Trouchelle <stro@cpan.org>", "Shoichi Kaji <skaji@cpan.org>", "SkyMarshal <skymarshal1729@gmail.com>", "Sören Kornetzki <soeren.kornetzki@delti.com>", "Steve Grazzini <steve.grazzini@grantstreet.com>", "Stig Palmquist <git@stig.io>", "Syohei YOSHIDA <syohex@gmail.com>", "Tatsuhiko Miyagawa <miyagawa@bulknews.net>", "Tom Hukins <tom@eborcom.com>", "Tony Cook <tony@develop-help.com>", "Xavier Guimard <yadd@debian.org>" ], "x_generated_by_perl" : "v5.36.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/Types-Serialiser-1.01/install.json����������������������������0000444�����������������00000000660�15253012307�0021407 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"Types-Serialiser-1.01","name":"Types::Serialiser","provides":{"Types::Serialiser":{"version":1.01,"file":"Serialiser.pm"},"Types::Serialiser::BooleanBase":{"file":"Serialiser.pm","version":1.01},"JSON::PP::Boolean":{"file":"Serialiser.pm","version":1.01},"Types::Serialiser::Error":{"file":"Serialiser.pm","version":1.01}},"target":"Types::Serialiser","version":1.01,"pathname":"M/ML/MLEHMANN/Types-Serialiser-1.01.tar.gz"}��������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Types-Serialiser-1.01/MYMETA.json�����������������������������0000444�����������������00000001647�15253012307�0020743 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "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/YAML-Syck-1.34/install.json�����������������������������������0000444�����������������00000000555�15253012307�0017665 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"YAML-Syck-1.34","name":"YAML::Syck","target":"YAML::Syck","provides":{"JSON::Syck":{"version":1.34,"file":"lib/JSON/Syck.pm"},"YAML::Dumper::Syck":{"file":"lib/YAML/Dumper/Syck.pm"},"YAML::Loader::Syck":{"file":"lib/YAML/Loader/Syck.pm"},"YAML::Syck":{"version":1.34,"file":"lib/YAML/Syck.pm"}},"pathname":"T/TO/TODDR/YAML-Syck-1.34.tar.gz","version":1.34}���������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/YAML-Syck-1.34/MYMETA.json������������������������������������0000444�����������������00000002345�15253012307�0017212 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "Fast, lightweight YAML loader and dumper", "author" : [ "Todd Rinaldo <toddr@cpan.org>" ], "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/Try-Tiny-0.31/install.json������������������������������������0000444�����������������00000000303�15253012307�0017676 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"Try-Tiny-0.31","name":"Try::Tiny","target":"Try::Tiny","provides":{"Try::Tiny":{"file":"lib/Try/Tiny.pm","version":"0.31"}},"pathname":"E/ET/ETHER/Try-Tiny-0.31.tar.gz","version":"0.31"}�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Try-Tiny-0.31/MYMETA.json�������������������������������������0000444�����������������00000136423�15253012307�0017241 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "Minimal try/catch with proper preservation of $@", "author" : [ "יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>", "Jesse Luehrs <doy@tozt.net>" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010", "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Try-Tiny", "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::Author::ETHER" : "0.161", "Dist::Zilla::PluginBundle::Git::VersionManager" : "0.007" }, "requires" : { "Capture::Tiny" : "0.12", "Encode" : "0", "File::Spec" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Pod::Coverage::TrustPod" : "0", "Pod::Wordlist" : "0", "Sub::Name" : "0.08", "Sub::Util" : "0", "Test::CPAN::Changes" : "0.19", "Test::CPAN::Meta" : "0", "Test::EOL" : "0", "Test::Kwalitee" : "1.21", "Test::MinimumVersion" : "0", "Test::Mojibake" : "0", "Test::More" : "0.96", "Test::NoTabs" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Pod::No404s" : "0", "Test::Portability::Files" : "0", "Test::Spelling" : "0.12" } }, "runtime" : { "requires" : { "Carp" : "0", "Exporter" : "5.57", "constant" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" }, "suggests" : { "Sub::Name" : "0.08", "Sub::Util" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "Test::More" : "0", "if" : "0" }, "suggests" : { "CPAN::Meta::Check" : "0.011", "CPAN::Meta::Requirements" : "0", "Capture::Tiny" : "0.12" } }, "x_Dist_Zilla" : { "requires" : { "Dist::Zilla" : "5", "Dist::Zilla::Plugin::Authority" : "1.009", "Dist::Zilla::Plugin::AutoMetaResources" : "0", "Dist::Zilla::Plugin::AutoPrereqs" : "5.038", "Dist::Zilla::Plugin::Breaks" : "0", "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : "0.004", "Dist::Zilla::Plugin::CheckIssues" : "0", "Dist::Zilla::Plugin::CheckMetaResources" : "0", "Dist::Zilla::Plugin::CheckPrereqsIndexed" : "0.019", "Dist::Zilla::Plugin::CheckSelfDependency" : "0", "Dist::Zilla::Plugin::CheckStrictVersion" : "0", "Dist::Zilla::Plugin::ConfirmRelease" : "0", "Dist::Zilla::Plugin::CopyFilesFromRelease" : "0", "Dist::Zilla::Plugin::EnsureLatestPerl" : "0", "Dist::Zilla::Plugin::FileFinder::ByName" : "0", "Dist::Zilla::Plugin::FileFinder::Filter" : "0", "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : "0", "Dist::Zilla::Plugin::Git::Check" : "0", "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch" : "0.004", "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts" : "0", "Dist::Zilla::Plugin::Git::Commit" : "2.020", "Dist::Zilla::Plugin::Git::Contributors" : "0.029", "Dist::Zilla::Plugin::Git::Describe" : "0.004", "Dist::Zilla::Plugin::Git::GatherDir" : "2.016", "Dist::Zilla::Plugin::Git::Push" : "0", "Dist::Zilla::Plugin::Git::Remote::Check" : "0", "Dist::Zilla::Plugin::Git::Tag" : "0", "Dist::Zilla::Plugin::GitHub::Update" : "0.40", "Dist::Zilla::Plugin::GithubMeta" : "0.54", "Dist::Zilla::Plugin::InstallGuide" : "1.200005", "Dist::Zilla::Plugin::Keywords" : "0.004", "Dist::Zilla::Plugin::License" : "5.038", "Dist::Zilla::Plugin::MakeMaker" : "0", "Dist::Zilla::Plugin::Manifest" : "0", "Dist::Zilla::Plugin::MetaConfig" : "0", "Dist::Zilla::Plugin::MetaJSON" : "0", "Dist::Zilla::Plugin::MetaNoIndex" : "0", "Dist::Zilla::Plugin::MetaProvides::Package" : "1.15000002", "Dist::Zilla::Plugin::MetaTests" : "0", "Dist::Zilla::Plugin::MetaYAML" : "0", "Dist::Zilla::Plugin::MinimumPerl" : "1.006", "Dist::Zilla::Plugin::MojibakeTests" : "0.8", "Dist::Zilla::Plugin::NextRelease" : "5.033", "Dist::Zilla::Plugin::OnlyCorePrereqs" : "0", "Dist::Zilla::Plugin::PodCoverageTests" : "5.040", "Dist::Zilla::Plugin::PodSyntaxTests" : "5.040", "Dist::Zilla::Plugin::PodWeaver" : "4.008", "Dist::Zilla::Plugin::Prereqs" : "0", "Dist::Zilla::Plugin::Prereqs::AuthorDeps" : "0.006", "Dist::Zilla::Plugin::Prereqs::Soften" : "0", "Dist::Zilla::Plugin::PromptIfStale" : "0", "Dist::Zilla::Plugin::Readme" : "0", "Dist::Zilla::Plugin::ReadmeAnyFromPod" : "0.142180", "Dist::Zilla::Plugin::RewriteVersion::Transitional" : "0.006", "Dist::Zilla::Plugin::Run::AfterBuild" : "0.041", "Dist::Zilla::Plugin::Run::AfterRelease" : "0.038", "Dist::Zilla::Plugin::RunExtraTests" : "0.024", "Dist::Zilla::Plugin::StaticInstall" : "0.005", "Dist::Zilla::Plugin::Substitute" : "0", "Dist::Zilla::Plugin::Test::CPAN::Changes" : "0.012", "Dist::Zilla::Plugin::Test::ChangesHasContent" : "0", "Dist::Zilla::Plugin::Test::CheckBreaks" : "0.018", "Dist::Zilla::Plugin::Test::Compile" : "2.039", "Dist::Zilla::Plugin::Test::EOL" : "0.17", "Dist::Zilla::Plugin::Test::Kwalitee" : "2.10", "Dist::Zilla::Plugin::Test::MinimumVersion" : "2.000010", "Dist::Zilla::Plugin::Test::NoTabs" : "0.08", "Dist::Zilla::Plugin::Test::Pod::No404s" : "1.003", "Dist::Zilla::Plugin::Test::PodSpelling" : "2.006003", "Dist::Zilla::Plugin::Test::Portability" : "2.000007", "Dist::Zilla::Plugin::Test::ReportPrereqs" : "0.022", "Dist::Zilla::Plugin::TestRelease" : "0", "Dist::Zilla::Plugin::UploadToCPAN" : "0", "Dist::Zilla::Plugin::UseUnsafeInc" : "0", "Dist::Zilla::PluginBundle::Author::ETHER" : "0.136", "Dist::Zilla::PluginBundle::Git::VersionManager" : "0.007", "Software::License::MIT" : "0" } } }, "provides" : { "Try::Tiny" : { "file" : "lib/Try/Tiny.pm", "version" : "0.31" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-Try-Tiny@rt.cpan.org", "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Try-Tiny" }, "homepage" : "https://github.com/p5sagit/Try-Tiny", "repository" : { "type" : "git", "url" : "https://github.com/p5sagit/Try-Tiny.git", "web" : "https://github.com/p5sagit/Try-Tiny" } }, "version" : "0.31", "x_Dist_Zilla" : { "perl" : { "version" : "5.035006" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::FileFinder::Filter", "name" : "all_files_but_using_5.10_features", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "recommends" } }, "name" : "@Author::ETHER/pluginbundle version", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 0, "check_all_prereqs" : 0, "modules" : [ "Dist::Zilla::PluginBundle::Author::ETHER" ], "phase" : "build", "run_under_travis" : 0, "skip" : [] } }, "name" : "@Author::ETHER/stale modules, build", "version" : "0.057" }, { "class" : "Dist::Zilla::Plugin::FileFinder::ByName", "name" : "@Author::ETHER/Examples", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "CONTRIBUTING", "INSTALL", "LICENCE", "README.pod" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "@Author::ETHER/Git::GatherDir", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "@Author::ETHER/MetaYAML", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "@Author::ETHER/MetaJSON", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Readme", "name" : "@Author::ETHER/Readme", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "@Author::ETHER/Manifest", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "@Author::ETHER/License", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir", "config" : { "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : { "destination_filename" : "CONTRIBUTING", "dist" : "Dist-Zilla-PluginBundle-Author-ETHER", "encoding" : "UTF-8", "has_xs" : 0, "location" : "build", "source_filename" : "CONTRIBUTING" }, "Dist::Zilla::Role::RepoFileInjector" : { "allow_overwrite" : 1, "repo_root" : ".", "version" : "0.009" } }, "name" : "@Author::ETHER/generate CONTRIBUTING", "version" : "0.015" }, { "class" : "Dist::Zilla::Plugin::InstallGuide", "config" : { "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "@Author::ETHER/InstallGuide", "version" : "1.200014" }, { "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", "@Author::ETHER/Examples" ], "skips" : [], "switch" : [] } }, "name" : "@Author::ETHER/Test::Compile", "version" : "2.058" }, { "class" : "Dist::Zilla::Plugin::Test::NoTabs", "config" : { "Dist::Zilla::Plugin::Test::NoTabs" : { "filename" : "xt/author/no-tabs.t", "finder" : [ ":InstallModules", ":ExecFiles", "@Author::ETHER/Examples", ":TestFiles", ":ExtraTestFiles" ] } }, "name" : "@Author::ETHER/Test::NoTabs", "version" : "0.15" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":ExtraTestFiles", ":InstallModules", ":TestFiles", "@Author::ETHER/Examples" ], "trailing_whitespace" : 1 } }, "name" : "@Author::ETHER/Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::MetaTests", "name" : "@Author::ETHER/MetaTests", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes", "config" : { "Dist::Zilla::Plugin::Test::CPAN::Changes" : { "changelog" : "Changes" } }, "name" : "@Author::ETHER/Test::CPAN::Changes", "version" : "0.012" }, { "class" : "Dist::Zilla::Plugin::Test::ChangesHasContent", "name" : "@Author::ETHER/Test::ChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::Test::MinimumVersion", "config" : { "Dist::Zilla::Plugin::Test::MinimumVersion" : { "max_target_perl" : "5.006" } }, "name" : "@Author::ETHER/Test::MinimumVersion", "version" : "2.000010" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "@Author::ETHER/PodSyntaxTests", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::PodCoverageTests", "name" : "@Author::ETHER/PodCoverageTests", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Test::PodSpelling", "config" : { "Dist::Zilla::Plugin::Test::PodSpelling" : { "directories" : [ "examples", "lib", "script", "t", "xt" ], "spell_cmd" : "", "stopwords" : [ "irc" ], "wordlist" : "Pod::Wordlist" } }, "name" : "@Author::ETHER/Test::PodSpelling", "version" : "2.007005" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::No404s", "name" : "@Author::ETHER/Test::Pod::No404s", "version" : "1.004" }, { "class" : "Dist::Zilla::Plugin::Test::Kwalitee", "config" : { "Dist::Zilla::Plugin::Test::Kwalitee" : { "filename" : "xt/author/kwalitee.t", "skiptest" : [] } }, "name" : "@Author::ETHER/Test::Kwalitee", "version" : "2.12" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "@Author::ETHER/MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "@Author::ETHER/Test::ReportPrereqs", "version" : "0.028" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "config" : { "Dist::Zilla::Plugin::Test::Portability" : { "options" : "" } }, "name" : "@Author::ETHER/Test::Portability", "version" : "2.001000" }, { "class" : "Dist::Zilla::Plugin::Git::Describe", "name" : "@Author::ETHER/Git::Describe", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::PodWeaver", "config" : { "Dist::Zilla::Plugin::PodWeaver" : { "config_plugins" : [ "@Author::ETHER" ], "finder" : [ ":InstallModules", ":ExecFiles" ], "plugins" : [ { "class" : "Pod::Weaver::Plugin::EnsurePod5", "name" : "@Author::ETHER/EnsurePod5", "version" : "4.018" }, { "class" : "Pod::Weaver::Plugin::H1Nester", "name" : "@Author::ETHER/H1Nester", "version" : "4.018" }, { "class" : "Pod::Weaver::Plugin::SingleEncoding", "name" : "@Author::ETHER/SingleEncoding", "version" : "4.018" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@Author::ETHER/List", "version" : "4.018" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@Author::ETHER/Verbatim", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Author::ETHER/header", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Name", "name" : "@Author::ETHER/Name", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Version", "name" : "@Author::ETHER/Version", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Author::ETHER/prelude", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "SYNOPSIS", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "DESCRIPTION", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "OVERVIEW", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "ATTRIBUTES", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "METHODS", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "FUNCTIONS", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "TYPES", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Leftovers", "name" : "@Author::ETHER/Leftovers", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Author::ETHER/postlude", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::GenerateSection", "name" : "@Author::ETHER/generate SUPPORT", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::AllowOverride", "name" : "@Author::ETHER/allow override SUPPORT", "version" : "0.05" }, { "class" : "Pod::Weaver::Section::Authors", "name" : "@Author::ETHER/Authors", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::AllowOverride", "name" : "@Author::ETHER/allow override AUTHOR", "version" : "0.05" }, { "class" : "Pod::Weaver::Section::Contributors", "name" : "@Author::ETHER/Contributors", "version" : "0.009" }, { "class" : "Pod::Weaver::Section::Legal", "name" : "@Author::ETHER/Legal", "version" : "4.018" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@Author::ETHER/footer", "version" : "4.018" } ] } }, "name" : "@Author::ETHER/PodWeaver", "version" : "4.009" }, { "class" : "Dist::Zilla::Plugin::GithubMeta", "name" : "@Author::ETHER/GithubMeta", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::AutoMetaResources", "name" : "@Author::ETHER/AutoMetaResources", "version" : "1.21" }, { "class" : "Dist::Zilla::Plugin::Authority", "name" : "@Author::ETHER/Authority", "version" : "1.009" }, { "class" : "Dist::Zilla::Plugin::MetaNoIndex", "name" : "@Author::ETHER/MetaNoIndex", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Package", "config" : { "Dist::Zilla::Plugin::MetaProvides::Package" : { "finder" : [ ":InstallModules" ], "finder_objects" : [ { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.024" } ], "include_underscores" : 0 }, "Dist::Zilla::Role::MetaProvider::Provider" : { "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004", "inherit_missing" : 0, "inherit_version" : 0, "meta_noindex" : 1 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "@Author::ETHER/MetaProvides::Package", "version" : "2.004003" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "@Author::ETHER/MetaConfig", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Keywords", "config" : { "Dist::Zilla::Plugin::Keywords" : { "keywords" : [] } }, "name" : "@Author::ETHER/Keywords", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::UseUnsafeInc", "config" : { "Dist::Zilla::Plugin::UseUnsafeInc" : { "dot_in_INC" : 0 } }, "name" : "@Author::ETHER/UseUnsafeInc", "version" : "0.001" }, { "class" : "Dist::Zilla::Plugin::AutoPrereqs", "name" : "@Author::ETHER/AutoPrereqs", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Prereqs::AuthorDeps", "name" : "@Author::ETHER/Prereqs::AuthorDeps", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::MinimumPerl", "name" : "@Author::ETHER/MinimumPerl", "version" : "1.006" }, { "class" : "Dist::Zilla::Plugin::MakeMaker", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 9 } }, "name" : "@Author::ETHER/MakeMaker", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "git_version" : "2.31.1", "include_authors" : 0, "include_releaser" : 1, "order_by" : "commits", "paths" : [] } }, "name" : "@Author::ETHER/Git::Contributors", "version" : "0.036" }, { "class" : "Dist::Zilla::Plugin::StaticInstall", "config" : { "Dist::Zilla::Plugin::StaticInstall" : { "dry_run" : 1, "mode" : "auto" } }, "name" : "@Author::ETHER/StaticInstall", "version" : "0.012" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 9 } }, "name" : "@Author::ETHER/RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::CheckSelfDependency", "config" : { "Dist::Zilla::Plugin::CheckSelfDependency" : { "finder" : [ ":InstallModules" ] }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "@Author::ETHER/CheckSelfDependency", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::Run::AfterBuild", "config" : { "Dist::Zilla::Plugin::Run::Role::Runner" : { "fatal_errors" : 1, "quiet" : 1, "run" : [ "bash -c \"test -e .ackrc && grep -q -- '--ignore-dir=.latest' .ackrc || echo '--ignore-dir=.latest' >> .ackrc; if [[ `dirname '%d'` != .build ]]; then test -e .ackrc && grep -q -- '--ignore-dir=%d' .ackrc || echo '--ignore-dir=%d' >> .ackrc; fi\"" ], "version" : "0.048" } }, "name" : "@Author::ETHER/.ackrc", "version" : "0.048" }, { "class" : "Dist::Zilla::Plugin::Run::AfterBuild", "config" : { "Dist::Zilla::Plugin::Run::Role::Runner" : { "eval" : [ "if ('%d' =~ /^%n-[.[:xdigit:]]+$/) { unlink '.latest'; symlink '%d', '.latest'; }" ], "fatal_errors" : 0, "quiet" : 1, "version" : "0.048" } }, "name" : "@Author::ETHER/.latest", "version" : "0.048" }, { "class" : "Dist::Zilla::Plugin::CheckStrictVersion", "name" : "@Author::ETHER/CheckStrictVersion", "version" : "0.001" }, { "class" : "Dist::Zilla::Plugin::CheckMetaResources", "name" : "@Author::ETHER/CheckMetaResources", "version" : "0.001" }, { "class" : "Dist::Zilla::Plugin::EnsureLatestPerl", "config" : { "Dist::Zilla::Plugin::EnsureLatestPerl" : { "Module::CoreList" : "5.20211120" } }, "name" : "@Author::ETHER/EnsureLatestPerl", "version" : "0.008" }, { "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::ETHER/stale modules, release", "version" : "0.057" }, { "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.31.1", "repo_root" : "." } }, "name" : "@Author::ETHER/initial check", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts", "config" : { "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.31.1", "repo_root" : "." } }, "name" : "@Author::ETHER/Git::CheckFor::MergeConflicts", "version" : "0.014" }, { "class" : "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch", "config" : { "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.31.1", "repo_root" : "." } }, "name" : "@Author::ETHER/Git::CheckFor::CorrectBranch", "version" : "0.014" }, { "class" : "Dist::Zilla::Plugin::Git::Remote::Check", "name" : "@Author::ETHER/Git::Remote::Check", "version" : "0.1.2" }, { "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed", "name" : "@Author::ETHER/CheckPrereqsIndexed", "version" : "0.021" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "@Author::ETHER/TestRelease", "version" : "6.024" }, { "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.31.1", "repo_root" : "." } }, "name" : "@Author::ETHER/after tests", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::CheckIssues", "name" : "@Author::ETHER/CheckIssues", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "@Author::ETHER/UploadToCPAN", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "CONTRIBUTING", "INSTALL", "LICENCE", "LICENSE", "ppport.h" ], "match" : [] } }, "name" : "@Author::ETHER/copy generated files", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "@Author::ETHER/ReadmeAnyFromPod", "version" : "0.163250" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "recommends" } }, "name" : "@Author::ETHER/@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" : 1, "skip_version_provider" : 0 }, "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {} }, "name" : "@Author::ETHER/@Git::VersionManager/RewriteVersion::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Update", "name" : "@Author::ETHER/@Git::VersionManager/MetaProvides::Update", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease", "config" : { "Dist::Zilla::Plugin::CopyFilesFromRelease" : { "filename" : [ "Changes" ], "match" : [] } }, "name" : "@Author::ETHER/@Git::VersionManager/CopyFilesFromRelease", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [ "." ], "commit_msg" : "%N-%v%t%n%n%c", "signoff" : 0 }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "CONTRIBUTING", "Changes", "INSTALL", "LICENCE", "README.pod" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.31.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::ETHER/@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" : "v0.31", "tag_format" : "v%V", "tag_message" : "v%v%t" }, "Dist::Zilla::Role::Git::Repo" : { "git_version" : "2.31.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::ETHER/@Git::VersionManager/Git::Tag", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":InstallModules" ], "global" : 1, "munge_makefile_pl" : 1 }, "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {} }, "name" : "@Author::ETHER/@Git::VersionManager/BumpVersionAfterRelease::Transitional", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@Author::ETHER/@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.31.1", "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@Author::ETHER/@Git::VersionManager/post-release commit", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "x_Dist_Zilla", "type" : "requires" } }, "name" : "@Author::ETHER/@Git::VersionManager/prereqs for @Git::VersionManager", "version" : "6.024" }, { "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.31.1", "repo_root" : "." } }, "name" : "@Author::ETHER/Git::Push", "version" : "2.048" }, { "class" : "Dist::Zilla::Plugin::GitHub::Update", "config" : { "Dist::Zilla::Plugin::GitHub::Update" : { "metacpan" : 1 } }, "name" : "@Author::ETHER/GitHub::Update", "version" : "0.48" }, { "class" : "Dist::Zilla::Plugin::Run::AfterRelease", "config" : { "Dist::Zilla::Plugin::Run::Role::Runner" : { "fatal_errors" : 0, "quiet" : 0, "run" : [ "REDACTED" ], "version" : "0.048" } }, "name" : "@Author::ETHER/install release", "version" : "0.048" }, { "class" : "Dist::Zilla::Plugin::Run::AfterRelease", "config" : { "Dist::Zilla::Plugin::Run::Role::Runner" : { "eval" : [ "print \"release complete!\\xa\"" ], "fatal_errors" : 1, "quiet" : 1, "version" : "0.048" } }, "name" : "@Author::ETHER/release complete", "version" : "0.048" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "@Author::ETHER/ConfirmRelease", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "x_Dist_Zilla", "type" : "requires" } }, "name" : "@Author::ETHER/prereqs for @Author::ETHER", "version" : "6.024" }, { "class" : "Dist::Zilla::Plugin::Substitute", "name" : "Substitute", "version" : "0.006" }, { "class" : "Dist::Zilla::Plugin::Prereqs::Soften", "config" : { "Dist::Zilla::Plugin::Prereqs::Soften" : { "copy_to" : [ "develop.requires" ], "modules" : [ "Capture::Tiny", "Sub::Name", "Sub::Util" ], "modules_from_features" : null, "to_relationship" : "suggests" } }, "name" : "Prereqs::Soften", "version" : "0.006003" }, { "class" : "Dist::Zilla::Plugin::OnlyCorePrereqs", "config" : { "Dist::Zilla::Plugin::OnlyCorePrereqs" : { "also_disallow" : [], "check_dual_life_versions" : "0", "deprecated_ok" : 0, "phases" : [ "configure", "build", "runtime", "test" ], "skips" : [], "starting_version" : "to be determined from perl prereq" } }, "name" : "OnlyCorePrereqs", "version" : "0.024" }, { "class" : "Dist::Zilla::Plugin::Breaks", "name" : "Breaks", "version" : "0.004" }, { "class" : "Dist::Zilla::Plugin::Test::CheckBreaks", "config" : { "Dist::Zilla::Plugin::Test::CheckBreaks" : { "conflicts_module" : [], "no_forced_deps" : 1 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000037", "version" : "0.006" } }, "name" : "Test::CheckBreaks", "version" : "0.019" }, { "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::VerifyPhases", "name" : "@Author::ETHER/PHASE VERIFICATION", "version" : "0.016" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.024" } }, "x_authority" : "cpan:NUFFIN", "x_breaks" : { "Try::Tiny::Except" : "<= 0.01" }, "x_contributors" : [ "Karen Etheridge <ether@cpan.org>", "Peter Rabbitson <ribasushi@cpan.org>", "Ricardo Signes <rjbs@cpan.org>", "Mark Fowler <mark@twoshortplanks.com>", "Graham Knop <haarg@haarg.org>", "Aristotle Pagaltzis <pagaltzis@gmx.de>", "Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>", "Lukas Mai <l.mai@web.de>", "Alex <alex@koban.(none)>", "anaxagoras <walkeraj@gmail.com>", "Andrew Yates <ayates@haddock.local>", "awalker <awalker@sourcefire.com>", "chromatic <chromatic@wgz.org>", "cm-perl <cm-perl@users.noreply.github.com>", "David Lowe <davidl@lokku.com>", "Glenn Fowler <cebjyre@cpan.org>", "Hans Dieter Pearcey <hdp@weftsoar.net>", "Jens Berthold <jens@jebecs.de>", "Jonathan Yu <JAWNSY@cpan.org>", "Marc Mims <marc@questright.com>", "Mark Stosberg <mark@stosberg.com>", "Pali <pali@cpan.org>", "Paul Howarth <paul@city-fan.org>", "Rudolf Leermakers <rudolf@hatsuseno.org>" ], "x_generated_by_perl" : "v5.35.6", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "MIT", "x_use_unsafe_inc" : 0 } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/CPAN-2.36/install.json����������������������������������������0000444�����������������00000006750�15253012307�0016743 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"name":"CPAN","dist":"CPAN-2.36","pathname":"A/AN/ANDK/CPAN-2.36.tar.gz","version":2.36,"target":"CPAN","provides":{"CPAN::Index":{"version":2.29,"file":"lib/CPAN/Index.pm"},"CPAN::URL":{"version":5.5,"file":"lib/CPAN/URL.pm"},"CPAN::HandleConfig":{"file":"lib/CPAN/HandleConfig.pm","version":5.5012},"CPAN::Admin":{"file":"lib/CPAN/Admin.pm","version":5.501},"CPAN::Nox":{"file":"lib/CPAN/Nox.pm","version":5.5001},"CPAN::Distroprefs::Result::Success":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Shell":{"version":5.5009,"file":"lib/CPAN/Shell.pm"},"CPAN::FTP::netrc":{"file":"lib/CPAN/FTP/netrc.pm","version":1.01},"CPAN::Bundle":{"file":"lib/CPAN/Bundle.pm","version":5.5005},"CPAN::HTTP::Credentials":{"file":"lib/CPAN/HTTP/Credentials.pm","version":1.9601},"CPAN::Version":{"file":"lib/CPAN/Version.pm","version":5.5003},"CPAN::Distroprefs::Result::Warning":{"version":6.0001,"file":"lib/CPAN/Distroprefs.pm"},"CPAN::Debug":{"version":5.5001,"file":"lib/CPAN/Debug.pm"},"CPAN::Author":{"version":5.5002,"file":"lib/CPAN/Author.pm"},"CPAN::CacheMgr":{"version":5.5002,"file":"lib/CPAN/CacheMgr.pm"},"CPAN::Exception::blocked_urllist":{"version":1.001,"file":"lib/CPAN/Exception/blocked_urllist.pm"},"CPAN::Plugin::Specfile":{"file":"lib/CPAN/Plugin/Specfile.pm","version":0.02},"CPAN::HTTP::Client":{"file":"lib/CPAN/HTTP/Client.pm","version":1.9602},"CPAN::Distroprefs::Result":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Distroprefs::Result::Error":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Kwalify":{"version":"5.50","file":"lib/CPAN/Kwalify.pm"},"CPAN::Exception::RecursiveDependency::na":{"file":"lib/CPAN/Exception/RecursiveDependency.pm","version":5.5001},"CPAN::Tarzip":{"version":5.5013,"file":"lib/CPAN/Tarzip.pm"},"App::Cpan":{"file":"lib/App/Cpan.pm","version":1.678},"CPAN::Module":{"version":5.5003,"file":"lib/CPAN/Module.pm"},"CPAN::Exception::yaml_not_installed":{"version":5.5,"file":"lib/CPAN/Exception/yaml_not_installed.pm"},"CPAN::Distroprefs::Pref":{"version":6.0001,"file":"lib/CPAN/Distroprefs.pm"},"CPAN::FirstTime":{"file":"lib/CPAN/FirstTime.pm","version":5.5317},"CPAN::Distroprefs":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::DeferredCode":{"file":"lib/CPAN/DeferredCode.pm","version":"5.50"},"CPAN::Prompt":{"version":5.5,"file":"lib/CPAN/Prompt.pm"},"CPAN::Mirrored::By":{"version":2.27,"file":"lib/CPAN/Mirrors.pm"},"CPAN::Distroprefs::Result::Fatal":{"version":6.0001,"file":"lib/CPAN/Distroprefs.pm"},"CPAN::Complete":{"version":5.5001,"file":"lib/CPAN/Complete.pm"},"CPAN::Distrostatus":{"file":"lib/CPAN/Distrostatus.pm","version":5.5},"CPAN":{"file":"lib/CPAN.pm","version":2.36},"CPAN::Plugin":{"version":0.97,"file":"lib/CPAN/Plugin.pm"},"CPAN::Mirrors":{"file":"lib/CPAN/Mirrors.pm","version":2.27},"CPAN::Exception::yaml_process_error":{"file":"lib/CPAN/Exception/yaml_process_error.pm","version":5.5},"CPAN::Distribution":{"file":"lib/CPAN/Distribution.pm","version":2.34},"CPAN::Eval":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001},"CPAN::Queue":{"file":"lib/CPAN/Queue.pm","version":5.5003},"CPAN::LWP::UserAgent":{"version":1.9601,"file":"lib/CPAN/LWP/UserAgent.pm"},"CPAN::FTP":{"file":"lib/CPAN/FTP.pm","version":5.5016},"CPAN::Exception::RecursiveDependency":{"file":"lib/CPAN/Exception/RecursiveDependency.pm","version":5.5001},"CPAN::Queue::Item":{"file":"lib/CPAN/Queue.pm","version":5.5003},"CPAN::InfoObj":{"file":"lib/CPAN/InfoObj.pm","version":5.5},"CPAN::Distroprefs::Iterator":{"file":"lib/CPAN/Distroprefs.pm","version":6.0001}}}������������������������perl5/x86_64-linux-thread-multi/.meta/CPAN-2.36/MYMETA.json�����������������������������������������0000444�����������������00000004647�15253012307�0016274 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "query, download and build perl modules from CPAN sites", "author" : [ "Andreas Koenig <andreas.koenig.gmwojprw@franz.ak.mind.de>" ], "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.005", "IO::Compress::Base" : "0", "IO::Zlib" : "0", "JSON::PP" : "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.36", "x_serialization_backend" : "JSON::PP version 2.97001" } �����������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/version-0.9930/install.json�����������������������������������0000444�����������������00000000606�15253012307�0020053 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"version-0.9930","name":"version","provides":{"version::vpp":{"version":"0.9930","file":"vperl/vpp.pm"},"version":{"file":"lib/version.pm","version":"0.9930"},"version::vxs":{"file":"vutil/lib/version/vxs.pm","version":"0.9930"},"version::regex":{"file":"lib/version/regex.pm","version":"0.9930"}},"target":"version","version":"0.9930","pathname":"L/LE/LEONT/version-0.9930.tar.gz"}��������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/version-0.9930/MYMETA.json������������������������������������0000444�����������������00000002712�15253012307�0017401 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "Structured version objects", "author" : [ "John Peacock <jpeacock@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.70, 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.9930", "x_serialization_backend" : "JSON::PP version 2.97001" } ������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Canary-Stability-2013/install.json����������������������������0000444�����������������00000000347�15253012307�0021372 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"name":"Canary::Stability","dist":"Canary-Stability-2013","pathname":"M/ML/MLEHMANN/Canary-Stability-2013.tar.gz","version":2013,"target":"Canary::Stability","provides":{"Canary::Stability":{"version":2013,"file":"Stability.pm"}}}�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/Canary-Stability-2013/MYMETA.json�����������������������������0000444�����������������00000001435�15253012307�0020717 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "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/JSON-XS-4.03/install.json�������������������������������������0000444�����������������00000000263�15253012307�0017310 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"dist":"JSON-XS-4.03","name":"JSON::XS","provides":{"JSON::XS":{"file":"XS.pm","version":4.03}},"target":"JSON::XS","version":4.03,"pathname":"M/ML/MLEHMANN/JSON-XS-4.03.tar.gz"}���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/JSON-XS-4.03/MYMETA.json��������������������������������������0000444�����������������00000001757�15253012307�0016647 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "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/common-sense-3.75/install.json��������������������������������0000444�����������������00000000322�15253012307�0020616 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"name":"common::sense","dist":"common-sense-3.75","pathname":"M/ML/MLEHMANN/common-sense-3.75.tar.gz","version":3.75,"target":"common::sense","provides":{"common::sense":{"version":3.75,"file":"sense.pm.PL"}}}��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/common-sense-3.75/MYMETA.json���������������������������������0000444�����������������00000001477�15253012307�0020160 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "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/local-lib-2.000029/install.json�������������������������������0000444�����������������00000000407�15253012307�0020353 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"provides":{"local::lib":{"version":2.000029,"file":"lib/local/lib.pm"},"lib::core::only":{"file":"lib/lib/core/only.pm"}},"target":"local::lib","version":2.000029,"pathname":"H/HA/HAARG/local-lib-2.000029.tar.gz","dist":"local-lib-2.000029","name":"local::lib"}���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/local-lib-2.000029/MYMETA.json��������������������������������0000444�����������������00000003367�15253012307�0017711 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "create and use a local lib/ for perl modules with PERL5LIB", "author" : [ "mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>" ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "local-lib", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : {} }, "configure" : { "requires" : {} }, "develop" : { "requires" : { "Capture::Tiny" : "0", "Module::Build" : "0.36", "Test::CPAN::Changes" : "0", "Test::EOL" : "0", "Test::More" : "0.8101", "Test::NoTabs" : "0", "Test::Pod" : "0" } }, "runtime" : { "requires" : { "perl" : "5.006" } }, "test" : { "requires" : { "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-local-lib@rt.cpan.org", "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=local-lib" }, "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "git://github.com/Perl-Toolchain-Gang/local-lib", "web" : "https://github.com/Perl-Toolchain-Gang/local-lib" }, "x_IRC" : "irc://irc.perl.org/#local-lib" }, "version" : "2.000029", "x_serialization_backend" : "JSON::PP version 2.97001" } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/CPAN-Meta-Requirements-2.143/install.json���������������������0000444�����������������00000000600�15253012307�0022353 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"version":"2.143","pathname":"R/RJ/RJBS/CPAN-Meta-Requirements-2.143.tar.gz","provides":{"CPAN::Meta::Requirements::Range":{"file":"lib/CPAN/Meta/Requirements/Range.pm","version":"2.143"},"CPAN::Meta::Requirements":{"version":"2.143","file":"lib/CPAN/Meta/Requirements.pm"}},"target":"CPAN::Meta::Requirements","name":"CPAN::Meta::Requirements","dist":"CPAN-Meta-Requirements-2.143"}��������������������������������������������������������������������������������������������������������������������������������perl5/x86_64-linux-thread-multi/.meta/CPAN-Meta-Requirements-2.143/MYMETA.json����������������������0000444�����������������00000014576�15253012307�0021722 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "abstract" : "a set of version requirements for a CPAN dist", "author" : [ "David Golden <dagolden@cpan.org>", "Ricardo Signes <rjbs@cpan.org>" ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.030, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "CPAN-Meta-Requirements", "no_index" : { "directory" : [ "corpus", "examples", "t", "xt" ], "package" : [ "DB" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.17" } }, "develop" : { "requires" : { "Dist::Zilla" : "5", "Dist::Zilla::Plugin::Authority" : "0", "Dist::Zilla::Plugin::AutoPrereqs" : "0", "Dist::Zilla::Plugin::BumpVersionAfterRelease" : "0", "Dist::Zilla::Plugin::CPANFile" : "0", "Dist::Zilla::Plugin::CheckChangesHasContent" : "0", "Dist::Zilla::Plugin::CheckMetaResources" : "0", "Dist::Zilla::Plugin::CheckPrereqsIndexed" : "0", "Dist::Zilla::Plugin::ConfirmRelease" : "0", "Dist::Zilla::Plugin::CopyFilesFromBuild::Filtered" : "0", "Dist::Zilla::Plugin::ExecDir" : "0", "Dist::Zilla::Plugin::Git::Check" : "0", "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch" : "0", "Dist::Zilla::Plugin::Git::Commit" : "0", "Dist::Zilla::Plugin::Git::Contributors" : "0", "Dist::Zilla::Plugin::Git::GatherDir" : "0", "Dist::Zilla::Plugin::Git::Push" : "0", "Dist::Zilla::Plugin::Git::Tag" : "0", "Dist::Zilla::Plugin::GithubMeta" : "0", "Dist::Zilla::Plugin::InsertCopyright" : "0", "Dist::Zilla::Plugin::License" : "0", "Dist::Zilla::Plugin::MakeMaker" : "0", "Dist::Zilla::Plugin::MakeMaker::Highlander" : "0.003", "Dist::Zilla::Plugin::Manifest" : "0", "Dist::Zilla::Plugin::ManifestSkip" : "0", "Dist::Zilla::Plugin::MetaJSON" : "0", "Dist::Zilla::Plugin::MetaNoIndex" : "0", "Dist::Zilla::Plugin::MetaProvides::Package" : "0", "Dist::Zilla::Plugin::MetaTests" : "0", "Dist::Zilla::Plugin::MetaYAML" : "0", "Dist::Zilla::Plugin::MinimumPerl" : "0", "Dist::Zilla::Plugin::NextRelease" : "0", "Dist::Zilla::Plugin::OnlyCorePrereqs" : "0.014", "Dist::Zilla::Plugin::Pod2Readme" : "0", "Dist::Zilla::Plugin::PodCoverageTests" : "0", "Dist::Zilla::Plugin::PodSyntaxTests" : "0", "Dist::Zilla::Plugin::Prereqs" : "0", "Dist::Zilla::Plugin::Prereqs::AuthorDeps" : "0", "Dist::Zilla::Plugin::PromptIfStale" : "0", "Dist::Zilla::Plugin::PruneCruft" : "0", "Dist::Zilla::Plugin::RewriteVersion" : "0", "Dist::Zilla::Plugin::RunExtraTests" : "0", "Dist::Zilla::Plugin::ShareDir" : "0", "Dist::Zilla::Plugin::SurgicalPodWeaver" : "0", "Dist::Zilla::Plugin::Test::Compile" : "0", "Dist::Zilla::Plugin::Test::MinimumVersion" : "0", "Dist::Zilla::Plugin::Test::Perl::Critic" : "0", "Dist::Zilla::Plugin::Test::PodSpelling" : "0", "Dist::Zilla::Plugin::Test::Portability" : "0", "Dist::Zilla::Plugin::Test::ReportPrereqs" : "0", "Dist::Zilla::Plugin::Test::Version" : "0", "Dist::Zilla::Plugin::TestRelease" : "0", "Dist::Zilla::Plugin::UploadToCPAN" : "0", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Pod::Coverage::TrustPod" : "0", "Pod::Weaver::PluginBundle::DAGOLDEN" : "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" } }, "runtime" : { "requires" : { "B" : "0", "Carp" : "0", "perl" : "5.010000", "strict" : "0", "version" : "0.88", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "Test::More" : "0.88", "version" : "0.88" } } }, "provides" : { "CPAN::Meta::Requirements" : { "file" : "lib/CPAN/Meta/Requirements.pm", "version" : "2.143" }, "CPAN::Meta::Requirements::Range" : { "file" : "lib/CPAN/Meta/Requirements/Range.pm", "version" : "2.143" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements/issues" }, "homepage" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements", "repository" : { "type" : "git", "url" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git", "web" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements" } }, "version" : "2.143", "x_authority" : "cpan:DAGOLDEN", "x_contributors" : [ "Ed J <mohawk2@users.noreply.github.com>", "Graham Knop <haarg@haarg.org>", "Karen Etheridge <ether@cpan.org>", "Leon Timmermans <fawaka@gmail.com>", "Paul Howarth <paul@city-fan.org>", "Ricardo Signes <rjbs@semiotic.systems>", "robario <webmaster@robario.com>", "Tatsuhiko Miyagawa <miyagawa@bulknews.net>", "Tatsuhiko Miyagawa <miyagawa@gmail.com>" ], "x_generated_by_perl" : "v5.37.10", "x_serialization_backend" : "JSON::PP version 2.97001", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } ����������������������������������������������������������������������������������������������������������������������������������perl5/local/lib.pm����������������������������������������������������������������������������������0000444�����������������00000121117�15253012307�0007770 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package local::lib; use 5.006; BEGIN { if ($ENV{RELEASE_TESTING}) { require strict; strict->import; require warnings; warnings->import; } } use Config (); our $VERSION = '2.000029'; $VERSION =~ tr/_//d; BEGIN { *_WIN32 = ($^O eq 'MSWin32' || $^O eq 'NetWare' || $^O eq 'symbian') ? sub(){1} : sub(){0}; # punt on these systems *_USE_FSPEC = ($^O eq 'MacOS' || $^O eq 'VMS' || $INC{'File/Spec.pm'}) ? sub(){1} : sub(){0}; } my $_archname = $Config::Config{archname}; my $_version = $Config::Config{version}; my @_inc_version_list = reverse split / /, $Config::Config{inc_version_list}; my $_path_sep = $Config::Config{path_sep}; our $_DIR_JOIN = _WIN32 ? '\\' : '/'; our $_DIR_SPLIT = (_WIN32 || $^O eq 'cygwin') ? qr{[\\/]} : qr{/}; our $_ROOT = _WIN32 ? do { my $UNC = qr{[\\/]{2}[^\\/]+[\\/][^\\/]+}; qr{^(?:$UNC|[A-Za-z]:|)$_DIR_SPLIT}; } : qr{^/}; our $_PERL; sub _perl { if (!$_PERL) { # untaint and validate ($_PERL, my $exe) = $^X =~ /((?:.*$_DIR_SPLIT)?(.+))/; $_PERL = 'perl' if $exe !~ /perl/; if (_is_abs($_PERL)) { } elsif (-x $Config::Config{perlpath}) { $_PERL = $Config::Config{perlpath}; } elsif ($_PERL =~ $_DIR_SPLIT && -x $_PERL) { $_PERL = _rel2abs($_PERL); } else { ($_PERL) = map { /(.*)/ } grep { -x $_ } map { ($_, _WIN32 ? ("$_.exe") : ()) } map { join($_DIR_JOIN, $_, $_PERL) } split /\Q$_path_sep\E/, $ENV{PATH}; } } $_PERL; } sub _cwd { if (my $cwd = defined &Cwd::sys_cwd ? \&Cwd::sys_cwd : defined &Cwd::cwd ? \&Cwd::cwd : undef ) { no warnings 'redefine'; *_cwd = $cwd; goto &$cwd; } my $drive = shift; return Win32::GetCwd() if _WIN32 && defined &Win32::GetCwd && !$drive; local @ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}; delete @ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}; my $cmd = $drive ? "eval { Cwd::getdcwd(q($drive)) }" : 'getcwd'; my $perl = _perl; my $cwd = `"$perl" -MCwd -le "print $cmd"`; chomp $cwd; if (!length $cwd && $drive) { $cwd = $drive; } $cwd =~ s/$_DIR_SPLIT?$/$_DIR_JOIN/; $cwd; } sub _catdir { if (_USE_FSPEC) { require File::Spec; File::Spec->catdir(@_); } else { my $dir = join($_DIR_JOIN, @_); $dir =~ s{($_DIR_SPLIT)(?:\.?$_DIR_SPLIT)+}{$1}g; $dir; } } sub _is_abs { if (_USE_FSPEC) { require File::Spec; File::Spec->file_name_is_absolute($_[0]); } else { $_[0] =~ $_ROOT; } } sub _rel2abs { my ($dir, $base) = @_; return $dir if _is_abs($dir); $base = _WIN32 && $dir =~ s/^([A-Za-z]:)// ? _cwd("$1") : $base ? _rel2abs($base) : _cwd; return _catdir($base, $dir); } our $_DEVNULL; sub _devnull { return $_DEVNULL ||= _USE_FSPEC ? (require File::Spec, File::Spec->devnull) : _WIN32 ? 'nul' : $^O eq 'os2' ? '/dev/nul' : '/dev/null'; } sub import { my ($class, @args) = @_; if ($0 eq '-') { push @args, @ARGV; require Cwd; } my @steps; my %opts; my %attr; my $shelltype; while (@args) { my $arg = shift @args; # check for lethal dash first to stop processing before causing problems # the fancy dash is U+2212 or \xE2\x88\x92 if ($arg =~ /\xE2\x88\x92/) { die <<'DEATH'; WHOA THERE! It looks like you've got some fancy dashes in your commandline! These are *not* the traditional -- dashes that software recognizes. You probably got these by copy-pasting from the perldoc for this module as rendered by a UTF8-capable formatter. This most typically happens on an OS X terminal, but can happen elsewhere too. Please try again after replacing the dashes with normal minus signs. DEATH } elsif ($arg eq '--self-contained') { die <<'DEATH'; FATAL: The local::lib --self-contained flag has never worked reliably and the original author, Mark Stosberg, was unable or unwilling to maintain it. As such, this flag has been removed from the local::lib codebase in order to prevent misunderstandings and potentially broken builds. The local::lib authors recommend that you look at the lib::core::only module shipped with this distribution in order to create a more robust environment that is equivalent to what --self-contained provided (although quite possibly not what you originally thought it provided due to the poor quality of the documentation, for which we apologise). DEATH } elsif( $arg =~ /^--deactivate(?:=(.*))?$/ ) { my $path = defined $1 ? $1 : shift @args; push @steps, ['deactivate', $path]; } elsif ( $arg eq '--deactivate-all' ) { push @steps, ['deactivate_all']; } elsif ( $arg =~ /^--shelltype(?:=(.*))?$/ ) { $shelltype = defined $1 ? $1 : shift @args; } elsif ( $arg eq '--no-create' ) { $opts{no_create} = 1; } elsif ( $arg eq '--quiet' ) { $attr{quiet} = 1; } elsif ( $arg eq '--always' ) { $attr{always} = 1; } elsif ( $arg =~ /^--/ ) { die "Unknown import argument: $arg"; } else { push @steps, ['activate', $arg, \%opts]; } } if (!@steps) { push @steps, ['activate', undef, \%opts]; } my $self = $class->new(%attr); for (@steps) { my ($method, @args) = @$_; $self = $self->$method(@args); } if ($0 eq '-') { print $self->environment_vars_string($shelltype); exit 0; } else { $self->setup_local_lib; } } sub new { my $class = shift; bless {@_}, $class; } sub clone { my $self = shift; bless {%$self, @_}, ref $self; } sub inc { $_[0]->{inc} ||= \@INC } sub libs { $_[0]->{libs} ||= [ \'PERL5LIB' ] } sub bins { $_[0]->{bins} ||= [ \'PATH' ] } sub roots { $_[0]->{roots} ||= [ \'PERL_LOCAL_LIB_ROOT' ] } sub extra { $_[0]->{extra} ||= {} } sub quiet { $_[0]->{quiet} } sub _as_list { my $list = shift; grep length, map { !(ref $_ && ref $_ eq 'SCALAR') ? $_ : ( defined $ENV{$$_} ? split(/\Q$_path_sep/, $ENV{$$_}) : () ) } ref $list ? @$list : $list; } sub _remove_from { my ($list, @remove) = @_; return @$list if !@remove; my %remove = map { $_ => 1 } @remove; grep !$remove{$_}, _as_list($list); } my @_lib_subdirs = ( [$_version, $_archname], [$_version], [$_archname], (map [$_], @_inc_version_list), [], ); sub install_base_bin_path { my ($class, $path) = @_; return _catdir($path, 'bin'); } sub install_base_perl_path { my ($class, $path) = @_; return _catdir($path, 'lib', 'perl5'); } sub install_base_arch_path { my ($class, $path) = @_; _catdir($class->install_base_perl_path($path), $_archname); } sub lib_paths_for { my ($class, $path) = @_; my $base = $class->install_base_perl_path($path); return map { _catdir($base, @$_) } @_lib_subdirs; } sub _mm_escape_path { my $path = shift; $path =~ s/\\/\\\\/g; if ($path =~ s/ /\\ /g) { $path = qq{"$path"}; } return $path; } sub _mb_escape_path { my $path = shift; $path =~ s/\\/\\\\/g; return qq{"$path"}; } sub installer_options_for { my ($class, $path) = @_; return ( PERL_MM_OPT => defined $path ? "INSTALL_BASE="._mm_escape_path($path) : undef, PERL_MB_OPT => defined $path ? "--install_base "._mb_escape_path($path) : undef, ); } sub active_paths { my ($self) = @_; $self = ref $self ? $self : $self->new; return grep { # screen out entries that aren't actually reflected in @INC my $active_ll = $self->install_base_perl_path($_); grep { $_ eq $active_ll } @{$self->inc}; } _as_list($self->roots); } sub deactivate { my ($self, $path) = @_; $self = $self->new unless ref $self; $path = $self->resolve_path($path); $path = $self->normalize_path($path); my @active_lls = $self->active_paths; if (!grep { $_ eq $path } @active_lls) { warn "Tried to deactivate inactive local::lib '$path'\n"; return $self; } my %args = ( bins => [ _remove_from($self->bins, $self->install_base_bin_path($path)) ], libs => [ _remove_from($self->libs, $self->install_base_perl_path($path)) ], inc => [ _remove_from($self->inc, $self->lib_paths_for($path)) ], roots => [ _remove_from($self->roots, $path) ], ); $args{extra} = { $self->installer_options_for($args{roots}[0]) }; $self->clone(%args); } sub deactivate_all { my ($self) = @_; $self = $self->new unless ref $self; my @active_lls = $self->active_paths; my %args; if (@active_lls) { %args = ( bins => [ _remove_from($self->bins, map $self->install_base_bin_path($_), @active_lls) ], libs => [ _remove_from($self->libs, map $self->install_base_perl_path($_), @active_lls) ], inc => [ _remove_from($self->inc, map $self->lib_paths_for($_), @active_lls) ], roots => [ _remove_from($self->roots, @active_lls) ], ); } $args{extra} = { $self->installer_options_for(undef) }; $self->clone(%args); } sub activate { my ($self, $path, $opts) = @_; $opts ||= {}; $self = $self->new unless ref $self; $path = $self->resolve_path($path); $self->ensure_dir_structure_for($path, { quiet => $self->quiet }) unless $opts->{no_create}; $path = $self->normalize_path($path); my @active_lls = $self->active_paths; if (grep { $_ eq $path } @active_lls[1 .. $#active_lls]) { $self = $self->deactivate($path); } my %args; if ($opts->{always} || !@active_lls || $active_lls[0] ne $path) { %args = ( bins => [ $self->install_base_bin_path($path), @{$self->bins} ], libs => [ $self->install_base_perl_path($path), @{$self->libs} ], inc => [ $self->lib_paths_for($path), @{$self->inc} ], roots => [ $path, @{$self->roots} ], ); } $args{extra} = { $self->installer_options_for($path) }; $self->clone(%args); } sub normalize_path { my ($self, $path) = @_; $path = ( Win32::GetShortPathName($path) || $path ) if $^O eq 'MSWin32'; return $path; } sub build_environment_vars_for { my $self = $_[0]->new->activate($_[1], { always => 1 }); $self->build_environment_vars; } sub build_activate_environment_vars_for { my $self = $_[0]->new->activate($_[1], { always => 1 }); $self->build_environment_vars; } sub build_deactivate_environment_vars_for { my $self = $_[0]->new->deactivate($_[1]); $self->build_environment_vars; } sub build_deact_all_environment_vars_for { my $self = $_[0]->new->deactivate_all; $self->build_environment_vars; } sub build_environment_vars { my $self = shift; ( PATH => join($_path_sep, _as_list($self->bins)), PERL5LIB => join($_path_sep, _as_list($self->libs)), PERL_LOCAL_LIB_ROOT => join($_path_sep, _as_list($self->roots)), %{$self->extra}, ); } sub setup_local_lib_for { my $self = $_[0]->new->activate($_[1]); $self->setup_local_lib; } sub setup_local_lib { my $self = shift; # if Carp is already loaded, ensure Carp::Heavy is also loaded, to avoid # $VERSION mismatch errors (Carp::Heavy loads Carp, so we do not need to # check in the other direction) require Carp::Heavy if $INC{'Carp.pm'}; $self->setup_env_hash; @INC = @{$self->inc}; } sub setup_env_hash_for { my $self = $_[0]->new->activate($_[1]); $self->setup_env_hash; } sub setup_env_hash { my $self = shift; my %env = $self->build_environment_vars; for my $key (keys %env) { if (defined $env{$key}) { $ENV{$key} = $env{$key}; } else { delete $ENV{$key}; } } } sub print_environment_vars_for { print $_[0]->environment_vars_string_for(@_[1..$#_]); } sub environment_vars_string_for { my $self = $_[0]->new->activate($_[1], { always => 1}); $self->environment_vars_string; } sub environment_vars_string { my ($self, $shelltype) = @_; $shelltype ||= $self->guess_shelltype; my $extra = $self->extra; my @envs = ( PATH => $self->bins, PERL5LIB => $self->libs, PERL_LOCAL_LIB_ROOT => $self->roots, map { $_ => $extra->{$_} } sort keys %$extra, ); $self->_build_env_string($shelltype, \@envs); } sub _build_env_string { my ($self, $shelltype, $envs) = @_; my @envs = @$envs; my $build_method = "build_${shelltype}_env_declaration"; my $out = ''; while (@envs) { my ($name, $value) = (shift(@envs), shift(@envs)); if ( ref $value && @$value == 1 && ref $value->[0] && ref $value->[0] eq 'SCALAR' && ${$value->[0]} eq $name) { next; } $out .= $self->$build_method($name, $value); } my $wrap_method = "wrap_${shelltype}_output"; if ($self->can($wrap_method)) { return $self->$wrap_method($out); } return $out; } sub build_bourne_env_declaration { my ($class, $name, $args) = @_; my $value = $class->_interpolate($args, '${%s:-}', qr/["\\\$!`]/, '\\%s'); if (!defined $value) { return qq{unset $name;\n}; } $value =~ s/(^|\G|$_path_sep)\$\{$name:-\}$_path_sep/$1\${$name}\${$name:+$_path_sep}/g; $value =~ s/$_path_sep\$\{$name:-\}$/\${$name:+$_path_sep\${$name}}/; qq{${name}="$value"; export ${name};\n} } sub build_csh_env_declaration { my ($class, $name, $args) = @_; my ($value, @vars) = $class->_interpolate($args, '${%s}', qr/["\$]/, '"\\%s"'); if (!defined $value) { return qq{unsetenv $name;\n}; } my $out = ''; for my $var (@vars) { $out .= qq{if ! \$?$name setenv $name '';\n}; } my $value_without = $value; if ($value_without =~ s/(?:^|$_path_sep)\$\{$name\}(?:$_path_sep|$)//g) { $out .= qq{if "\${$name}" != '' setenv $name "$value";\n}; $out .= qq{if "\${$name}" == '' }; } $out .= qq{setenv $name "$value_without";\n}; return $out; } sub build_cmd_env_declaration { my ($class, $name, $args) = @_; my $value = $class->_interpolate($args, '%%%s%%', qr(%), '%s'); if (!$value) { return qq{\@set $name=\n}; } my $out = ''; my $value_without = $value; if ($value_without =~ s/(?:^|$_path_sep)%$name%(?:$_path_sep|$)//g) { $out .= qq{\@if not "%$name%"=="" set "$name=$value"\n}; $out .= qq{\@if "%$name%"=="" }; } $out .= qq{\@set "$name=$value_without"\n}; return $out; } sub build_powershell_env_declaration { my ($class, $name, $args) = @_; my $value = $class->_interpolate($args, '$env:%s', qr/["\$]/, '`%s'); if (!$value) { return qq{Remove-Item -ErrorAction 0 Env:\\$name;\n}; } my $maybe_path_sep = qq{\$(if("\$env:$name"-eq""){""}else{"$_path_sep"})}; $value =~ s/(^|\G|$_path_sep)\$env:$name$_path_sep/$1\$env:$name"+$maybe_path_sep+"/g; $value =~ s/$_path_sep\$env:$name$/"+$maybe_path_sep+\$env:$name+"/; qq{\$env:$name = \$("$value");\n}; } sub wrap_powershell_output { my ($class, $out) = @_; return $out || " \n"; } sub build_fish_env_declaration { my ($class, $name, $args) = @_; my $value = $class->_interpolate($args, '$%s', qr/[\\"'$ ]/, '\\%s'); if (!defined $value) { return qq{set -e $name;\n}; } # fish has special handling for PATH, CDPATH, and MANPATH. They are always # treated as arrays, and joined with ; when storing the environment. Other # env vars can be arrays, but will be joined without a separator. We only # really care about PATH, but might as well make this routine more general. if ($name =~ /^(?:CD|MAN)?PATH$/) { $value =~ s/$_path_sep/ /g; my $silent = $name =~ /^(?:CD)?PATH$/ ? " 2>"._devnull : ''; return qq{set -x $name $value$silent;\n}; } my $out = ''; my $value_without = $value; if ($value_without =~ s/(?:^|$_path_sep)\$$name(?:$_path_sep|$)//g) { $out .= qq{set -q $name; and set -x $name $value;\n}; $out .= qq{set -q $name; or }; } $out .= qq{set -x $name $value_without;\n}; $out; } sub _interpolate { my ($class, $args, $var_pat, $escape, $escape_pat) = @_; return unless defined $args; my @args = ref $args ? @$args : $args; return unless @args; my @vars = map { $$_ } grep { ref $_ eq 'SCALAR' } @args; my $string = join $_path_sep, map { ref $_ eq 'SCALAR' ? sprintf($var_pat, $$_) : do { s/($escape)/sprintf($escape_pat, $1)/ge; $_; }; } @args; return wantarray ? ($string, \@vars) : $string; } sub pipeline; sub pipeline { my @methods = @_; my $last = pop(@methods); if (@methods) { \sub { my ($obj, @args) = @_; $obj->${pipeline @methods}( $obj->$last(@args) ); }; } else { \sub { shift->$last(@_); }; } } sub resolve_path { my ($class, $path) = @_; $path = $class->${pipeline qw( resolve_relative_path resolve_home_path resolve_empty_path )}($path); $path; } sub resolve_empty_path { my ($class, $path) = @_; if (defined $path) { $path; } else { '~/perl5'; } } sub resolve_home_path { my ($class, $path) = @_; $path =~ /^~([^\/]*)/ or return $path; my $user = $1; my $homedir = do { if (! length($user) && defined $ENV{HOME}) { $ENV{HOME}; } else { require File::Glob; File::Glob::bsd_glob("~$user", File::Glob::GLOB_TILDE()); } }; unless (defined $homedir) { require Carp; require Carp::Heavy; Carp::croak( "Couldn't resolve homedir for " .(defined $user ? $user : 'current user') ); } $path =~ s/^~[^\/]*/$homedir/; $path; } sub resolve_relative_path { my ($class, $path) = @_; _rel2abs($path); } sub ensure_dir_structure_for { my ($class, $path, $opts) = @_; $opts ||= {}; my @dirs; foreach my $dir ( $class->lib_paths_for($path), $class->install_base_bin_path($path), ) { my $d = $dir; while (!-d $d) { push @dirs, $d; require File::Basename; $d = File::Basename::dirname($d); } } warn "Attempting to create directory ${path}\n" if !$opts->{quiet} && @dirs; my %seen; foreach my $dir (reverse @dirs) { next if $seen{$dir}++; mkdir $dir or -d $dir or die "Unable to create $dir: $!" } return; } sub guess_shelltype { my $shellbin = defined $ENV{SHELL} && length $ENV{SHELL} ? ($ENV{SHELL} =~ /([\w.]+)$/)[-1] : ( $^O eq 'MSWin32' && exists $ENV{'!EXITCODE'} ) ? 'bash' : ( $^O eq 'MSWin32' && $ENV{PROMPT} && $ENV{COMSPEC} ) ? ($ENV{COMSPEC} =~ /([\w.]+)$/)[-1] : ( $^O eq 'MSWin32' && !$ENV{PROMPT} ) ? 'powershell.exe' : 'sh'; for ($shellbin) { return /csh$/ ? 'csh' : /fish$/ ? 'fish' : /command(?:\.com)?$/i ? 'cmd' : /cmd(?:\.exe)?$/i ? 'cmd' : /4nt(?:\.exe)?$/i ? 'cmd' : /powershell(?:\.exe)?$/i ? 'powershell' : 'bourne'; } } 1; __END__ =encoding utf8 =head1 NAME local::lib - create and use a local lib/ for perl modules with PERL5LIB =head1 SYNOPSIS In code - use local::lib; # sets up a local lib at ~/perl5 use local::lib '~/foo'; # same, but ~/foo # Or... use FindBin; use local::lib "$FindBin::Bin/../support"; # app-local support library From the shell - # Install LWP and its missing dependencies to the '~/perl5' directory perl -MCPAN -Mlocal::lib -e 'CPAN::install(LWP)' # Just print out useful shell commands $ perl -Mlocal::lib PERL_MB_OPT='--install_base /home/username/perl5'; export PERL_MB_OPT; PERL_MM_OPT='INSTALL_BASE=/home/username/perl5'; export PERL_MM_OPT; PERL5LIB="/home/username/perl5/lib/perl5"; export PERL5LIB; PATH="/home/username/perl5/bin:$PATH"; export PATH; PERL_LOCAL_LIB_ROOT="/home/usename/perl5:$PERL_LOCAL_LIB_ROOT"; export PERL_LOCAL_LIB_ROOT; From a F<.bash_profile> or F<.bashrc> file - eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)" =head2 The bootstrapping technique A typical way to install local::lib is using what is known as the "bootstrapping" technique. You would do this if your system administrator hasn't already installed local::lib. In this case, you'll need to install local::lib in your home directory. Even if you do have administrative privileges, you will still want to set up your environment variables, as discussed in step 4. Without this, you would still install the modules into the system CPAN installation and also your Perl scripts will not use the lib/ path you bootstrapped with local::lib. By default local::lib installs itself and the CPAN modules into ~/perl5. Windows users must also see L</Differences when using this module under Win32>. =over 4 =item 1. Download and unpack the local::lib tarball from CPAN (search for "Download" on the CPAN page about local::lib). Do this as an ordinary user, not as root or administrator. Unpack the file in your home directory or in any other convenient location. =item 2. Run this: perl Makefile.PL --bootstrap If the system asks you whether it should automatically configure as much as possible, you would typically answer yes. =item 3. Run this: (local::lib assumes you have make installed on your system) make test && make install =item 4. Now we need to setup the appropriate environment variables, so that Perl starts using our newly generated lib/ directory. If you are using bash or any other Bourne shells, you can add this to your shell startup script this way: echo 'eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)"' >>~/.bashrc If you are using C shell, you can do this as follows: % echo $SHELL /bin/csh $ echo 'eval `perl -I$HOME/perl5/lib/perl5 -Mlocal::lib`' >> ~/.cshrc After writing your shell configuration file, be sure to re-read it to get the changed settings into your current shell's environment. Bourne shells use C<. ~/.bashrc> for this, whereas C shells use C<source ~/.cshrc>. =back =head3 Bootstrapping into an alternate directory In order to install local::lib into a directory other than the default, you need to specify the name of the directory when you call bootstrap. Then, when setting up the environment variables, both perl and local::lib must be told the location of the bootstrap directory. The setup process would look as follows: perl Makefile.PL --bootstrap=~/foo make test && make install echo 'eval "$(perl -I$HOME/foo/lib/perl5 -Mlocal::lib=$HOME/foo)"' >>~/.bashrc . ~/.bashrc =head3 Other bootstrapping options If you're on a slower machine, or are operating under draconian disk space limitations, you can disable the automatic generation of manpages from POD when installing modules by using the C<--no-manpages> argument when bootstrapping: perl Makefile.PL --bootstrap --no-manpages To avoid doing several bootstrap for several Perl module environments on the same account, for example if you use it for several different deployed applications independently, you can use one bootstrapped local::lib installation to install modules in different directories directly this way: cd ~/mydir1 perl -Mlocal::lib=./ eval $(perl -Mlocal::lib=./) ### To set the environment for this shell alone printenv ### You will see that ~/mydir1 is in the PERL5LIB perl -MCPAN -e install ... ### whatever modules you want cd ../mydir2 ... REPEAT ... If you use F<.bashrc> to activate a local::lib automatically, the local::lib will be re-enabled in any sub-shells used, overriding adjustments you may have made in the parent shell. To avoid this, you can initialize the local::lib in F<.bash_profile> rather than F<.bashrc>, or protect the local::lib invocation with a C<$SHLVL> check: [ $SHLVL -eq 1 ] && eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)" If you are working with several C<local::lib> environments, you may want to remove some of them from the current environment without disturbing the others. You can deactivate one environment like this (using bourne sh): eval $(perl -Mlocal::lib=--deactivate,~/path) which will generate and run the commands needed to remove C<~/path> from your various search paths. Whichever environment was B<activated most recently> will remain the target for module installations. That is, if you activate C<~/path_A> and then you activate C<~/path_B>, new modules you install will go in C<~/path_B>. If you deactivate C<~/path_B> then modules will be installed into C<~/pathA> -- but if you deactivate C<~/path_A> then they will still be installed in C<~/pathB> because pathB was activated later. You can also ask C<local::lib> to clean itself completely out of the current shell's environment with the C<--deactivate-all> option. For multiple environments for multiple apps you may need to include a modified version of the C<< use FindBin >> instructions in the "In code" sample above. If you did something like the above, you have a set of Perl modules at C<< ~/mydir1/lib >>. If you have a script at C<< ~/mydir1/scripts/myscript.pl >>, you need to tell it where to find the modules you installed for it at C<< ~/mydir1/lib >>. In C<< ~/mydir1/scripts/myscript.pl >>: use strict; use warnings; use local::lib "$FindBin::Bin/.."; ### points to ~/mydir1 and local::lib finds lib use lib "$FindBin::Bin/../lib"; ### points to ~/mydir1/lib Put this before any BEGIN { ... } blocks that require the modules you installed. =head2 Differences when using this module under Win32 To set up the proper environment variables for your current session of C<CMD.exe>, you can use this: C:\>perl -Mlocal::lib set PERL_MB_OPT=--install_base C:\DOCUME~1\ADMINI~1\perl5 set PERL_MM_OPT=INSTALL_BASE=C:\DOCUME~1\ADMINI~1\perl5 set PERL5LIB=C:\DOCUME~1\ADMINI~1\perl5\lib\perl5 set PATH=C:\DOCUME~1\ADMINI~1\perl5\bin;%PATH% ### To set the environment for this shell alone C:\>perl -Mlocal::lib > %TEMP%\tmp.bat && %TEMP%\tmp.bat && del %TEMP%\tmp.bat ### instead of $(perl -Mlocal::lib=./) If you want the environment entries to persist, you'll need to add them to the Control Panel's System applet yourself or use L<App::local::lib::Win32Helper>. The "~" is translated to the user's profile directory (the directory named for the user under "Documents and Settings" (Windows XP or earlier) or "Users" (Windows Vista or later)) unless $ENV{HOME} exists. After that, the home directory is translated to a short name (which means the directory must exist) and the subdirectories are created. =head3 PowerShell local::lib also supports PowerShell, and can be used with the C<Invoke-Expression> cmdlet. Invoke-Expression "$(perl -Mlocal::lib)" =head1 RATIONALE The version of a Perl package on your machine is not always the version you need. Obviously, the best thing to do would be to update to the version you need. However, you might be in a situation where you're prevented from doing this. Perhaps you don't have system administrator privileges; or perhaps you are using a package management system such as Debian, and nobody has yet gotten around to packaging up the version you need. local::lib solves this problem by allowing you to create your own directory of Perl packages downloaded from CPAN (in a multi-user system, this would typically be within your own home directory). The existing system Perl installation is not affected; you simply invoke Perl with special options so that Perl uses the packages in your own local package directory rather than the system packages. local::lib arranges things so that your locally installed version of the Perl packages takes precedence over the system installation. If you are using a package management system (such as Debian), you don't need to worry about Debian and CPAN stepping on each other's toes. Your local version of the packages will be written to an entirely separate directory from those installed by Debian. =head1 DESCRIPTION This module provides a quick, convenient way of bootstrapping a user-local Perl module library located within the user's home directory. It also constructs and prints out for the user the list of environment variables using the syntax appropriate for the user's current shell (as specified by the C<SHELL> environment variable), suitable for directly adding to one's shell configuration file. More generally, local::lib allows for the bootstrapping and usage of a directory containing Perl modules outside of Perl's C<@INC>. This makes it easier to ship an application with an app-specific copy of a Perl module, or collection of modules. Useful in cases like when an upstream maintainer hasn't applied a patch to a module of theirs that you need for your application. On import, local::lib sets the following environment variables to appropriate values: =over 4 =item PERL_MB_OPT =item PERL_MM_OPT =item PERL5LIB =item PATH =item PERL_LOCAL_LIB_ROOT =back When possible, these will be appended to instead of overwritten entirely. These values are then available for reference by any code after import. =head1 CREATING A SELF-CONTAINED SET OF MODULES See L<lib::core::only> for one way to do this - but note that there are a number of caveats, and the best approach is always to perform a build against a clean perl (i.e. site and vendor as close to empty as possible). =head1 IMPORT OPTIONS Options are values that can be passed to the C<local::lib> import besides the directory to use. They are specified as C<use local::lib '--option'[, path];> or C<perl -Mlocal::lib=--option[,path]>. =head2 --deactivate Remove the chosen path (or the default path) from the module search paths if it was added by C<local::lib>, instead of adding it. =head2 --deactivate-all Remove all directories that were added to search paths by C<local::lib> from the search paths. =head2 --quiet Don't output any messages about directories being created. =head2 --always Always add directories to environment variables, ignoring if they are already included. =head2 --shelltype Specify the shell type to use for output. By default, the shell will be detected based on the environment. Should be one of: C<bourne>, C<csh>, C<cmd>, or C<powershell>. =head2 --no-create Prevents C<local::lib> from creating directories when activating dirs. This is likely to cause issues on Win32 systems. =head1 CLASS METHODS =head2 ensure_dir_structure_for =over 4 =item Arguments: $path =item Return value: None =back Attempts to create a local::lib directory, including subdirectories and all required parent directories. Throws an exception on failure. =head2 print_environment_vars_for =over 4 =item Arguments: $path =item Return value: None =back Prints to standard output the variables listed above, properly set to use the given path as the base directory. =head2 build_environment_vars_for =over 4 =item Arguments: $path =item Return value: %environment_vars =back Returns a hash with the variables listed above, properly set to use the given path as the base directory. =head2 setup_env_hash_for =over 4 =item Arguments: $path =item Return value: None =back Constructs the C<%ENV> keys for the given path, by calling L</build_environment_vars_for>. =head2 active_paths =over 4 =item Arguments: None =item Return value: @paths =back Returns a list of active C<local::lib> paths, according to the C<PERL_LOCAL_LIB_ROOT> environment variable and verified against what is really in C<@INC>. =head2 install_base_perl_path =over 4 =item Arguments: $path =item Return value: $install_base_perl_path =back Returns a path describing where to install the Perl modules for this local library installation. Appends the directories C<lib> and C<perl5> to the given path. =head2 lib_paths_for =over 4 =item Arguments: $path =item Return value: @lib_paths =back Returns the list of paths perl will search for libraries, given a base path. This includes the base path itself, the architecture specific subdirectory, and perl version specific subdirectories. These paths may not all exist. =head2 install_base_bin_path =over 4 =item Arguments: $path =item Return value: $install_base_bin_path =back Returns a path describing where to install the executable programs for this local library installation. Appends the directory C<bin> to the given path. =head2 installer_options_for =over 4 =item Arguments: $path =item Return value: %installer_env_vars =back Returns a hash of environment variables that should be set to cause installation into the given path. =head2 resolve_empty_path =over 4 =item Arguments: $path =item Return value: $base_path =back Builds and returns the base path into which to set up the local module installation. Defaults to C<~/perl5>. =head2 resolve_home_path =over 4 =item Arguments: $path =item Return value: $home_path =back Attempts to find the user's home directory. If no definite answer is available, throws an exception. =head2 resolve_relative_path =over 4 =item Arguments: $path =item Return value: $absolute_path =back Translates the given path into an absolute path. =head2 resolve_path =over 4 =item Arguments: $path =item Return value: $absolute_path =back Calls the following in a pipeline, passing the result from the previous to the next, in an attempt to find where to configure the environment for a local library installation: L</resolve_empty_path>, L</resolve_home_path>, L</resolve_relative_path>. Passes the given path argument to L</resolve_empty_path> which then returns a result that is passed to L</resolve_home_path>, which then has its result passed to L</resolve_relative_path>. The result of this final call is returned from L</resolve_path>. =head1 OBJECT INTERFACE =head2 new =over 4 =item Arguments: %attributes =item Return value: $local_lib =back Constructs a new C<local::lib> object, representing the current state of C<@INC> and the relevant environment variables. =head1 ATTRIBUTES =head2 roots An arrayref representing active C<local::lib> directories. =head2 inc An arrayref representing C<@INC>. =head2 libs An arrayref representing the PERL5LIB environment variable. =head2 bins An arrayref representing the PATH environment variable. =head2 extra A hashref of extra environment variables (e.g. C<PERL_MM_OPT> and C<PERL_MB_OPT>) =head2 no_create If set, C<local::lib> will not try to create directories when activating them. =head1 OBJECT METHODS =head2 clone =over 4 =item Arguments: %attributes =item Return value: $local_lib =back Constructs a new C<local::lib> object based on the existing one, overriding the specified attributes. =head2 activate =over 4 =item Arguments: $path =item Return value: $new_local_lib =back Constructs a new instance with the specified path active. =head2 deactivate =over 4 =item Arguments: $path =item Return value: $new_local_lib =back Constructs a new instance with the specified path deactivated. =head2 deactivate_all =over 4 =item Arguments: None =item Return value: $new_local_lib =back Constructs a new instance with all C<local::lib> directories deactivated. =head2 environment_vars_string =over 4 =item Arguments: [ $shelltype ] =item Return value: $shell_env_string =back Returns a string to set up the C<local::lib>, meant to be run by a shell. =head2 build_environment_vars =over 4 =item Arguments: None =item Return value: %environment_vars =back Returns a hash with the variables listed above, properly set to use the given path as the base directory. =head2 setup_env_hash =over 4 =item Arguments: None =item Return value: None =back Constructs the C<%ENV> keys for the given path, by calling L</build_environment_vars>. =head2 setup_local_lib Constructs the C<%ENV> hash using L</setup_env_hash>, and set up C<@INC>. =head1 A WARNING ABOUT UNINST=1 Be careful about using local::lib in combination with "make install UNINST=1". The idea of this feature is that will uninstall an old version of a module before installing a new one. However it lacks a safety check that the old version and the new version will go in the same directory. Used in combination with local::lib, you can potentially delete a globally accessible version of a module while installing the new version in a local place. Only combine "make install UNINST=1" and local::lib if you understand these possible consequences. =head1 LIMITATIONS =over 4 =item * Directory names with spaces in them are not well supported by the perl toolchain and the programs it uses. Pure-perl distributions should support spaces, but problems are more likely with dists that require compilation. A workaround you can do is moving your local::lib to a directory with spaces B<after> you installed all modules inside your local::lib bootstrap. But be aware that you can't update or install CPAN modules after the move. =item * Rather basic shell detection. Right now anything with csh in its name is assumed to be a C shell or something compatible, and everything else is assumed to be Bourne, except on Win32 systems. If the C<SHELL> environment variable is not set, a Bourne-compatible shell is assumed. =item * Kills any existing PERL_MM_OPT or PERL_MB_OPT. =item * Should probably auto-fixup CPAN config if not already done. =item * On VMS and MacOS Classic (pre-OS X), local::lib loads L<File::Spec>. This means any L<File::Spec> version installed in the local::lib will be ignored by scripts using local::lib. A workaround for this is using C<use lib "$local_lib/lib/perl5";> instead of using C<local::lib> directly. =item * Conflicts with L<ExtUtils::MakeMaker>'s C<PREFIX> option. C<local::lib> uses the C<INSTALL_BASE> option, as it has more predictable and sane behavior. If something attempts to use the C<PREFIX> option when running a F<Makefile.PL>, L<ExtUtils::MakeMaker> will refuse to run, as the two options conflict. This can be worked around by temporarily unsetting the C<PERL_MM_OPT> environment variable. =item * Conflicts with L<Module::Build>'s C<--prefix> option. Similar to the previous limitation, but any C<--prefix> option specified will be ignored. This can be worked around by temporarily unsetting the C<PERL_MB_OPT> environment variable. =back Patches very much welcome for any of the above. =over 4 =item * On Win32 systems, does not have a way to write the created environment variables to the registry, so that they can persist through a reboot. =back =head1 TROUBLESHOOTING If you've configured local::lib to install CPAN modules somewhere in to your home directory, and at some point later you try to install a module with C<cpan -i Foo::Bar>, but it fails with an error like: C<Warning: You do not have permissions to install into /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux at /usr/lib64/perl5/5.8.8/Foo/Bar.pm> and buried within the install log is an error saying C<'INSTALL_BASE' is not a known MakeMaker parameter name>, then you've somehow lost your updated ExtUtils::MakeMaker module. To remedy this situation, rerun the bootstrapping procedure documented above. Then, run C<rm -r ~/.cpan/build/Foo-Bar*> Finally, re-run C<cpan -i Foo::Bar> and it should install without problems. =head1 ENVIRONMENT =over 4 =item SHELL =item COMSPEC local::lib looks at the user's C<SHELL> environment variable when printing out commands to add to the shell configuration file. On Win32 systems, C<COMSPEC> is also examined. =back =head1 SEE ALSO =over 4 =item * L<Perl Advent article, 2011|http://perladvent.org/2011/2011-12-01.html> =back =head1 SUPPORT IRC: Join #toolchain on irc.perl.org. =head1 AUTHOR Matt S Trout <mst@shadowcat.co.uk> http://www.shadowcat.co.uk/ auto_install fixes kindly sponsored by http://www.takkle.com/ =head1 CONTRIBUTORS Patches to correctly output commands for csh style shells, as well as some documentation additions, contributed by Christopher Nehren <apeiron@cpan.org>. Doc patches for a custom local::lib directory, more cleanups in the english documentation and a L<german documentation|POD2::DE::local::lib> contributed by Torsten Raudssus <torsten@raudssus.de>. Hans Dieter Pearcey <hdp@cpan.org> sent in some additional tests for ensuring things will install properly, submitted a fix for the bug causing problems with writing Makefiles during bootstrapping, contributed an example program, and submitted yet another fix to ensure that local::lib can install and bootstrap properly. Many, many thanks! pattern of Freenode IRC contributed the beginnings of the Troubleshooting section. Many thanks! Patch to add Win32 support contributed by Curtis Jewell <csjewell@cpan.org>. Warnings for missing PATH/PERL5LIB (as when not running interactively) silenced by a patch from Marco Emilio Poleggi. Mark Stosberg <mark@summersault.com> provided the code for the now deleted '--self-contained' option. Documentation patches to make win32 usage clearer by David Mertens <dcmertens.perl@gmail.com> (run4flat). Brazilian L<portuguese translation|POD2::PT_BR::local::lib> and minor doc patches contributed by Breno G. de Oliveira <garu@cpan.org>. Improvements to stacking multiple local::lib dirs and removing them from the environment later on contributed by Andrew Rodland <arodland@cpan.org>. Patch for Carp version mismatch contributed by Hakim Cassimally <osfameron@cpan.org>. Rewrite of internals and numerous bug fixes and added features contributed by Graham Knop <haarg@haarg.org>. =head1 COPYRIGHT Copyright (c) 2007 - 2013 the local::lib L</AUTHOR> and L</CONTRIBUTORS> as listed above. =head1 LICENSE 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/CPAN.pm���������������������������������������������������������������������������������������0000444�����������������00000440626�15253012307�0006662 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- # vim: ts=4 sts=4 sw=4: use strict; package CPAN; $CPAN::VERSION = '2.36'; $CPAN::VERSION =~ s/_//; # we need to run chdir all over and we would get at wrong libraries # there use File::Spec (); BEGIN { if (File::Spec->can("rel2abs")) { for my $inc (@INC) { $inc = File::Spec->rel2abs($inc) unless ref $inc; } } $SIG{WINCH} = 'IGNORE' if exists $SIG{WINCH}; } use CPAN::Author; use CPAN::HandleConfig; use CPAN::Version; use CPAN::Bundle; use CPAN::CacheMgr; use CPAN::Complete; use CPAN::Debug; use CPAN::Distribution; use CPAN::Distrostatus; use CPAN::FTP; use CPAN::Index 1.93; # https://rt.cpan.org/Ticket/Display.html?id=43349 use CPAN::InfoObj; use CPAN::Module; use CPAN::Prompt; use CPAN::URL; use CPAN::Queue; use CPAN::Tarzip; use CPAN::DeferredCode; use CPAN::Shell; use CPAN::LWP::UserAgent; use CPAN::Exception::RecursiveDependency; use CPAN::Exception::yaml_not_installed; use CPAN::Exception::yaml_process_error; use Carp (); use Config (); use Cwd qw(chdir); use DirHandle (); use Exporter (); use ExtUtils::MakeMaker qw(prompt); # for some unknown reason, # 5.005_04 does not work without # this use File::Basename (); use File::Copy (); use File::Find; use File::Path (); use FileHandle (); use Fcntl qw(:flock); use Safe (); use Sys::Hostname qw(hostname); use Text::ParseWords (); use Text::Wrap (); # protect against "called too early" sub find_perl (); sub anycwd (); sub _uniq; no lib "."; require Mac::BuildTools if $^O eq 'MacOS'; if ($ENV{PERL5_CPAN_IS_RUNNING} && $$ != $ENV{PERL5_CPAN_IS_RUNNING}) { $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION} ||= $ENV{PERL5_CPAN_IS_RUNNING}; my @rec = _uniq split(/,/, $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION}), $$; $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION} = join ",", @rec; # warn "# Note: Recursive call of CPAN.pm detected\n"; my $w = sprintf "# Note: CPAN.pm is running in process %d now", pop @rec; my %sleep = ( 5 => 30, 6 => 60, 7 => 120, ); my $sleep = @rec > 7 ? 300 : ($sleep{scalar @rec}||0); my $verbose = @rec >= 4; while (@rec) { $w .= sprintf " which has been called by process %d", pop @rec; } if ($sleep) { $w .= ".\n\n# Sleeping $sleep seconds to protect other processes\n"; } if ($verbose) { warn $w; } local $| = 1; my $have_been_sleeping = 0; while ($sleep > 0) { printf "\r#%5d", --$sleep; sleep 1; ++$have_been_sleeping; } print "\n" if $have_been_sleeping; } $ENV{PERL5_CPAN_IS_RUNNING}=$$; $ENV{PERL5_CPANPLUS_IS_RUNNING}=$$; # https://rt.cpan.org/Ticket/Display.html?id=23735 END { $CPAN::End++; &cleanup; } $CPAN::Signal ||= 0; $CPAN::Frontend ||= "CPAN::Shell"; unless (@CPAN::Defaultsites) { @CPAN::Defaultsites = map { CPAN::URL->new(TEXT => $_, FROM => "DEF") } "http://www.perl.org/CPAN/", "ftp://ftp.perl.org/pub/CPAN/"; } # $CPAN::iCwd (i for initial) $CPAN::iCwd ||= CPAN::anycwd(); $CPAN::Perl ||= CPAN::find_perl(); $CPAN::Defaultdocs ||= "http://search.cpan.org/perldoc?"; $CPAN::Defaultrecent ||= "http://search.cpan.org/uploads.rdf"; $CPAN::Defaultrecent ||= "http://cpan.uwinnipeg.ca/htdocs/cpan.xml"; # our globals are getting a mess use vars qw( $AUTOLOAD $Be_Silent $CONFIG_DIRTY $Defaultdocs $Echo_readline $Frontend $GOTOSHELL $HAS_USABLE $Have_warned $MAX_RECURSION $META $RUN_DEGRADED $Signal $SQLite $Suppress_readline $VERSION $autoload_recursion $term @Defaultsites @EXPORT ); $MAX_RECURSION = 32; @CPAN::ISA = qw(CPAN::Debug Exporter); # note that these functions live in CPAN::Shell and get executed via # AUTOLOAD when called directly @EXPORT = qw( autobundle bundle clean cvs_import expand force fforce get install install_tested is_tested make mkmyconfig notest perldoc readme recent recompile report shell smoke test upgrade ); sub soft_chdir_with_alternatives ($); { $autoload_recursion ||= 0; #-> sub CPAN::AUTOLOAD ; sub AUTOLOAD { ## no critic $autoload_recursion++; my($l) = $AUTOLOAD; $l =~ s/.*:://; if ($CPAN::Signal) { warn "Refusing to autoload '$l' while signal pending"; $autoload_recursion--; return; } if ($autoload_recursion > 1) { my $fullcommand = join " ", map { "'$_'" } $l, @_; warn "Refusing to autoload $fullcommand in recursion\n"; $autoload_recursion--; return; } my(%export); @export{@EXPORT} = ''; CPAN::HandleConfig->load unless $CPAN::Config_loaded++; if (exists $export{$l}) { CPAN::Shell->$l(@_); } else { die(qq{Unknown CPAN command "$AUTOLOAD". }. qq{Type ? for help.\n}); } $autoload_recursion--; } } { my $x = *SAVEOUT; # avoid warning open($x,">&STDOUT") or die "dup failed"; my $redir = 0; sub _redirect(@) { #die if $redir; local $_; push(@_,undef); while(defined($_=shift)) { if (s/^\s*>//){ my ($m) = s/^>// ? ">" : ""; s/\s+//; $_=shift unless length; die "no dest" unless defined; open(STDOUT,">$m$_") or die "open:$_:$!\n"; $redir=1; } elsif ( s/^\s*\|\s*// ) { my $pipe="| $_"; while(defined($_[0])){ $pipe .= ' ' . shift; } open(STDOUT,$pipe) or die "open:$pipe:$!\n"; $redir=1; } else { push(@_,$_); } } return @_; } sub _unredirect { return unless $redir; $redir = 0; ## redirect: unredirect and propagate errors. explicit close to wait for pipe. close(STDOUT); open(STDOUT,">&SAVEOUT"); die "$@" if "$@"; ## redirect: done } } sub _uniq { my(@list) = @_; my %seen; return grep { !$seen{$_}++ } @list; } #-> sub CPAN::shell ; sub shell { my($self) = @_; $Suppress_readline = ! -t STDIN unless defined $Suppress_readline; CPAN::HandleConfig->load unless $CPAN::Config_loaded++; my $oprompt = shift || CPAN::Prompt->new; my $prompt = $oprompt; my $commandline = shift || ""; $CPAN::CurrentCommandId ||= 1; local($^W) = 1; unless ($Suppress_readline) { require Term::ReadLine; if (! $term or $term->ReadLine eq "Term::ReadLine::Stub" ) { $term = Term::ReadLine->new('CPAN Monitor'); } if ($term->ReadLine eq "Term::ReadLine::Gnu") { my $attribs = $term->Attribs; $attribs->{attempted_completion_function} = sub { &CPAN::Complete::gnu_cpl; } } else { $readline::rl_completion_function = $readline::rl_completion_function = 'CPAN::Complete::cpl'; } if (my $histfile = $CPAN::Config->{'histfile'}) {{ unless ($term->can("AddHistory")) { $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n"); unless ($CPAN::META->has_inst('Term::ReadLine::Perl')) { $CPAN::Frontend->mywarn("\nTo fix that, maybe try> install Term::ReadLine::Perl\n\n"); } last; } $META->readhist($term,$histfile); }} for ($CPAN::Config->{term_ornaments}) { # alias local $Term::ReadLine::termcap_nowarn = 1; $term->ornaments($_) if defined; } # $term->OUT is autoflushed anyway my $odef = select STDERR; $| = 1; select STDOUT; $| = 1; select $odef; } $META->checklock(); my @cwd = grep { defined $_ and length $_ } CPAN::anycwd(), File::Spec->can("tmpdir") ? File::Spec->tmpdir() : (), File::Spec->rootdir(); my $try_detect_readline; $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub" if $term; unless ($CPAN::Config->{inhibit_startup_message}) { my $rl_avail = $Suppress_readline ? "suppressed" : ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" : "available (maybe install Bundle::CPAN or Bundle::CPANxxl?)"; $CPAN::Frontend->myprint( sprintf qq{ cpan shell -- CPAN exploration and modules installation (v%s) Enter 'h' for help. }, $CPAN::VERSION, ) } my($continuation) = ""; my $last_term_ornaments; SHELLCOMMAND: while () { if ($Suppress_readline) { if ($Echo_readline) { $|=1; } print $prompt; last SHELLCOMMAND unless defined ($_ = <> ); if ($Echo_readline) { # backdoor: I could not find a way to record sessions print $_; } chomp; } else { last SHELLCOMMAND unless defined ($_ = $term->readline($prompt, $commandline)); } $_ = "$continuation$_" if $continuation; s/^\s+//; next SHELLCOMMAND if /^$/; s/^\s*\?\s*/help /; if (/^(?:q(?:uit)?|bye|exit)\s*$/i) { last SHELLCOMMAND; } elsif (s/\\$//s) { chomp; $continuation = $_; $prompt = " > "; } elsif (/^\!/) { s/^\!//; my($eval) = $_; package CPAN::Eval; # hide from the indexer use strict; use vars qw($import_done); CPAN->import(':DEFAULT') unless $import_done++; CPAN->debug("eval[$eval]") if $CPAN::DEBUG; eval($eval); warn $@ if $@; $continuation = ""; $prompt = $oprompt; } elsif (/./) { my(@line); eval { @line = Text::ParseWords::shellwords($_) }; warn($@), next SHELLCOMMAND if $@; warn("Text::Parsewords could not parse the line [$_]"), next SHELLCOMMAND unless @line; $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG; my $command = shift @line; eval { local (*STDOUT)=*STDOUT; @line = _redirect(@line); CPAN::Shell->$command(@line) }; my $command_error = $@; _unredirect; my $reported_error; if ($command_error) { my $err = $command_error; if (ref $err and $err->isa('CPAN::Exception::blocked_urllist')) { $CPAN::Frontend->mywarn("Client not fully configured, please proceed with configuring.$err"); $reported_error = ref $err; } else { # I'd prefer never to arrive here and make all errors exception objects if ($err =~ /\S/) { require Carp; require Dumpvalue; my $dv = Dumpvalue->new(tick => '"'); Carp::cluck(sprintf "Catching error: %s", $dv->stringify($err)); } } } if ($command =~ /^( # classic commands make |test |install |clean # pragmas for classic commands |ff?orce |notest # compounds |report |smoke |upgrade )$/x) { # only commands that tell us something about failed distros # eval necessary for people without an urllist eval {CPAN::Shell->failed($CPAN::CurrentCommandId,1);}; if (my $err = $@) { unless (ref $err and $reported_error eq ref $err) { die $@; } } } soft_chdir_with_alternatives(\@cwd); $CPAN::Frontend->myprint("\n"); $continuation = ""; $CPAN::CurrentCommandId++; $prompt = $oprompt; } } continue { $commandline = ""; # I do want to be able to pass a default to # shell, but on the second command I see no # use in that $Signal=0; CPAN::Queue->nullify_queue; if ($try_detect_readline) { if ($CPAN::META->has_inst("Term::ReadLine::Gnu") || $CPAN::META->has_inst("Term::ReadLine::Perl") ) { delete $INC{"Term/ReadLine.pm"}; my $redef = 0; local($SIG{__WARN__}) = CPAN::Shell::paintdots_onreload(\$redef); require Term::ReadLine; $CPAN::Frontend->myprint("\n$redef subroutines in ". "Term::ReadLine redefined\n"); $GOTOSHELL = 1; } } if ($term and $term->can("ornaments")) { for ($CPAN::Config->{term_ornaments}) { # alias if (defined $_) { if (not defined $last_term_ornaments or $_ != $last_term_ornaments ) { local $Term::ReadLine::termcap_nowarn = 1; $term->ornaments($_); $last_term_ornaments = $_; } } else { undef $last_term_ornaments; } } } for my $class (qw(Module Distribution)) { # again unsafe meta access? for my $dm (sort keys %{$CPAN::META->{readwrite}{"CPAN::$class"}}) { next unless $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor}; CPAN->debug("BUG: $class '$dm' was in command state, resetting"); delete $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor}; } } if ($GOTOSHELL) { $GOTOSHELL = 0; # not too often $META->savehist if $CPAN::term && $CPAN::term->can("GetHistory"); @_ = ($oprompt,""); goto &shell; } } soft_chdir_with_alternatives(\@cwd); } #-> CPAN::soft_chdir_with_alternatives ; sub soft_chdir_with_alternatives ($) { my($cwd) = @_; unless (@$cwd) { my $root = File::Spec->rootdir(); $CPAN::Frontend->mywarn(qq{Warning: no good directory to chdir to! Trying '$root' as temporary haven. }); push @$cwd, $root; } while () { if (chdir "$cwd->[0]") { return; } else { if (@$cwd>1) { $CPAN::Frontend->mywarn(qq{Could not chdir to "$cwd->[0]": $! Trying to chdir to "$cwd->[1]" instead. }); shift @$cwd; } else { $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd->[0]": $!}); } } } } sub _flock { my($fh,$mode) = @_; if ( $Config::Config{d_flock} || $Config::Config{d_fcntl_can_lock} ) { return flock $fh, $mode; } elsif (!$Have_warned->{"d_flock"}++) { $CPAN::Frontend->mywarn("Your OS does not seem to support locking; continuing and ignoring all locking issues\n"); $CPAN::Frontend->mysleep(5); return 1; } else { return 1; } } sub _yaml_module () { my $yaml_module = $CPAN::Config->{yaml_module} || "YAML"; if ( $yaml_module ne "YAML" && !$CPAN::META->has_inst($yaml_module) ) { # $CPAN::Frontend->mywarn("'$yaml_module' not installed, falling back to 'YAML'\n"); $yaml_module = "YAML"; } if ($yaml_module eq "YAML" && $CPAN::META->has_inst($yaml_module) && $YAML::VERSION < 0.60 && !$Have_warned->{"YAML"}++ ) { $CPAN::Frontend->mywarn("Warning: YAML version '$YAML::VERSION' is too low, please upgrade!\n". "I'll continue but problems are *very* likely to happen.\n" ); $CPAN::Frontend->mysleep(5); } return $yaml_module; } # CPAN::_yaml_loadfile sub _yaml_loadfile { my($self,$local_file,$opt) = @_; return +[] unless -s $local_file; my $opt_loadblessed = $opt->{loadblessed} || $CPAN::Config->{yaml_load_code} || 0; my $yaml_module = _yaml_module; if ($CPAN::META->has_inst($yaml_module)) { # temporarily enable yaml code deserialisation no strict 'refs'; # 5.6.2 could not do the local() with the reference # so we do it manually instead my $old_loadcode = ${"$yaml_module\::LoadCode"}; my $old_loadblessed = ${"$yaml_module\::LoadBlessed"}; ${ "$yaml_module\::LoadCode" } = $CPAN::Config->{yaml_load_code} || 0; ${ "$yaml_module\::LoadBlessed" } = $opt_loadblessed ? 1 : 0; my ($code, @yaml); if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) { eval { @yaml = $code->($local_file); }; if ($@) { # this shall not be done by the frontend die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@); } } elsif ($code = UNIVERSAL::can($yaml_module, "Load")) { local *FH; if (open FH, $local_file) { local $/; my $ystream = <FH>; eval { @yaml = $code->($ystream); }; if ($@) { # this shall not be done by the frontend die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@); } } else { $CPAN::Frontend->mywarn("Could not open '$local_file': $!"); } } ${"$yaml_module\::LoadCode"} = $old_loadcode; ${"$yaml_module\::LoadBlessed"} = $old_loadblessed; return \@yaml; } else { # this shall not be done by the frontend die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "parse"); } return +[]; } # CPAN::_yaml_dumpfile sub _yaml_dumpfile { my($self,$local_file,@what) = @_; my $yaml_module = _yaml_module; if ($CPAN::META->has_inst($yaml_module)) { my $code; if (UNIVERSAL::isa($local_file, "FileHandle")) { $code = UNIVERSAL::can($yaml_module, "Dump"); eval { print $local_file $code->(@what) }; } elsif ($code = UNIVERSAL::can($yaml_module, "DumpFile")) { eval { $code->($local_file,@what); }; } elsif ($code = UNIVERSAL::can($yaml_module, "Dump")) { local *FH; open FH, ">$local_file" or die "Could not open '$local_file': $!"; print FH $code->(@what); } if ($@) { die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"dump",$@); } } else { if (UNIVERSAL::isa($local_file, "FileHandle")) { # I think this case does not justify a warning at all } else { die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "dump"); } } } sub _init_sqlite () { unless ($CPAN::META->has_inst("CPAN::SQLite")) { $CPAN::Frontend->mywarn(qq{CPAN::SQLite not installed, trying to work without\n}) unless $Have_warned->{"CPAN::SQLite"}++; return; } require CPAN::SQLite::META; # not needed since CVS version of 2006-12-17 $CPAN::SQLite ||= CPAN::SQLite::META->new($CPAN::META); } { my $negative_cache = {}; sub _sqlite_running { if ($negative_cache->{time} && time < $negative_cache->{time} + 60) { # need to cache the result, otherwise too slow return $negative_cache->{fact}; } else { $negative_cache = {}; # reset } my $ret = $CPAN::Config->{use_sqlite} && ($CPAN::SQLite || _init_sqlite()); return $ret if $ret; # fast anyway $negative_cache->{time} = time; return $negative_cache->{fact} = $ret; } } $META ||= CPAN->new; # In case we re-eval ourselves we need the || # from here on only subs. ################################################################################ sub _perl_fingerprint { my($self,$other_fingerprint) = @_; my $dll = eval {OS2::DLLname()}; my $mtime_dll = 0; if (defined $dll) { $mtime_dll = (-f $dll ? (stat(_))[9] : '-1'); } my $mtime_perl = (-f CPAN::find_perl ? (stat(_))[9] : '-1'); my $this_fingerprint = { '$^X' => CPAN::find_perl, sitearchexp => $Config::Config{sitearchexp}, 'mtime_$^X' => $mtime_perl, 'mtime_dll' => $mtime_dll, }; if ($other_fingerprint) { if (exists $other_fingerprint->{'stat($^X)'}) { # repair fp from rev. 1.88_57 $other_fingerprint->{'mtime_$^X'} = $other_fingerprint->{'stat($^X)'}[9]; } # mandatory keys since 1.88_57 for my $key (qw($^X sitearchexp mtime_dll mtime_$^X)) { return unless $other_fingerprint->{$key} eq $this_fingerprint->{$key}; } return 1; } else { return $this_fingerprint; } } sub suggest_myconfig () { SUGGEST_MYCONFIG: if(!$INC{'CPAN/MyConfig.pm'}) { $CPAN::Frontend->myprint("You don't seem to have a user ". "configuration (MyConfig.pm) yet.\n"); my $new = CPAN::Shell::colorable_makemaker_prompt("Do you want to create a ". "user configuration now? (Y/n)", "yes"); if($new =~ m{^y}i) { CPAN::Shell->mkmyconfig(); return &checklock; } else { $CPAN::Frontend->mydie("OK, giving up."); } } } #-> sub CPAN::all_objects ; sub all_objects { my($mgr,$class) = @_; CPAN::HandleConfig->load unless $CPAN::Config_loaded++; CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG; CPAN::Index->reload; values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok } # Called by shell, not in batch mode. In batch mode I see no risk in # having many processes updating something as installations are # continually checked at runtime. In shell mode I suspect it is # unintentional to open more than one shell at a time #-> sub CPAN::checklock ; sub checklock { my($self) = @_; my $lockfile = File::Spec->catfile($CPAN::Config->{cpan_home},".lock"); if (-f $lockfile && -M _ > 0) { my $fh = FileHandle->new($lockfile) or $CPAN::Frontend->mydie("Could not open lockfile '$lockfile': $!"); my $otherpid = <$fh>; my $otherhost = <$fh>; $fh->close; if (defined $otherpid && length $otherpid) { chomp $otherpid; } if (defined $otherhost && length $otherhost) { chomp $otherhost; } my $thishost = hostname(); my $ask_if_degraded_wanted = 0; if (defined $otherhost && defined $thishost && $otherhost ne '' && $thishost ne '' && $otherhost ne $thishost) { $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile '$lockfile'\n". "reports other host $otherhost and other ". "process $otherpid.\n". "Cannot proceed.\n")); } elsif ($RUN_DEGRADED) { $CPAN::Frontend->mywarn("Running in downgraded mode (experimental)\n"); } elsif (defined $otherpid && $otherpid) { return if $$ == $otherpid; # should never happen $CPAN::Frontend->mywarn( qq{ There seems to be running another CPAN process (pid $otherpid). Contacting... }); if (kill 0, $otherpid or $!{EPERM}) { $CPAN::Frontend->mywarn(qq{Other job is running.\n}); $ask_if_degraded_wanted = 1; } elsif (-w $lockfile) { my($ans) = CPAN::Shell::colorable_makemaker_prompt (qq{Other job not responding. Shall I overwrite }. qq{the lockfile '$lockfile'? (Y/n)},"y"); $CPAN::Frontend->myexit("Ok, bye\n") unless $ans =~ /^y/i; } else { Carp::croak( qq{Lockfile '$lockfile' not writable by you. }. qq{Cannot proceed.\n}. qq{ On UNIX try:\n}. qq{ rm '$lockfile'\n}. qq{ and then rerun us.\n} ); } } elsif ($^O eq "MSWin32") { $CPAN::Frontend->mywarn( qq{ There seems to be running another CPAN process according to '$lockfile'. }); $ask_if_degraded_wanted = 1; } else { $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Found invalid lockfile ". "'$lockfile', please remove. Cannot proceed.\n")); } if ($ask_if_degraded_wanted) { my($ans) = CPAN::Shell::colorable_makemaker_prompt (qq{Shall I try to run in downgraded }. qq{mode? (Y/n)},"y"); if ($ans =~ /^y/i) { $CPAN::Frontend->mywarn("Running in downgraded mode (experimental). Please report if something unexpected happens\n"); $RUN_DEGRADED = 1; for ($CPAN::Config) { # XXX # $_->{build_dir_reuse} = 0; # 2006-11-17 akoenig Why was that? $_->{commandnumber_in_prompt} = 0; # visibility $_->{histfile} = ""; # who should win otherwise? $_->{cache_metadata} = 0; # better would be a lock? $_->{use_sqlite} = 0; # better would be a write lock! $_->{auto_commit} = 0; # we are violent, do not persist $_->{test_report} = 0; # Oliver Paukstadt had sent wrong reports in degraded mode } } else { my $msg = "You may want to kill the other job and delete the lockfile."; if (defined $otherpid) { $msg .= " Something like: kill $otherpid rm $lockfile "; } $CPAN::Frontend->mydie("\n$msg"); } } } my $dotcpan = $CPAN::Config->{cpan_home}; eval { File::Path::mkpath($dotcpan);}; if ($@) { # A special case at least for Jarkko. my $firsterror = $@; my $seconderror; my $symlinkcpan; if (-l $dotcpan) { $symlinkcpan = readlink $dotcpan; die "readlink $dotcpan failed: $!" unless defined $symlinkcpan; eval { File::Path::mkpath($symlinkcpan); }; if ($@) { $seconderror = $@; } else { $CPAN::Frontend->mywarn(qq{ Working directory $symlinkcpan created. }); } } unless (-d $dotcpan) { my $mess = qq{ Your configuration suggests "$dotcpan" as your CPAN.pm working directory. I could not create this directory due to this error: $firsterror\n}; $mess .= qq{ As "$dotcpan" is a symlink to "$symlinkcpan", I tried to create that, but I failed with this error: $seconderror } if $seconderror; $mess .= qq{ Please make sure the directory exists and is writable. }; $CPAN::Frontend->mywarn($mess); return suggest_myconfig; } } # $@ after eval mkpath $dotcpan if (0) { # to test what happens when a race condition occurs for (reverse 1..10) { print $_, "\n"; sleep 1; } } # locking if (!$RUN_DEGRADED && !$self->{LOCKFH}) { my $fh; unless ($fh = FileHandle->new("+>>$lockfile")) { $CPAN::Frontend->mywarn(qq{ Your configuration suggests that CPAN.pm should use a working directory of $CPAN::Config->{cpan_home} Unfortunately we could not create the lock file $lockfile due to '$!'. Please make sure that the configuration variable \$CPAN::Config->{cpan_home} points to a directory where you can write a .lock file. You can set this variable in either a CPAN/MyConfig.pm or a CPAN/Config.pm in your \@INC path; }); return suggest_myconfig; } my $sleep = 1; while (!CPAN::_flock($fh, LOCK_EX|LOCK_NB)) { my $err = $! || "unknown error"; if ($sleep>3) { $CPAN::Frontend->mydie("Could not lock '$lockfile' with flock: $err; giving up\n"); } $CPAN::Frontend->mysleep($sleep+=0.1); $CPAN::Frontend->mywarn("Could not lock '$lockfile' with flock: $err; retrying\n"); } seek $fh, 0, 0; truncate $fh, 0; $fh->autoflush(1); $fh->print($$, "\n"); $fh->print(hostname(), "\n"); $self->{LOCK} = $lockfile; $self->{LOCKFH} = $fh; } $SIG{TERM} = sub { my $sig = shift; &cleanup; $CPAN::Frontend->mydie("Got SIG$sig, leaving"); }; $SIG{INT} = sub { # no blocks!!! my $sig = shift; &cleanup if $Signal; die "Got yet another signal" if $Signal > 1; $CPAN::Frontend->mydie("Got another SIG$sig") if $Signal; $CPAN::Frontend->mywarn("Caught SIG$sig, trying to continue\n"); $Signal++; }; # From: Larry Wall <larry@wall.org> # Subject: Re: deprecating SIGDIE # To: perl5-porters@perl.org # Date: Thu, 30 Sep 1999 14:58:40 -0700 (PDT) # # The original intent of __DIE__ was only to allow you to substitute one # kind of death for another on an application-wide basis without respect # to whether you were in an eval or not. As a global backstop, it should # not be used any more lightly (or any more heavily :-) than class # UNIVERSAL. Any attempt to build a general exception model on it should # be politely squashed. Any bug that causes every eval {} to have to be # modified should be not so politely squashed. # # Those are my current opinions. It is also my opinion that polite # arguments degenerate to personal arguments far too frequently, and that # when they do, it's because both people wanted it to, or at least didn't # sufficiently want it not to. # # Larry # global backstop to cleanup if we should really die $SIG{__DIE__} = \&cleanup; $self->debug("Signal handler set.") if $CPAN::DEBUG; } #-> sub CPAN::DESTROY ; sub DESTROY { &cleanup; # need an eval? } #-> sub CPAN::anycwd ; sub anycwd () { my $getcwd; $getcwd = $CPAN::Config->{'getcwd'} || 'cwd'; CPAN->$getcwd(); } #-> sub CPAN::cwd ; sub cwd {Cwd::cwd();} #-> sub CPAN::getcwd ; sub getcwd {Cwd::getcwd();} #-> sub CPAN::fastcwd ; sub fastcwd {Cwd::fastcwd();} #-> sub CPAN::getdcwd ; sub getdcwd {Cwd::getdcwd();} #-> sub CPAN::backtickcwd ; sub backtickcwd {my $cwd = `cwd`; chomp $cwd; $cwd} # Adapted from Probe::Perl #-> sub CPAN::_perl_is_same sub _perl_is_same { my ($perl) = @_; return MM->maybe_command($perl) && `$perl -MConfig=myconfig -e print -e myconfig` eq Config->myconfig; } # Adapted in part from Probe::Perl #-> sub CPAN::find_perl ; sub find_perl () { if ( File::Spec->file_name_is_absolute($^X) ) { return $^X; } else { my $exe = $Config::Config{exe_ext}; my @candidates = ( File::Spec->catfile($CPAN::iCwd,$^X), $Config::Config{'perlpath'}, ); for my $perl_name ($^X, 'perl', 'perl5', "perl$]") { for my $path (File::Spec->path(), $Config::Config{'binexp'}) { if ( defined($path) && length $path && -d $path ) { my $perl = File::Spec->catfile($path,$perl_name); push @candidates, $perl; # try with extension if not provided already if ($^O eq 'VMS') { # VMS might have a file version at the end push @candidates, $perl . $exe unless $perl =~ m/$exe(;\d+)?$/i; } elsif (defined $exe && length $exe) { push @candidates, $perl . $exe unless $perl =~ m/$exe$/i; } } } } for my $perl ( @candidates ) { if (MM->maybe_command($perl) && _perl_is_same($perl)) { $^X = $perl; return $perl; } } } return $^X; # default fall back } #-> sub CPAN::exists ; sub exists { my($mgr,$class,$id) = @_; CPAN::HandleConfig->load unless $CPAN::Config_loaded++; CPAN::Index->reload; ### Carp::croak "exists called without class argument" unless $class; $id ||= ""; $id =~ s/:+/::/g if $class eq "CPAN::Module"; my $exists; if (CPAN::_sqlite_running) { $exists = (exists $META->{readonly}{$class}{$id} or $CPAN::SQLite->set($class, $id)); } else { $exists = exists $META->{readonly}{$class}{$id}; } $exists ||= exists $META->{readwrite}{$class}{$id}; # unsafe meta access, ok } #-> sub CPAN::delete ; sub delete { my($mgr,$class,$id) = @_; delete $META->{readonly}{$class}{$id}; # unsafe meta access, ok delete $META->{readwrite}{$class}{$id}; # unsafe meta access, ok } #-> sub CPAN::has_usable # has_inst is sometimes too optimistic, we should replace it with this # has_usable whenever a case is given sub has_usable { my($self,$mod,$message) = @_; return 1 if $HAS_USABLE->{$mod}; my $has_inst = $self->has_inst($mod,$message); return unless $has_inst; my $usable; $usable = { # # most of these subroutines warn on the frontend, then # die if the installed version is unusable for some # reason; has_usable() then returns false when it caught # an exception, otherwise returns true and caches that; # 'CPAN::Meta' => [ sub { require CPAN::Meta; unless (CPAN::Version->vge(CPAN::Meta->VERSION, 2.110350)) { for ("Will not use CPAN::Meta, need version 2.110350\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ], 'CPAN::Meta::Requirements' => [ sub { if (defined $CPAN::Meta::Requirements::VERSION && CPAN::Version->vlt($CPAN::Meta::Requirements::VERSION, "2.120920") ) { delete $INC{"CPAN/Meta/Requirements.pm"}; } require CPAN::Meta::Requirements; unless (CPAN::Version->vge(CPAN::Meta::Requirements->VERSION, 2.120920)) { for ("Will not use CPAN::Meta::Requirements, need version 2.120920\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ], 'CPAN::Reporter' => [ sub { if (defined $CPAN::Reporter::VERSION && CPAN::Version->vlt($CPAN::Reporter::VERSION, "1.2011") ) { delete $INC{"CPAN/Reporter.pm"}; } require CPAN::Reporter; unless (CPAN::Version->vge(CPAN::Reporter->VERSION, "1.2011")) { for ("Will not use CPAN::Reporter, need version 1.2011\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ], LWP => [ # we frequently had "Can't locate object # method "new" via package "LWP::UserAgent" at # (eval 69) line 2006 sub {require LWP}, sub {require LWP::UserAgent}, sub {require HTTP::Request}, sub {require URI::URL; unless (CPAN::Version->vge(URI::URL::->VERSION,0.08)) { for ("Will not use URI::URL, need 0.08\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ], 'Net::FTP' => [ sub { my $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy}; if ($var and $var =~ /^http:/i) { # rt #110833 for ("Net::FTP cannot handle http proxy") { $CPAN::Frontend->mywarn($_); die $_; } } }, sub {require Net::FTP}, sub {require Net::Config}, ], 'IO::Socket::SSL' => [ sub { require IO::Socket::SSL; unless (CPAN::Version->vge(IO::Socket::SSL::->VERSION,1.56)) { for ("Will not use IO::Socket::SSL, need 1.56\n") { $CPAN::Frontend->mywarn($_); die $_; } } } ], 'Net::SSLeay' => [ sub { require Net::SSLeay; unless (CPAN::Version->vge(Net::SSLeay::->VERSION,1.49)) { for ("Will not use Net::SSLeay, need 1.49\n") { $CPAN::Frontend->mywarn($_); die $_; } } } ], 'HTTP::Tiny' => [ sub { require HTTP::Tiny; unless (CPAN::Version->vge(HTTP::Tiny->VERSION, 0.005)) { for ("Will not use HTTP::Tiny, need version 0.005\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ], 'File::HomeDir' => [ sub {require File::HomeDir; unless (CPAN::Version->vge(File::HomeDir::->VERSION, 0.52)) { for ("Will not use File::HomeDir, need 0.52\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ], 'Archive::Tar' => [ sub {require Archive::Tar; my $demand = "1.50"; unless (CPAN::Version->vge(Archive::Tar::->VERSION, $demand)) { my $atv = Archive::Tar->VERSION; for ("You have Archive::Tar $atv, but $demand or later is recommended. Please upgrade.\n") { $CPAN::Frontend->mywarn($_); # don't die, because we may need # Archive::Tar to upgrade } } }, ], 'File::Temp' => [ # XXX we should probably delete from # %INC too so we can load after we # installed a new enough version -- # I'm not sure. sub {require File::Temp; unless (CPAN::Version->vge(File::Temp::->VERSION,0.16)) { for ("Will not use File::Temp, need 0.16\n") { $CPAN::Frontend->mywarn($_); die $_; } } }, ] }; if ($usable->{$mod}) { local @INC = @INC; pop @INC if $INC[-1] eq '.'; for my $c (0..$#{$usable->{$mod}}) { my $code = $usable->{$mod}[$c]; my $ret = eval { &$code() }; $ret = "" unless defined $ret; if ($@) { # warn "DEBUG: c[$c]\$\@[$@]ret[$ret]"; return; } } } return $HAS_USABLE->{$mod} = 1; } sub frontend { shift; $CPAN::Frontend = shift if @_; $CPAN::Frontend; } sub use_inst { my ($self, $module) = @_; unless ($self->has_inst($module)) { $self->frontend->mydie("$module not installed, cannot continue"); } } #-> sub CPAN::has_inst sub has_inst { my($self,$mod,$message) = @_; Carp::croak("CPAN->has_inst() called without an argument") unless defined $mod; my %dont = map { $_ => 1 } keys %{$CPAN::META->{dontload_hash}||{}}, keys %{$CPAN::Config->{dontload_hash}||{}}, @{$CPAN::Config->{dontload_list}||[]}; if (defined $message && $message eq "no" # as far as I remember only used by Nox || $dont{$mod} ) { $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok return 0; } local @INC = @INC; pop @INC if $INC[-1] eq '.'; my $file = $mod; my $obj; $file =~ s|::|/|g; $file .= ".pm"; if ($INC{$file}) { # checking %INC is wrong, because $INC{LWP} may be true # although $INC{"URI/URL.pm"} may have failed. But as # I really want to say "blah loaded OK", I have to somehow # cache results. ### warn "$file in %INC"; #debug return 1; } elsif (eval { require $file }) { # eval is good: if we haven't yet read the database it's # perfect and if we have installed the module in the meantime, # it tries again. The second require is only a NOOP returning # 1 if we had success, otherwise it's retrying my $mtime = (stat $INC{$file})[9]; # privileged files loaded by has_inst; Note: we use $mtime # as a proxy for a checksum. $CPAN::Shell::reload->{$file} = $mtime; my $v = eval "\$$mod\::VERSION"; $v = $v ? " (v$v)" : ""; CPAN::Shell->optprint("load_module","CPAN: $mod loaded ok$v\n"); if ($mod eq "CPAN::WAIT") { push @CPAN::Shell::ISA, 'CPAN::WAIT'; } return 1; } elsif ($mod eq "Net::FTP") { $CPAN::Frontend->mywarn(qq{ Please, install Net::FTP as soon as possible. CPAN.pm installs it for you if you just type install Bundle::libnet }) unless $Have_warned->{"Net::FTP"}++; $CPAN::Frontend->mysleep(3); } elsif ($mod eq "Digest::SHA") { if ($Have_warned->{"Digest::SHA"}++) { $CPAN::Frontend->mywarn(qq{CPAN: checksum security checks disabled }. qq{because Digest::SHA not installed.\n}); } else { $CPAN::Frontend->mywarn(qq{ CPAN: checksum security checks disabled because Digest::SHA not installed. Please consider installing the Digest::SHA module. }); $CPAN::Frontend->mysleep(2); } } elsif ($mod eq "Module::Signature") { # NOT prefs_lookup, we are not a distro my $check_sigs = $CPAN::Config->{check_sigs}; if (not $check_sigs) { # they do not want us:-( } elsif (not $Have_warned->{"Module::Signature"}++) { # No point in complaining unless the user can # reasonably install and use it. if (eval { require Crypt::OpenPGP; 1 } || ( defined $CPAN::Config->{'gpg'} && $CPAN::Config->{'gpg'} =~ /\S/ ) ) { $CPAN::Frontend->mywarn(qq{ CPAN: Module::Signature security checks disabled because Module::Signature not installed. Please consider installing the Module::Signature module. You may also need to be able to connect over the Internet to the public key servers like pool.sks-keyservers.net or pgp.mit.edu. }); $CPAN::Frontend->mysleep(2); } } } else { delete $INC{$file}; # if it inc'd LWP but failed during, say, URI } return 0; } #-> sub CPAN::instance ; sub instance { my($mgr,$class,$id) = @_; CPAN::Index->reload; $id ||= ""; # unsafe meta access, ok? return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id}; $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id); } #-> sub CPAN::new ; sub new { bless {}, shift; } #-> sub CPAN::_exit_messages ; sub _exit_messages { my ($self) = @_; $self->{exit_messages} ||= []; } #-> sub CPAN::cleanup ; sub cleanup { # warn "cleanup called with arg[@_] End[$CPAN::End] Signal[$Signal]"; local $SIG{__DIE__} = ''; my($message) = @_; my $i = 0; my $ineval = 0; my($subroutine); while ((undef,undef,undef,$subroutine) = caller(++$i)) { $ineval = 1, last if $subroutine eq '(eval)'; } return if $ineval && !$CPAN::End; return unless defined $META->{LOCK}; return unless -f $META->{LOCK}; $META->savehist; $META->{cachemgr} ||= CPAN::CacheMgr->new('atexit'); close $META->{LOCKFH}; unlink $META->{LOCK}; # require Carp; # Carp::cluck("DEBUGGING"); if ( $CPAN::CONFIG_DIRTY ) { $CPAN::Frontend->mywarn("Warning: Configuration not saved.\n"); } $CPAN::Frontend->myprint("Lockfile removed.\n"); for my $msg ( @{ $META->_exit_messages } ) { $CPAN::Frontend->myprint($msg); } } #-> sub CPAN::readhist sub readhist { my($self,$term,$histfile) = @_; my $histsize = $CPAN::Config->{'histsize'} || 100; $term->Attribs->{'MaxHistorySize'} = $histsize if (defined($term->Attribs->{'MaxHistorySize'})); my($fh) = FileHandle->new; open $fh, "<$histfile" or return; local $/ = "\n"; while (<$fh>) { chomp; $term->AddHistory($_); } close $fh; } #-> sub CPAN::savehist sub savehist { my($self) = @_; my($histfile,$histsize); unless ($histfile = $CPAN::Config->{'histfile'}) { $CPAN::Frontend->mywarn("No history written (no histfile specified).\n"); return; } $histsize = $CPAN::Config->{'histsize'} || 100; if ($CPAN::term) { unless ($CPAN::term->can("GetHistory")) { $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n"); return; } } else { return; } my @h = $CPAN::term->GetHistory; splice @h, 0, @h-$histsize if @h>$histsize; my($fh) = FileHandle->new; open $fh, ">$histfile" or $CPAN::Frontend->mydie("Couldn't open >$histfile: $!"); local $\ = local $, = "\n"; print $fh @h; close $fh; } #-> sub CPAN::is_tested sub is_tested { my($self,$what,$when) = @_; unless ($what) { Carp::cluck("DEBUG: empty what"); return; } $self->{is_tested}{$what} = $when; } #-> sub CPAN::reset_tested # forget all distributions tested -- resets what gets included in PERL5LIB sub reset_tested { my ($self) = @_; $self->{is_tested} = {}; } #-> sub CPAN::is_installed # unsets the is_tested flag: as soon as the thing is installed, it is # not needed in set_perl5lib anymore sub is_installed { my($self,$what) = @_; delete $self->{is_tested}{$what}; } sub _list_sorted_descending_is_tested { my($self) = @_; my $foul = 0; my @sorted = sort { ($self->{is_tested}{$b}||0) <=> ($self->{is_tested}{$a}||0) } grep { if ($foul){ 0 } elsif (-e) { 1 } else { $foul = $_; 0 } } keys %{$self->{is_tested}}; if ($foul) { $CPAN::Frontend->mywarn("Lost build_dir detected ($foul), giving up all cached test results of currently running session.\n"); for my $dbd (sort keys %{$self->{is_tested}}) { # distro-build-dir SEARCH: for my $d (sort { $a->id cmp $b->id } $CPAN::META->all_objects("CPAN::Distribution")) { if ($d->{build_dir} && $d->{build_dir} eq $dbd) { $CPAN::Frontend->mywarn(sprintf "Flushing cache for %s\n", $d->pretty_id); $d->fforce(""); last SEARCH; } } delete $self->{is_tested}{$dbd}; } return (); } else { return @sorted; } } #-> sub CPAN::set_perl5lib # Notes on max environment variable length: # - Win32 : XP or later, 8191; Win2000 or NT4, 2047 { my $fh; sub set_perl5lib { my($self,$for) = @_; unless ($for) { (undef,undef,undef,$for) = caller(1); $for =~ s/.*://; } $self->{is_tested} ||= {}; return unless %{$self->{is_tested}}; my $env = $ENV{PERL5LIB}; $env = $ENV{PERLLIB} unless defined $env; my @env; push @env, split /\Q$Config::Config{path_sep}\E/, $env if defined $env and length $env; #my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}}; #$CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n"); my @dirs = map {("$_/blib/arch", "$_/blib/lib")} $self->_list_sorted_descending_is_tested; return if !@dirs; if (@dirs < 12) { $CPAN::Frontend->optprint('perl5lib', "Prepending @dirs to PERL5LIB for '$for'\n"); $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; } elsif (@dirs < 24 ) { my @d = map {my $cp = $_; $cp =~ s/^\Q$CPAN::Config->{build_dir}\E/%BUILDDIR%/; $cp } @dirs; $CPAN::Frontend->optprint('perl5lib', "Prepending @d to PERL5LIB; ". "%BUILDDIR%=$CPAN::Config->{build_dir} ". "for '$for'\n" ); $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; } else { my $cnt = keys %{$self->{is_tested}}; my $newenv = join $Config::Config{path_sep}, @dirs, @env; $CPAN::Frontend->optprint('perl5lib', sprintf ("Prepending blib/arch and blib/lib of ". "%d build dirs to PERL5LIB, reaching size %d; ". "for '%s'\n", $cnt, length($newenv), $for) ); $ENV{PERL5LIB} = $newenv; } }} 1; __END__ =head1 NAME CPAN - query, download and build perl modules from CPAN sites =head1 SYNOPSIS Interactive mode: perl -MCPAN -e shell --or-- cpan Basic commands: # Modules: cpan> install Acme::Meta # in the shell CPAN::Shell->install("Acme::Meta"); # in perl # Distributions: cpan> install NWCLARK/Acme-Meta-0.02.tar.gz # in the shell CPAN::Shell-> install("NWCLARK/Acme-Meta-0.02.tar.gz"); # in perl # module objects: $mo = CPAN::Shell->expandany($mod); $mo = CPAN::Shell->expand("Module",$mod); # same thing # distribution objects: $do = CPAN::Shell->expand("Module",$mod)->distribution; $do = CPAN::Shell->expandany($distro); # same thing $do = CPAN::Shell->expand("Distribution", $distro); # same thing =head1 DESCRIPTION The CPAN module automates or at least simplifies the make and install of perl modules and extensions. It includes some primitive searching capabilities and knows how to use LWP, HTTP::Tiny, Net::FTP and certain external download clients to fetch distributions from the net. These are fetched from one or more mirrored CPAN (Comprehensive Perl Archive Network) sites and unpacked in a dedicated directory. The CPAN module also supports named and versioned I<bundles> of modules. Bundles simplify handling of sets of related modules. See Bundles below. The package contains a session manager and a cache manager. The session manager keeps track of what has been fetched, built, and installed in the current session. The cache manager keeps track of the disk space occupied by the make processes and deletes excess space using a simple FIFO mechanism. All methods provided are accessible in a programmer style and in an interactive shell style. =head2 CPAN::shell([$prompt, $command]) Starting Interactive Mode Enter interactive mode by running perl -MCPAN -e shell or cpan which puts you into a readline interface. If C<Term::ReadKey> and either of C<Term::ReadLine::Perl> or C<Term::ReadLine::Gnu> are installed, history and command completion are supported. Once at the command line, type C<h> for one-page help screen; the rest should be self-explanatory. The function call C<shell> takes two optional arguments: one the prompt, the second the default initial command line (the latter only works if a real ReadLine interface module is installed). The most common uses of the interactive modes are =over 2 =item Searching for authors, bundles, distribution files and modules There are corresponding one-letter commands C<a>, C<b>, C<d>, and C<m> for each of the four categories and another, C<i> for any of the mentioned four. Each of the four entities is implemented as a class with slightly differing methods for displaying an object. Arguments to these commands are either strings exactly matching the identification string of an object, or regular expressions matched case-insensitively against various attributes of the objects. The parser only recognizes a regular expression when you enclose it with slashes. The principle is that the number of objects found influences how an item is displayed. If the search finds one item, the result is displayed with the rather verbose method C<as_string>, but if more than one is found, each object is displayed with the terse method C<as_glimpse>. Examples: cpan> m Acme::MetaSyntactic Module id = Acme::MetaSyntactic CPAN_USERID BOOK (Philippe Bruhat (BooK) <[...]>) CPAN_VERSION 0.99 CPAN_FILE B/BO/BOOK/Acme-MetaSyntactic-0.99.tar.gz UPLOAD_DATE 2006-11-06 MANPAGE Acme::MetaSyntactic - Themed metasyntactic variables names INST_FILE /usr/local/lib/perl/5.10.0/Acme/MetaSyntactic.pm INST_VERSION 0.99 cpan> a BOOK Author id = BOOK EMAIL [...] FULLNAME Philippe Bruhat (BooK) cpan> d BOOK/Acme-MetaSyntactic-0.99.tar.gz Distribution id = B/BO/BOOK/Acme-MetaSyntactic-0.99.tar.gz CPAN_USERID BOOK (Philippe Bruhat (BooK) <[...]>) CONTAINSMODS Acme::MetaSyntactic Acme::MetaSyntactic::Alias [...] UPLOAD_DATE 2006-11-06 cpan> m /lorem/ Module = Acme::MetaSyntactic::loremipsum (BOOK/Acme-MetaSyntactic-0.99.tar.gz) Module Text::Lorem (ADEOLA/Text-Lorem-0.3.tar.gz) Module Text::Lorem::More (RKRIMEN/Text-Lorem-More-0.12.tar.gz) Module Text::Lorem::More::Source (RKRIMEN/Text-Lorem-More-0.12.tar.gz) cpan> i /berlin/ Distribution BEATNIK/Filter-NumberLines-0.02.tar.gz Module = DateTime::TimeZone::Europe::Berlin (DROLSKY/DateTime-TimeZone-0.7904.tar.gz) Module Filter::NumberLines (BEATNIK/Filter-NumberLines-0.02.tar.gz) Author [...] The examples illustrate several aspects: the first three queries target modules, authors, or distros directly and yield exactly one result. The last two use regular expressions and yield several results. The last one targets all of bundles, modules, authors, and distros simultaneously. When more than one result is available, they are printed in one-line format. =item C<get>, C<make>, C<test>, C<install>, C<clean> modules or distributions These commands take any number of arguments and investigate what is necessary to perform the action. Argument processing is as follows: known module name in format Foo/Bar.pm module other embedded slash distribution - with trailing slash dot directory enclosing slashes regexp known module name in format Foo::Bar module If the argument is a distribution file name (recognized by embedded slashes), it is processed. If it is a module, CPAN determines the distribution file in which this module is included and processes that, following any dependencies named in the module's META.yml or Makefile.PL (this behavior is controlled by the configuration parameter C<prerequisites_policy>). If an argument is enclosed in slashes it is treated as a regular expression: it is expanded and if the result is a single object (distribution, bundle or module), this object is processed. Example: install Dummy::Perl # installs the module install AUXXX/Dummy-Perl-3.14.tar.gz # installs that distribution install /Dummy-Perl-3.14/ # same if the regexp is unambiguous C<get> downloads a distribution file and untars or unzips it, C<make> builds it, C<test> runs the test suite, and C<install> installs it. Any C<make> or C<test> is run unconditionally. An install <distribution_file> is also run unconditionally. But for install <module> CPAN checks whether an install is needed and prints I<module up to date> if the distribution file containing the module doesn't need updating. CPAN also keeps track of what it has done within the current session and doesn't try to build a package a second time regardless of whether it succeeded or not. It does not repeat a test run if the test has been run successfully before. Same for install runs. The C<force> pragma may precede another command (currently: C<get>, C<make>, C<test>, or C<install>) to execute the command from scratch and attempt to continue past certain errors. See the section below on the C<force> and the C<fforce> pragma. The C<notest> pragma skips the test part in the build process. Example: cpan> notest install Tk A C<clean> command results in a make clean being executed within the distribution file's working directory. =item C<readme>, C<perldoc>, C<look> module or distribution C<readme> displays the README file of the associated distribution. C<Look> gets and untars (if not yet done) the distribution file, changes to the appropriate directory and opens a subshell process in that directory. C<perldoc> displays the module's pod documentation in html or plain text format. =item C<ls> author =item C<ls> globbing_expression The first form lists all distribution files in and below an author's CPAN directory as stored in the CHECKSUMS files distributed on CPAN. The listing recurses into subdirectories. The second form limits or expands the output with shell globbing as in the following examples: ls JV/make* ls GSAR/*make* ls */*make* The last example is very slow and outputs extra progress indicators that break the alignment of the result. Note that globbing only lists directories explicitly asked for, for example FOO/* will not list FOO/bar/Acme-Sthg-n.nn.tar.gz. This may be regarded as a bug that may be changed in some future version. =item C<failed> The C<failed> command reports all distributions that failed on one of C<make>, C<test> or C<install> for some reason in the currently running shell session. =item Persistence between sessions If the C<YAML> or the C<YAML::Syck> module is installed a record of the internal state of all modules is written to disk after each step. The files contain a signature of the currently running perl version for later perusal. If the configurations variable C<build_dir_reuse> is set to a true value, then CPAN.pm reads the collected YAML files. If the stored signature matches the currently running perl, the stored state is loaded into memory such that persistence between sessions is effectively established. =item The C<force> and the C<fforce> pragma To speed things up in complex installation scenarios, CPAN.pm keeps track of what it has already done and refuses to do some things a second time. A C<get>, a C<make>, and an C<install> are not repeated. A C<test> is repeated only if the previous test was unsuccessful. The diagnostic message when CPAN.pm refuses to do something a second time is one of I<Has already been >C<unwrapped|made|tested successfully> or something similar. Another situation where CPAN refuses to act is an C<install> if the corresponding C<test> was not successful. In all these cases, the user can override this stubborn behaviour by prepending the command with the word force, for example: cpan> force get Foo cpan> force make AUTHOR/Bar-3.14.tar.gz cpan> force test Baz cpan> force install Acme::Meta Each I<forced> command is executed with the corresponding part of its memory erased. The C<fforce> pragma is a variant that emulates a C<force get> which erases the entire memory followed by the action specified, effectively restarting the whole get/make/test/install procedure from scratch. =item Lockfile Interactive sessions maintain a lockfile, by default C<~/.cpan/.lock>. Batch jobs can run without a lockfile and not disturb each other. The shell offers to run in I<downgraded mode> when another process is holding the lockfile. This is an experimental feature that is not yet tested very well. This second shell then does not write the history file, does not use the metadata file, and has a different prompt. =item Signals CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are in the cpan-shell, it is intended that you can press C<^C> anytime and return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell to clean up and leave the shell loop. You can emulate the effect of a SIGTERM by sending two consecutive SIGINTs, which usually means by pressing C<^C> twice. CPAN.pm ignores SIGPIPE. If the user sets C<inactivity_timeout>, a SIGALRM is used during the run of the C<perl Makefile.PL> or C<perl Build.PL> subprocess. A SIGALRM is also used during module version parsing, and is controlled by C<version_timeout>. =back =head2 CPAN::Shell The commands available in the shell interface are methods in the package CPAN::Shell. If you enter the shell command, your input is split by the Text::ParseWords::shellwords() routine, which acts like most shells do. The first word is interpreted as the method to be invoked, and the rest of the words are treated as the method's arguments. Continuation lines are supported by ending a line with a literal backslash. =head2 autobundle C<autobundle> writes a bundle file into the C<$CPAN::Config-E<gt>{cpan_home}/Bundle> directory. The file contains a list of all modules that are both available from CPAN and currently installed within @INC. Duplicates of each distribution are suppressed. The name of the bundle file is based on the current date and a counter, e.g. F<Bundle/Snapshot_2012_05_21_00.pm>. This is installed again by running C<cpan Bundle::Snapshot_2012_05_21_00>, or installing C<Bundle::Snapshot_2012_05_21_00> from the CPAN shell. Return value: path to the written file. =head2 hosts Note: this feature is still in alpha state and may change in future versions of CPAN.pm This commands provides a statistical overview over recent download activities. The data for this is collected in the YAML file C<FTPstats.yml> in your C<cpan_home> directory. If no YAML module is configured or YAML not installed, no stats are provided. =over =item install_tested Install all distributions that have been tested successfully but have not yet been installed. See also C<is_tested>. =item is_tested List all build directories of distributions that have been tested successfully but have not yet been installed. See also C<install_tested>. =back =head2 mkmyconfig mkmyconfig() writes your own CPAN::MyConfig file into your C<~/.cpan/> directory so that you can save your own preferences instead of the system-wide ones. =head2 r [Module|/Regexp/]... scans current perl installation for modules that have a newer version available on CPAN and provides a list of them. If called without argument, all potential upgrades are listed; if called with arguments the list is filtered to the modules and regexps given as arguments. The listing looks something like this: Package namespace installed latest in CPAN file CPAN 1.94_64 1.9600 ANDK/CPAN-1.9600.tar.gz CPAN::Reporter 1.1801 1.1902 DAGOLDEN/CPAN-Reporter-1.1902.tar.gz YAML 0.70 0.73 INGY/YAML-0.73.tar.gz YAML::Syck 1.14 1.17 AVAR/YAML-Syck-1.17.tar.gz YAML::Tiny 1.44 1.50 ADAMK/YAML-Tiny-1.50.tar.gz CGI 3.43 3.55 MARKSTOS/CGI.pm-3.55.tar.gz Module::Build::YAML 1.40 1.41 DAGOLDEN/Module-Build-0.3800.tar.gz TAP::Parser::Result::YAML 3.22 3.23 ANDYA/Test-Harness-3.23.tar.gz YAML::XS 0.34 0.35 INGY/YAML-LibYAML-0.35.tar.gz It suppresses duplicates in the column C<in CPAN file> such that distributions with many upgradeable modules are listed only once. Note that the list is not sorted. =head2 recent ***EXPERIMENTAL COMMAND*** The C<recent> command downloads a list of recent uploads to CPAN and displays them I<slowly>. While the command is running, a $SIG{INT} exits the loop after displaying the current item. B<Note>: This command requires XML::LibXML installed. B<Note>: This whole command currently is just a hack and will probably change in future versions of CPAN.pm, but the general approach will likely remain. B<Note>: See also L<smoke> =head2 recompile recompile() is a special command that takes no argument and runs the make/test/install cycle with brute force over all installed dynamically loadable extensions (a.k.a. XS modules) with 'force' in effect. The primary purpose of this command is to finish a network installation. Imagine you have a common source tree for two different architectures. You decide to do a completely independent fresh installation. You start on one architecture with the help of a Bundle file produced earlier. CPAN installs the whole Bundle for you, but when you try to repeat the job on the second architecture, CPAN responds with a C<"Foo up to date"> message for all modules. So you invoke CPAN's recompile on the second architecture and you're done. Another popular use for C<recompile> is to act as a rescue in case your perl breaks binary compatibility. If one of the modules that CPAN uses is in turn depending on binary compatibility (so you cannot run CPAN commands), then you should try the CPAN::Nox module for recovery. =head2 report Bundle|Distribution|Module The C<report> command temporarily turns on the C<test_report> config variable, then runs the C<force test> command with the given arguments. The C<force> pragma reruns the tests and repeats every step that might have failed before. =head2 smoke ***EXPERIMENTAL COMMAND*** B<*** WARNING: this command downloads and executes software from CPAN to your computer of completely unknown status. You should never do this with your normal account and better have a dedicated well separated and secured machine to do this. ***> The C<smoke> command takes the list of recent uploads to CPAN as provided by the C<recent> command and tests them all. While the command is running $SIG{INT} is defined to mean that the current item shall be skipped. B<Note>: This whole command currently is just a hack and will probably change in future versions of CPAN.pm, but the general approach will likely remain. B<Note>: See also L<recent> =head2 upgrade [Module|/Regexp/]... The C<upgrade> command first runs an C<r> command with the given arguments and then installs the newest versions of all modules that were listed by that. =head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution Although it may be considered internal, the class hierarchy does matter for both users and programmer. CPAN.pm deals with the four classes mentioned above, and those classes all share a set of methods. Classical single polymorphism is in effect. A metaclass object registers all objects of all kinds and indexes them with a string. The strings referencing objects have a separated namespace (well, not completely separated): Namespace Class words containing a "/" (slash) Distribution words starting with Bundle:: Bundle everything else Module or Author Modules know their associated Distribution objects. They always refer to the most recent official release. Developers may mark their releases as unstable development versions (by inserting an underscore into the module version number which will also be reflected in the distribution name when you run 'make dist'), so the really hottest and newest distribution is not always the default. If a module Foo circulates on CPAN in both version 1.23 and 1.23_90, CPAN.pm offers a convenient way to install version 1.23 by saying install Foo This would install the complete distribution file (say BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would like to install version 1.23_90, you need to know where the distribution file resides on CPAN relative to the authors/id/ directory. If the author is BAR, this might be BAR/Foo-1.23_90.tar.gz; so you would have to say install BAR/Foo-1.23_90.tar.gz The first example will be driven by an object of the class CPAN::Module, the second by an object of class CPAN::Distribution. =head2 Integrating local directories Note: this feature is still in alpha state and may change in future versions of CPAN.pm Distribution objects are normally distributions from the CPAN, but there is a slightly degenerate case for Distribution objects, too, of projects held on the local disk. These distribution objects have the same name as the local directory and end with a dot. A dot by itself is also allowed for the current directory at the time CPAN.pm was used. All actions such as C<make>, C<test>, and C<install> are applied directly to that directory. This gives the command C<cpan .> an interesting touch: while the normal mantra of installing a CPAN module without CPAN.pm is one of perl Makefile.PL perl Build.PL ( go and get prerequisites ) make ./Build make test ./Build test make install ./Build install the command C<cpan .> does all of this at once. It figures out which of the two mantras is appropriate, fetches and installs all prerequisites, takes care of them recursively, and finally finishes the installation of the module in the current directory, be it a CPAN module or not. The typical usage case is for private modules or working copies of projects from remote repositories on the local disk. =head2 Redirection The usual shell redirection symbols C< | > and C<< > >> are recognized by the cpan shell B<only when surrounded by whitespace>. So piping to pager or redirecting output into a file works somewhat as in a normal shell, with the stipulation that you must type extra spaces. =head2 Plugin support ***EXPERIMENTAL*** Plugins are objects that implement any of currently eight methods: pre_get post_get pre_make post_make pre_test post_test pre_install post_install The C<plugin_list> configuration parameter holds a list of strings of the form Modulename=arg0,arg1,arg2,arg3,... eg: CPAN::Plugin::Flurb=dir,/opt/pkgs/flurb/raw,verbose,1 At run time, each listed plugin is instantiated as a singleton object by running the equivalent of this pseudo code: my $plugin = <string representation from config>; <generate Modulename and arguments from $plugin>; my $p = $instance{$plugin} ||= Modulename->new($arg0,$arg1,...); The generated singletons are kept around from instantiation until the end of the shell session. <plugin_list> can be reconfigured at any time at run time. While the cpan shell is running, it checks all activated plugins at each of the 8 reference points listed above and runs the respective method if it is implemented for that object. The method is called with the active CPAN::Distribution object passed in as an argument. =head1 CONFIGURATION When the CPAN module is used for the first time, a configuration dialogue tries to determine a couple of site specific options. The result of the dialog is stored in a hash reference C< $CPAN::Config > in a file CPAN/Config.pm. Default values defined in the CPAN/Config.pm file can be overridden in a user specific file: CPAN/MyConfig.pm. Such a file is best placed in C<$HOME/.cpan/CPAN/MyConfig.pm>, because C<$HOME/.cpan> is added to the search path of the CPAN module before the use() or require() statements. The mkmyconfig command writes this file for you. The C<o conf> command has various bells and whistles: =over =item completion support If you have a ReadLine module installed, you can hit TAB at any point of the commandline and C<o conf> will offer you completion for the built-in subcommands and/or config variable names. =item displaying some help: o conf help Displays a short help =item displaying current values: o conf [KEY] Displays the current value(s) for this config variable. Without KEY, displays all subcommands and config variables. Example: o conf shell If KEY starts and ends with a slash, the string in between is treated as a regular expression and only keys matching this regexp are displayed Example: o conf /color/ =item changing of scalar values: o conf KEY VALUE Sets the config variable KEY to VALUE. The empty string can be specified as usual in shells, with C<''> or C<""> Example: o conf wget /usr/bin/wget =item changing of list values: o conf KEY SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST If a config variable name ends with C<list>, it is a list. C<o conf KEY shift> removes the first element of the list, C<o conf KEY pop> removes the last element of the list. C<o conf KEYS unshift LIST> prepends a list of values to the list, C<o conf KEYS push LIST> appends a list of valued to the list. Likewise, C<o conf KEY splice LIST> passes the LIST to the corresponding splice command. Finally, any other list of arguments is taken as a new list value for the KEY variable discarding the previous value. Examples: o conf urllist unshift http://cpan.dev.local/CPAN o conf urllist splice 3 1 o conf urllist http://cpan1.local http://cpan2.local ftp://ftp.perl.org =item reverting to saved: o conf defaults Reverts all config variables to the state in the saved config file. =item saving the config: o conf commit Saves all config variables to the current config file (CPAN/Config.pm or CPAN/MyConfig.pm that was loaded at start). =back The configuration dialog can be started any time later again by issuing the command C< o conf init > in the CPAN shell. A subset of the configuration dialog can be run by issuing C<o conf init WORD> where WORD is any valid config variable or a regular expression. =head2 Config Variables The following keys in the hash reference $CPAN::Config are currently defined: allow_installing_module_downgrades allow or disallow installing module downgrades allow_installing_outdated_dists allow or disallow installing modules that are indexed in the cpan index pointing to a distro with a higher distro-version number applypatch path to external prg auto_commit commit all changes to config variables to disk build_cache size of cache for directories to build modules build_dir locally accessible directory to build modules build_dir_reuse boolean if distros in build_dir are persistent build_requires_install_policy to install or not to install when a module is only needed for building. yes|no|ask/yes|ask/no bzip2 path to external prg cache_metadata use serializer to cache metadata check_sigs if signatures should be verified cleanup_after_install remove build directory immediately after a successful install and remember that for the duration of the session colorize_debug Term::ANSIColor attributes for debugging output colorize_output boolean if Term::ANSIColor should colorize output colorize_print Term::ANSIColor attributes for normal output colorize_warn Term::ANSIColor attributes for warnings commandnumber_in_prompt boolean if you want to see current command number commands_quote preferred character to use for quoting external commands when running them. Defaults to double quote on Windows, single tick everywhere else; can be set to space to disable quoting connect_to_internet_ok whether to ask if opening a connection is ok before urllist is specified cpan_home local directory reserved for this package curl path to external prg dontload_hash DEPRECATED dontload_list arrayref: modules in the list will not be loaded by the CPAN::has_inst() routine ftp path to external prg ftp_passive if set, the environment variable FTP_PASSIVE is set for downloads ftp_proxy proxy host for ftp requests ftpstats_period max number of days to keep download statistics ftpstats_size max number of items to keep in the download statistics getcwd see below gpg path to external prg gzip location of external program gzip halt_on_failure stop processing after the first failure of queued items or dependencies histfile file to maintain history between sessions histsize maximum number of lines to keep in histfile http_proxy proxy host for http requests inactivity_timeout breaks interactive Makefile.PLs or Build.PLs after this many seconds inactivity. Set to 0 to disable timeouts. index_expire refetch index files after this many days inhibit_startup_message if true, suppress the startup message keep_source_where directory in which to keep the source (if we do) load_module_verbosity report loading of optional modules used by CPAN.pm lynx path to external prg make location of external make program make_arg arguments that should always be passed to 'make' make_install_make_command the make command for running 'make install', for example 'sudo make' make_install_arg same as make_arg for 'make install' makepl_arg arguments passed to 'perl Makefile.PL' mbuild_arg arguments passed to './Build' mbuild_install_arg arguments passed to './Build install' mbuild_install_build_command command to use instead of './Build' when we are in the install stage, for example 'sudo ./Build' mbuildpl_arg arguments passed to 'perl Build.PL' ncftp path to external prg ncftpget path to external prg no_proxy don't proxy to these hosts/domains (comma separated list) pager location of external program more (or any pager) password your password if you CPAN server wants one patch path to external prg patches_dir local directory containing patch files perl5lib_verbosity verbosity level for PERL5LIB additions plugin_list list of active hooks (see Plugin support above and the CPAN::Plugin module) prefer_external_tar per default all untar operations are done with Archive::Tar; by setting this variable to true the external tar command is used if available prefer_installer legal values are MB and EUMM: if a module comes with both a Makefile.PL and a Build.PL, use the former (EUMM) or the latter (MB); if the module comes with only one of the two, that one will be used no matter the setting prerequisites_policy what to do if you are missing module prerequisites ('follow' automatically, 'ask' me, or 'ignore') For 'follow', also sets PERL_AUTOINSTALL and PERL_EXTUTILS_AUTOINSTALL for "--defaultdeps" if not already set prefs_dir local directory to store per-distro build options proxy_user username for accessing an authenticating proxy proxy_pass password for accessing an authenticating proxy pushy_https use https to cpan.org when possible, otherwise use http to cpan.org and issue a warning randomize_urllist add some randomness to the sequence of the urllist recommends_policy whether recommended prerequisites should be included scan_cache controls scanning of cache ('atstart', 'atexit' or 'never') shell your favorite shell show_unparsable_versions boolean if r command tells which modules are versionless show_upload_date boolean if commands should try to determine upload date show_zero_versions boolean if r command tells for which modules $version==0 suggests_policy whether suggested prerequisites should be included tar location of external program tar tar_verbosity verbosity level for the tar command term_is_latin deprecated: if true Unicode is translated to ISO-8859-1 (and nonsense for characters outside latin range) term_ornaments boolean to turn ReadLine ornamenting on/off test_report email test reports (if CPAN::Reporter is installed) trust_test_report_history skip testing when previously tested ok (according to CPAN::Reporter history) unzip location of external program unzip urllist arrayref to nearby CPAN sites (or equivalent locations) urllist_ping_external use external ping command when autoselecting mirrors urllist_ping_verbose increase verbosity when autoselecting mirrors use_prompt_default set PERL_MM_USE_DEFAULT for configure/make/test/install use_sqlite use CPAN::SQLite for metadata storage (fast and lean) username your username if you CPAN server wants one version_timeout stops version parsing after this many seconds. Default is 15 secs. Set to 0 to disable. wait_list arrayref to a wait server to try (See CPAN::WAIT) wget path to external prg yaml_load_code enable YAML code deserialisation via CPAN::DeferredCode yaml_module which module to use to read/write YAML files You can set and query each of these options interactively in the cpan shell with the C<o conf> or the C<o conf init> command as specified below. =over 2 =item C<o conf E<lt>scalar optionE<gt>> prints the current value of the I<scalar option> =item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>> Sets the value of the I<scalar option> to I<value> =item C<o conf E<lt>list optionE<gt>> prints the current value of the I<list option> in MakeMaker's neatvalue format. =item C<o conf E<lt>list optionE<gt> [shift|pop]> shifts or pops the array in the I<list option> variable =item C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>> works like the corresponding perl commands. =item interactive editing: o conf init [MATCH|LIST] Runs an interactive configuration dialog for matching variables. Without argument runs the dialog over all supported config variables. To specify a MATCH the argument must be enclosed by slashes. Examples: o conf init ftp_passive ftp_proxy o conf init /color/ Note: this method of setting config variables often provides more explanation about the functioning of a variable than the manpage. =back =head2 CPAN::anycwd($path): Note on config variable getcwd CPAN.pm changes the current working directory often and needs to determine its own current working directory. By default it uses Cwd::cwd, but if for some reason this doesn't work on your system, configure alternatives according to the following table: =over 4 =item cwd Calls Cwd::cwd =item getcwd Calls Cwd::getcwd =item fastcwd Calls Cwd::fastcwd =item getdcwd Calls Cwd::getdcwd =item backtickcwd Calls the external command cwd. =back =head2 Note on the format of the urllist parameter urllist parameters are URLs according to RFC 1738. We do a little guessing if your URL is not compliant, but if you have problems with C<file> URLs, please try the correct format. Either: file://localhost/whatever/ftp/pub/CPAN/ or file:///home/ftp/pub/CPAN/ =head2 The urllist parameter has CD-ROM support The C<urllist> parameter of the configuration table contains a list of URLs used for downloading. If the list contains any C<file> URLs, CPAN always tries there first. This feature is disabled for index files. So the recommendation for the owner of a CD-ROM with CPAN contents is: include your local, possibly outdated CD-ROM as a C<file> URL at the end of urllist, e.g. o conf urllist push file://localhost/CDROM/CPAN CPAN.pm will then fetch the index files from one of the CPAN sites that come at the beginning of urllist. It will later check for each module to see whether there is a local copy of the most recent version. Another peculiarity of urllist is that the site that we could successfully fetch the last file from automatically gets a preference token and is tried as the first site for the next request. So if you add a new site at runtime it may happen that the previously preferred site will be tried another time. This means that if you want to disallow a site for the next transfer, it must be explicitly removed from urllist. =head2 Maintaining the urllist parameter If you have YAML.pm (or some other YAML module configured in C<yaml_module>) installed, CPAN.pm collects a few statistical data about recent downloads. You can view the statistics with the C<hosts> command or inspect them directly by looking into the C<FTPstats.yml> file in your C<cpan_home> directory. To get some interesting statistics, it is recommended that C<randomize_urllist> be set; this introduces some amount of randomness into the URL selection. =head2 The C<requires> and C<build_requires> dependency declarations Since CPAN.pm version 1.88_51 modules declared as C<build_requires> by a distribution are treated differently depending on the config variable C<build_requires_install_policy>. By setting C<build_requires_install_policy> to C<no>, such a module is not installed. It is only built and tested, and then kept in the list of tested but uninstalled modules. As such, it is available during the build of the dependent module by integrating the path to the C<blib/arch> and C<blib/lib> directories in the environment variable PERL5LIB. If C<build_requires_install_policy> is set to C<yes>, then both modules declared as C<requires> and those declared as C<build_requires> are treated alike. By setting to C<ask/yes> or C<ask/no>, CPAN.pm asks the user and sets the default accordingly. =head2 Configuration of the allow_installing_* parameters The C<allow_installing_*> parameters are evaluated during the C<make> phase. If set to C<yes>, they allow the testing and the installation of the current distro and otherwise have no effect. If set to C<no>, they may abort the build (preventing testing and installing), depending on the contents of the C<blib/> directory. The C<blib/> directory is the directory that holds all the files that would usually be installed in the C<install> phase. C<allow_installing_outdated_dists> compares the C<blib/> directory with the CPAN index. If it finds something there that belongs, according to the index, to a different dist, it aborts the current build. C<allow_installing_module_downgrades> compares the C<blib/> directory with already installed modules, actually their version numbers, as determined by ExtUtils::MakeMaker or equivalent. If a to-be-installed module would downgrade an already installed module, the current build is aborted. An interesting twist occurs when a distroprefs document demands the installation of an outdated dist via goto while C<allow_installing_outdated_dists> forbids it. Without additional provisions, this would let the C<allow_installing_outdated_dists> win and the distroprefs lose. So the proper arrangement in such a case is to write a second distroprefs document for the distro that C<goto> points to and overrule the C<cpanconfig> there. E.g.: --- match: distribution: "^MAUKE/Keyword-Simple-0.04.tar.gz" goto: "MAUKE/Keyword-Simple-0.03.tar.gz" --- match: distribution: "^MAUKE/Keyword-Simple-0.03.tar.gz" cpanconfig: allow_installing_outdated_dists: yes =head2 Configuration for individual distributions (I<Distroprefs>) (B<Note:> This feature has been introduced in CPAN.pm 1.8854) Distributions on CPAN usually behave according to what we call the CPAN mantra. Or since the advent of Module::Build we should talk about two mantras: perl Makefile.PL perl Build.PL make ./Build make test ./Build test make install ./Build install But some modules cannot be built with this mantra. They try to get some extra data from the user via the environment, extra arguments, or interactively--thus disturbing the installation of large bundles like Phalanx100 or modules with many dependencies like Plagger. The distroprefs system of C<CPAN.pm> addresses this problem by allowing the user to specify extra informations and recipes in YAML files to either =over =item pass additional arguments to one of the four commands, =item set environment variables =item instantiate an Expect object that reads from the console, waits for some regular expressions and enters some answers =item temporarily override assorted C<CPAN.pm> configuration variables =item specify dependencies the original maintainer forgot =item disable the installation of an object altogether =back See the YAML and Data::Dumper files that come with the C<CPAN.pm> distribution in the C<distroprefs/> directory for examples. =head2 Filenames The YAML files themselves must have the C<.yml> extension; all other files are ignored (for two exceptions see I<Fallback Data::Dumper and Storable> below). The containing directory can be specified in C<CPAN.pm> in the C<prefs_dir> config variable. Try C<o conf init prefs_dir> in the CPAN shell to set and activate the distroprefs system. Every YAML file may contain arbitrary documents according to the YAML specification, and every document is treated as an entity that can specify the treatment of a single distribution. Filenames can be picked arbitrarily; C<CPAN.pm> always reads all files (in alphabetical order) and takes the key C<match> (see below in I<Language Specs>) as a hashref containing match criteria that determine if the current distribution matches the YAML document or not. =head2 Fallback Data::Dumper and Storable If neither your configured C<yaml_module> nor YAML.pm is installed, CPAN.pm falls back to using Data::Dumper and Storable and looks for files with the extensions C<.dd> or C<.st> in the C<prefs_dir> directory. These files are expected to contain one or more hashrefs. For Data::Dumper generated files, this is expected to be done with by defining C<$VAR1>, C<$VAR2>, etc. The YAML shell would produce these with the command ysh < somefile.yml > somefile.dd For Storable files the rule is that they must be constructed such that C<Storable::retrieve(file)> returns an array reference and the array elements represent one distropref object each. The conversion from YAML would look like so: perl -MYAML=LoadFile -MStorable=nstore -e ' @y=LoadFile(shift); nstore(\@y, shift)' somefile.yml somefile.st In bootstrapping situations it is usually sufficient to translate only a few YAML files to Data::Dumper for crucial modules like C<YAML::Syck>, C<YAML.pm> and C<Expect.pm>. If you prefer Storable over Data::Dumper, remember to pull out a Storable version that writes an older format than all the other Storable versions that will need to read them. =head2 Blueprint The following example contains all supported keywords and structures with the exception of C<eexpect> which can be used instead of C<expect>. --- comment: "Demo" match: module: "Dancing::Queen" distribution: "^CHACHACHA/Dancing-" not_distribution: "\.zip$" perl: "/usr/local/cariba-perl/bin/perl" perlconfig: archname: "freebsd" not_cc: "gcc" env: DANCING_FLOOR: "Shubiduh" disabled: 1 cpanconfig: make: gmake pl: args: - "--somearg=specialcase" env: {} expect: - "Which is your favorite fruit" - "apple\n" make: args: - all - extra-all env: {} expect: [] commandline: "echo SKIPPING make" test: args: [] env: {} expect: [] install: args: [] env: WANT_TO_INSTALL: YES expect: - "Do you really want to install" - "y\n" patches: - "ABCDE/Fedcba-3.14-ABCDE-01.patch" depends: configure_requires: LWP: 5.8 build_requires: Test::Exception: 0.25 requires: Spiffy: 0.30 =head2 Language Specs Every YAML document represents a single hash reference. The valid keys in this hash are as follows: =over =item comment [scalar] A comment =item cpanconfig [hash] Temporarily override assorted C<CPAN.pm> configuration variables. Supported are: C<build_requires_install_policy>, C<check_sigs>, C<make>, C<make_install_make_command>, C<prefer_installer>, C<test_report>. Please report as a bug when you need another one supported. =item depends [hash] *** EXPERIMENTAL FEATURE *** All three types, namely C<configure_requires>, C<build_requires>, and C<requires> are supported in the way specified in the META.yml specification. The current implementation I<merges> the specified dependencies with those declared by the package maintainer. In a future implementation this may be changed to override the original declaration. =item disabled [boolean] Specifies that this distribution shall not be processed at all. =item features [array] *** EXPERIMENTAL FEATURE *** Experimental implementation to deal with optional_features from META.yml. Still needs coordination with installer software and currently works only for META.yml declaring C<dynamic_config=0>. Use with caution. =item goto [string] The canonical name of a delegate distribution to install instead. Useful when a new version, although it tests OK itself, breaks something else or a developer release or a fork is already uploaded that is better than the last released version. =item install [hash] Processing instructions for the C<make install> or C<./Build install> phase of the CPAN mantra. See below under I<Processing Instructions>. =item make [hash] Processing instructions for the C<make> or C<./Build> phase of the CPAN mantra. See below under I<Processing Instructions>. =item match [hash] A hashref with one or more of the keys C<distribution>, C<module>, C<perl>, C<perlconfig>, and C<env> that specify whether a document is targeted at a specific CPAN distribution or installation. Keys prefixed with C<not_> negates the corresponding match. The corresponding values are interpreted as regular expressions. The C<distribution> related one will be matched against the canonical distribution name, e.g. "AUTHOR/Foo-Bar-3.14.tar.gz". The C<module> related one will be matched against I<all> modules contained in the distribution until one module matches. The C<perl> related one will be matched against C<$^X> (but with the absolute path). The value associated with C<perlconfig> is itself a hashref that is matched against corresponding values in the C<%Config::Config> hash living in the C<Config.pm> module. Keys prefixed with C<not_> negates the corresponding match. The value associated with C<env> is itself a hashref that is matched against corresponding values in the C<%ENV> hash. Keys prefixed with C<not_> negates the corresponding match. If more than one restriction of C<module>, C<distribution>, etc. is specified, the results of the separately computed match values must all match. If so, the hashref represented by the YAML document is returned as the preference structure for the current distribution. =item patches [array] An array of patches on CPAN or on the local disk to be applied in order via an external patch program. If the value for the C<-p> parameter is C<0> or C<1> is determined by reading the patch beforehand. The path to each patch is either an absolute path on the local filesystem or relative to a patch directory specified in the C<patches_dir> configuration variable or in the format of a canonical distro name. For examples please consult the distroprefs/ directory in the CPAN.pm distribution (these examples are not installed by default). Note: if the C<applypatch> program is installed and C<CPAN::Config> knows about it B<and> a patch is written by the C<makepatch> program, then C<CPAN.pm> lets C<applypatch> apply the patch. Both C<makepatch> and C<applypatch> are available from CPAN in the C<JV/makepatch-*> distribution. =item pl [hash] Processing instructions for the C<perl Makefile.PL> or C<perl Build.PL> phase of the CPAN mantra. See below under I<Processing Instructions>. =item test [hash] Processing instructions for the C<make test> or C<./Build test> phase of the CPAN mantra. See below under I<Processing Instructions>. =back =head2 Processing Instructions =over =item args [array] Arguments to be added to the command line =item commandline A full commandline to run via C<system()>. During execution, the environment variable PERL is set to $^X (but with an absolute path). If C<commandline> is specified, C<args> is not used. =item eexpect [hash] Extended C<expect>. This is a hash reference with four allowed keys, C<mode>, C<timeout>, C<reuse>, and C<talk>. You must install the C<Expect> module to use C<eexpect>. CPAN.pm does not install it for you. C<mode> may have the values C<deterministic> for the case where all questions come in the order written down and C<anyorder> for the case where the questions may come in any order. The default mode is C<deterministic>. C<timeout> denotes a timeout in seconds. Floating-point timeouts are OK. With C<mode=deterministic>, the timeout denotes the timeout per question; with C<mode=anyorder> it denotes the timeout per byte received from the stream or questions. C<talk> is a reference to an array that contains alternating questions and answers. Questions are regular expressions and answers are literal strings. The Expect module watches the stream from the execution of the external program (C<perl Makefile.PL>, C<perl Build.PL>, C<make>, etc.). For C<mode=deterministic>, the CPAN.pm injects the corresponding answer as soon as the stream matches the regular expression. For C<mode=anyorder> CPAN.pm answers a question as soon as the timeout is reached for the next byte in the input stream. In this mode you can use the C<reuse> parameter to decide what will happen with a question-answer pair after it has been used. In the default case (reuse=0) it is removed from the array, avoiding being used again accidentally. If you want to answer the question C<Do you really want to do that> several times, then it must be included in the array at least as often as you want this answer to be given. Setting the parameter C<reuse> to 1 makes this repetition unnecessary. =item env [hash] Environment variables to be set during the command =item expect [array] You must install the C<Expect> module to use C<expect>. CPAN.pm does not install it for you. C<< expect: <array> >> is a short notation for this C<eexpect>: eexpect: mode: deterministic timeout: 15 talk: <array> =back =head2 Schema verification with C<Kwalify> If you have the C<Kwalify> module installed (which is part of the Bundle::CPANxxl), then all your distroprefs files are checked for syntactic correctness. =head2 Example Distroprefs Files C<CPAN.pm> comes with a collection of example YAML files. Note that these are really just examples and should not be used without care because they cannot fit everybody's purpose. After all, the authors of the packages that ask questions had a need to ask, so you should watch their questions and adjust the examples to your environment and your needs. You have been warned:-) =head1 PROGRAMMER'S INTERFACE If you do not enter the shell, shell commands are available both as methods (C<CPAN::Shell-E<gt>install(...)>) and as functions in the calling package (C<install(...)>). Before calling low-level commands, it makes sense to initialize components of CPAN you need, e.g.: CPAN::HandleConfig->load; CPAN::Shell::setup_output; CPAN::Index->reload; High-level commands do such initializations automatically. There's currently only one class that has a stable interface - CPAN::Shell. All commands that are available in the CPAN shell are methods of the class CPAN::Shell. The arguments on the commandline are passed as arguments to the method. So if you take for example the shell command notest install A B C the actually executed command is CPAN::Shell->notest("install","A","B","C"); Each of the commands that produce listings of modules (C<r>, C<autobundle>, C<u>) also return a list of the IDs of all modules within the list. =over 2 =item expand($type,@things) The IDs of all objects available within a program are strings that can be expanded to the corresponding real objects with the C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a list of CPAN::Module objects according to the C<@things> arguments given. In scalar context, it returns only the first element of the list. =item expandany(@things) Like expand, but returns objects of the appropriate type, i.e. CPAN::Bundle objects for bundles, CPAN::Module objects for modules, and CPAN::Distribution objects for distributions. Note: it does not expand to CPAN::Author objects. =item Programming Examples This enables the programmer to do operations that combine functionalities that are available in the shell. # install everything that is outdated on my disk: perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)' # install my favorite programs if necessary: for $mod (qw(Net::FTP Digest::SHA Data::Dumper)) { CPAN::Shell->install($mod); } # list all modules on my disk that have no VERSION number for $mod (CPAN::Shell->expand("Module","/./")) { next unless $mod->inst_file; # MakeMaker convention for undefined $VERSION: next unless $mod->inst_version eq "undef"; print "No VERSION in ", $mod->id, "\n"; } # find out which distribution on CPAN contains a module: print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file Or if you want to schedule a I<cron> job to watch CPAN, you could list all modules that need updating. First a quick and dirty way: perl -e 'use CPAN; CPAN::Shell->r;' If you don't want any output should all modules be up to date, parse the output of above command for the regular expression C</modules are up to date/> and decide to mail the output only if it doesn't match. If you prefer to do it more in a programmerish style in one single process, something like this may better suit you: # list all modules on my disk that have newer versions on CPAN for $mod (CPAN::Shell->expand("Module","/./")) { next unless $mod->inst_file; next if $mod->uptodate; printf "Module %s is installed as %s, could be updated to %s from CPAN\n", $mod->id, $mod->inst_version, $mod->cpan_version; } If that gives too much output every day, you may want to watch only for three modules. You can write for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")) { as the first line instead. Or you can combine some of the above tricks: # watch only for a new mod_perl module $mod = CPAN::Shell->expand("Module","mod_perl"); exit if $mod->uptodate; # new mod_perl arrived, let me know all update recommendations CPAN::Shell->r; =back =head2 Methods in the other Classes =over 4 =item CPAN::Author::as_glimpse() Returns a one-line description of the author =item CPAN::Author::as_string() Returns a multi-line description of the author =item CPAN::Author::email() Returns the author's email address =item CPAN::Author::fullname() Returns the author's name =item CPAN::Author::name() An alias for fullname =item CPAN::Bundle::as_glimpse() Returns a one-line description of the bundle =item CPAN::Bundle::as_string() Returns a multi-line description of the bundle =item CPAN::Bundle::clean() Recursively runs the C<clean> method on all items contained in the bundle. =item CPAN::Bundle::contains() Returns a list of objects' IDs contained in a bundle. The associated objects may be bundles, modules or distributions. =item CPAN::Bundle::force($method,@args) Forces CPAN to perform a task that it normally would have refused to do. Force takes as arguments a method name to be called and any number of additional arguments that should be passed to the called method. The internals of the object get the needed changes so that CPAN.pm does not refuse to take the action. The C<force> is passed recursively to all contained objects. See also the section above on the C<force> and the C<fforce> pragma. =item CPAN::Bundle::get() Recursively runs the C<get> method on all items contained in the bundle =item CPAN::Bundle::inst_file() Returns the highest installed version of the bundle in either @INC or C<< $CPAN::Config->{cpan_home} >>. Note that this is different from CPAN::Module::inst_file. =item CPAN::Bundle::inst_version() Like CPAN::Bundle::inst_file, but returns the $VERSION =item CPAN::Bundle::uptodate() Returns 1 if the bundle itself and all its members are up-to-date. =item CPAN::Bundle::install() Recursively runs the C<install> method on all items contained in the bundle =item CPAN::Bundle::make() Recursively runs the C<make> method on all items contained in the bundle =item CPAN::Bundle::readme() Recursively runs the C<readme> method on all items contained in the bundle =item CPAN::Bundle::test() Recursively runs the C<test> method on all items contained in the bundle =item CPAN::Distribution::as_glimpse() Returns a one-line description of the distribution =item CPAN::Distribution::as_string() Returns a multi-line description of the distribution =item CPAN::Distribution::author Returns the CPAN::Author object of the maintainer who uploaded this distribution =item CPAN::Distribution::pretty_id() Returns a string of the form "AUTHORID/TARBALL", where AUTHORID is the author's PAUSE ID and TARBALL is the distribution filename. =item CPAN::Distribution::base_id() Returns the distribution filename without any archive suffix. E.g "Foo-Bar-0.01" =item CPAN::Distribution::clean() Changes to the directory where the distribution has been unpacked and runs C<make clean> there. =item CPAN::Distribution::containsmods() Returns a list of IDs of modules contained in a distribution file. Works only for distributions listed in the 02packages.details.txt.gz file. This typically means that just most recent version of a distribution is covered. =item CPAN::Distribution::cvs_import() Changes to the directory where the distribution has been unpacked and runs something like cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version there. =item CPAN::Distribution::dir() Returns the directory into which this distribution has been unpacked. =item CPAN::Distribution::force($method,@args) Forces CPAN to perform a task that it normally would have refused to do. Force takes as arguments a method name to be called and any number of additional arguments that should be passed to the called method. The internals of the object get the needed changes so that CPAN.pm does not refuse to take the action. See also the section above on the C<force> and the C<fforce> pragma. =item CPAN::Distribution::get() Downloads the distribution from CPAN and unpacks it. Does nothing if the distribution has already been downloaded and unpacked within the current session. =item CPAN::Distribution::install() Changes to the directory where the distribution has been unpacked and runs the external command C<make install> there. If C<make> has not yet been run, it will be run first. A C<make test> is issued in any case and if this fails, the install is cancelled. The cancellation can be avoided by letting C<force> run the C<install> for you. This install method only has the power to install the distribution if there are no dependencies in the way. To install an object along with all its dependencies, use CPAN::Shell->install. Note that install() gives no meaningful return value. See uptodate(). =item CPAN::Distribution::isa_perl() Returns 1 if this distribution file seems to be a perl distribution. Normally this is derived from the file name only, but the index from CPAN can contain a hint to achieve a return value of true for other filenames too. =item CPAN::Distribution::look() Changes to the directory where the distribution has been unpacked and opens a subshell there. Exiting the subshell returns. =item CPAN::Distribution::make() First runs the C<get> method to make sure the distribution is downloaded and unpacked. Changes to the directory where the distribution has been unpacked and runs the external commands C<perl Makefile.PL> or C<perl Build.PL> and C<make> there. =item CPAN::Distribution::perldoc() Downloads the pod documentation of the file associated with a distribution (in HTML format) and runs it through the external command I<lynx> specified in C<< $CPAN::Config->{lynx} >>. If I<lynx> isn't available, it converts it to plain text with the external command I<html2text> and runs it through the pager specified in C<< $CPAN::Config->{pager} >>. =item CPAN::Distribution::prefs() Returns the hash reference from the first matching YAML file that the user has deposited in the C<prefs_dir/> directory. The first succeeding match wins. The files in the C<prefs_dir/> are processed alphabetically, and the canonical distro name (e.g. AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions stored in the $root->{match}{distribution} attribute value. Additionally all module names contained in a distribution are matched against the regular expressions in the $root->{match}{module} attribute value. The two match values are ANDed together. Each of the two attributes are optional. =item CPAN::Distribution::prereq_pm() Returns the hash reference that has been announced by a distribution as the C<requires> and C<build_requires> elements. These can be declared either by the C<META.yml> (if authoritative) or can be deposited after the run of C<Build.PL> in the file C<./_build/prereqs> or after the run of C<Makfile.PL> written as the C<PREREQ_PM> hash in a comment in the produced C<Makefile>. I<Note>: this method only works after an attempt has been made to C<make> the distribution. Returns undef otherwise. =item CPAN::Distribution::readme() Downloads the README file associated with a distribution and runs it through the pager specified in C<< $CPAN::Config->{pager} >>. =item CPAN::Distribution::reports() Downloads report data for this distribution from www.cpantesters.org and displays a subset of them. =item CPAN::Distribution::read_yaml() Returns the content of the META.yml of this distro as a hashref. Note: works only after an attempt has been made to C<make> the distribution. Returns undef otherwise. Also returns undef if the content of META.yml is not authoritative. (The rules about what exactly makes the content authoritative are still in flux.) =item CPAN::Distribution::test() Changes to the directory where the distribution has been unpacked and runs C<make test> there. =item CPAN::Distribution::uptodate() Returns 1 if all the modules contained in the distribution are up-to-date. Relies on containsmods. =item CPAN::Index::force_reload() Forces a reload of all indices. =item CPAN::Index::reload() Reloads all indices if they have not been read for more than C<< $CPAN::Config->{index_expire} >> days. =item CPAN::InfoObj::dump() CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution inherit this method. It prints the data structure associated with an object. Useful for debugging. Note: the data structure is considered internal and thus subject to change without notice. =item CPAN::Module::as_glimpse() Returns a one-line description of the module in four columns: The first column contains the word C<Module>, the second column consists of one character: an equals sign if this module is already installed and up-to-date, a less-than sign if this module is installed but can be upgraded, and a space if the module is not installed. The third column is the name of the module and the fourth column gives maintainer or distribution information. =item CPAN::Module::as_string() Returns a multi-line description of the module =item CPAN::Module::clean() Runs a clean on the distribution associated with this module. =item CPAN::Module::cpan_file() Returns the filename on CPAN that is associated with the module. =item CPAN::Module::cpan_version() Returns the latest version of this module available on CPAN. =item CPAN::Module::cvs_import() Runs a cvs_import on the distribution associated with this module. =item CPAN::Module::description() Returns a 44 character description of this module. Only available for modules listed in The Module List (CPAN/modules/00modlist.long.html or 00modlist.long.txt.gz) =item CPAN::Module::distribution() Returns the CPAN::Distribution object that contains the current version of this module. =item CPAN::Module::dslip_status() Returns a hash reference. The keys of the hash are the letters C<D>, C<S>, C<L>, C<I>, and <P>, for development status, support level, language, interface and public licence respectively. The data for the DSLIP status are collected by pause.perl.org when authors register their namespaces. The values of the 5 hash elements are one-character words whose meaning is described in the table below. There are also 5 hash elements C<DV>, C<SV>, C<LV>, C<IV>, and <PV> that carry a more verbose value of the 5 status variables. Where the 'DSLIP' characters have the following meanings: D - Development Stage (Note: *NO IMPLIED TIMESCALES*): i - Idea, listed to gain consensus or as a placeholder c - under construction but pre-alpha (not yet released) a/b - Alpha/Beta testing R - Released M - Mature (no rigorous definition) S - Standard, supplied with Perl 5 S - Support Level: m - Mailing-list d - Developer u - Usenet newsgroup comp.lang.perl.modules n - None known, try comp.lang.perl.modules a - abandoned; volunteers welcome to take over maintenance L - Language Used: p - Perl-only, no compiler needed, should be platform independent c - C and perl, a C compiler will be needed h - Hybrid, written in perl with optional C code, no compiler needed + - C++ and perl, a C++ compiler will be needed o - perl and another language other than C or C++ I - Interface Style f - plain Functions, no references used h - hybrid, object and function interfaces available n - no interface at all (huh?) r - some use of unblessed References or ties O - Object oriented using blessed references and/or inheritance P - Public License p - Standard-Perl: user may choose between GPL and Artistic g - GPL: GNU General Public License l - LGPL: "GNU Lesser General Public License" (previously known as "GNU Library General Public License") b - BSD: The BSD License a - Artistic license alone 2 - Artistic license 2.0 or later o - open source: approved by www.opensource.org d - allows distribution without restrictions r - restricted distribution n - no license at all =item CPAN::Module::force($method,@args) Forces CPAN to perform a task it would normally refuse to do. Force takes as arguments a method name to be invoked and any number of additional arguments to pass that method. The internals of the object get the needed changes so that CPAN.pm does not refuse to take the action. See also the section above on the C<force> and the C<fforce> pragma. =item CPAN::Module::get() Runs a get on the distribution associated with this module. =item CPAN::Module::inst_file() Returns the filename of the module found in @INC. The first file found is reported, just as perl itself stops searching @INC once it finds a module. =item CPAN::Module::available_file() Returns the filename of the module found in PERL5LIB or @INC. The first file found is reported. The advantage of this method over C<inst_file> is that modules that have been tested but not yet installed are included because PERL5LIB keeps track of tested modules. =item CPAN::Module::inst_version() Returns the version number of the installed module in readable format. =item CPAN::Module::available_version() Returns the version number of the available module in readable format. =item CPAN::Module::install() Runs an C<install> on the distribution associated with this module. =item CPAN::Module::look() Changes to the directory where the distribution associated with this module has been unpacked and opens a subshell there. Exiting the subshell returns. =item CPAN::Module::make() Runs a C<make> on the distribution associated with this module. =item CPAN::Module::manpage_headline() If module is installed, peeks into the module's manpage, reads the headline, and returns it. Moreover, if the module has been downloaded within this session, does the equivalent on the downloaded module even if it hasn't been installed yet. =item CPAN::Module::perldoc() Runs a C<perldoc> on this module. =item CPAN::Module::readme() Runs a C<readme> on the distribution associated with this module. =item CPAN::Module::reports() Calls the reports() method on the associated distribution object. =item CPAN::Module::test() Runs a C<test> on the distribution associated with this module. =item CPAN::Module::uptodate() Returns 1 if the module is installed and up-to-date. =item CPAN::Module::userid() Returns the author's ID of the module. =back =head2 Cache Manager Currently the cache manager only keeps track of the build directory ($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that deletes complete directories below C<build_dir> as soon as the size of all directories there gets bigger than $CPAN::Config->{build_cache} (in MB). The contents of this cache may be used for later re-installations that you intend to do manually, but will never be trusted by CPAN itself. This is due to the fact that the user might use these directories for building modules on different architectures. There is another directory ($CPAN::Config->{keep_source_where}) where the original distribution files are kept. This directory is not covered by the cache manager and must be controlled by the user. If you choose to have the same directory as build_dir and as keep_source_where directory, then your sources will be deleted with the same fifo mechanism. =head2 Bundles A bundle is just a perl module in the namespace Bundle:: that does not define any functions or methods. It usually only contains documentation. It starts like a perl module with a package declaration and a $VERSION variable. After that the pod section looks like any other pod with the only difference being that I<one special pod section> exists starting with (verbatim): =head1 CONTENTS In this pod section each line obeys the format Module_Name [Version_String] [- optional text] The only required part is the first field, the name of a module (e.g. Foo::Bar, i.e. I<not> the name of the distribution file). The rest of the line is optional. The comment part is delimited by a dash just as in the man page header. The distribution of a bundle should follow the same convention as other distributions. Bundles are treated specially in the CPAN package. If you say 'install Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all the modules in the CONTENTS section of the pod. You can install your own Bundles locally by placing a conformant Bundle file somewhere into your @INC path. The autobundle() command which is available in the shell interface does that for you by including all currently installed modules in a snapshot bundle file. =head1 PREREQUISITES The CPAN program is trying to depend on as little as possible so the user can use it in hostile environment. It works better the more goodies the environment provides. For example if you try in the CPAN shell install Bundle::CPAN or install Bundle::CPANxxl you will find the shell more convenient than the bare shell before. If you have a local mirror of CPAN and can access all files with "file:" URLs, then you only need a perl later than perl5.003 to run this module. Otherwise Net::FTP is strongly recommended. LWP may be required for non-UNIX systems, or if your nearest CPAN site is associated with a URL that is not C<ftp:>. If you have neither Net::FTP nor LWP, there is a fallback mechanism implemented for an external ftp command or for an external lynx command. =head1 UTILITIES =head2 Finding packages and VERSION This module presumes that all packages on CPAN =over 2 =item * declare their $VERSION variable in an easy to parse manner. This prerequisite can hardly be relaxed because it consumes far too much memory to load all packages into the running program just to determine the $VERSION variable. Currently all programs that are dealing with version use something like this perl -MExtUtils::MakeMaker -le \ 'print MM->parse_version(shift)' filename If you are author of a package and wonder if your $VERSION can be parsed, please try the above method. =item * come as compressed or gzipped tarfiles or as zip files and contain a C<Makefile.PL> or C<Build.PL> (well, we try to handle a bit more, but with little enthusiasm). =back =head2 Debugging Debugging this module is more than a bit complex due to interference from the software producing the indices on CPAN, the mirroring process on CPAN, packaging, configuration, synchronicity, and even (gasp!) due to bugs within the CPAN.pm module itself. For debugging the code of CPAN.pm itself in interactive mode, some debugging aid can be turned on for most packages within CPAN.pm with one of =over 2 =item o debug package... sets debug mode for packages. =item o debug -package... unsets debug mode for packages. =item o debug all turns debugging on for all packages. =item o debug number =back which sets the debugging packages directly. Note that C<o debug 0> turns debugging off. What seems a successful strategy is the combination of C<reload cpan> and the debugging switches. Add a new debug statement while running in the shell and then issue a C<reload cpan> and see the new debugging messages immediately without losing the current context. C<o debug> without an argument lists the valid package names and the current set of packages in debugging mode. C<o debug> has built-in completion support. For debugging of CPAN data there is the C<dump> command which takes the same arguments as make/test/install and outputs each object's Data::Dumper dump. If an argument looks like a perl variable and contains one of C<$>, C<@> or C<%>, it is eval()ed and fed to Data::Dumper directly. =head2 Floppy, Zip, Offline Mode CPAN.pm works nicely without network access, too. If you maintain machines that are not networked at all, you should consider working with C<file:> URLs. You'll have to collect your modules somewhere first. So you might use CPAN.pm to put together all you need on a networked machine. Then copy the $CPAN::Config->{keep_source_where} (but not $CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind of a personal CPAN. CPAN.pm on the non-networked machines works nicely with this floppy. See also below the paragraph about CD-ROM support. =head2 Basic Utilities for Programmers =over 2 =item has_inst($module) Returns true if the module is installed. Used to load all modules into the running CPAN.pm that are considered optional. The config variable C<dontload_list> intercepts the C<has_inst()> call such that an optional module is not loaded despite being available. For example, the following command will prevent C<YAML.pm> from being loaded: cpan> o conf dontload_list push YAML See the source for details. =item use_inst($module) Similary to L<has_inst()> tries to load optional library but also dies if library is not available =item has_usable($module) Returns true if the module is installed and in a usable state. Only useful for a handful of modules that are used internally. See the source for details. =item instance($module) The constructor for all the singletons used to represent modules, distributions, authors, and bundles. If the object already exists, this method returns the object; otherwise, it calls the constructor. =item frontend() =item frontend($new_frontend) Getter/setter for frontend object. Method just allows to subclass CPAN.pm. =back =head1 SECURITY There's no strong security layer in CPAN.pm. CPAN.pm helps you to install foreign, unmasked, unsigned code on your machine. We compare to a checksum that comes from the net just as the distribution file itself. But we try to make it easy to add security on demand: =head2 Cryptographically signed modules Since release 1.77, CPAN.pm has been able to verify cryptographically signed module distributions using Module::Signature. The CPAN modules can be signed by their authors, thus giving more security. The simple unsigned MD5 checksums that were used before by CPAN protect mainly against accidental file corruption. You will need to have Module::Signature installed, which in turn requires that you have at least one of Crypt::OpenPGP module or the command-line F<gpg> tool installed. You will also need to be able to connect over the Internet to the public key servers, like pgp.mit.edu, and their port 11731 (the HKP protocol). The configuration parameter check_sigs is there to turn signature checking on or off. =head1 EXPORT Most functions in package CPAN are exported by default. The reason for this is that the primary use is intended for the cpan shell or for one-liners. =head1 ENVIRONMENT When the CPAN shell enters a subshell via the look command, it sets the environment CPAN_SHELL_LEVEL to 1, or increments that variable if it is already set. When CPAN runs, it sets the environment variable PERL5_CPAN_IS_RUNNING to the ID of the running process. It also sets PERL5_CPANPLUS_IS_RUNNING to prevent runaway processes which could happen with older versions of Module::Install. When running C<perl Makefile.PL>, the environment variable C<PERL5_CPAN_IS_EXECUTING> is set to the full path of the C<Makefile.PL> that is being executed. This prevents runaway processes with newer versions of Module::Install. When the config variable ftp_passive is set, all downloads will be run with the environment variable FTP_PASSIVE set to this value. This is in general a good idea as it influences both Net::FTP and LWP based connections. The same effect can be achieved by starting the cpan shell with this environment variable set. For Net::FTP alone, one can also always set passive mode by running libnetcfg. =head1 POPULATE AN INSTALLATION WITH LOTS OF MODULES Populating a freshly installed perl with one's favorite modules is pretty easy if you maintain a private bundle definition file. To get a useful blueprint of a bundle definition file, the command autobundle can be used on the CPAN shell command line. This command writes a bundle definition file for all modules installed for the current perl interpreter. It's recommended to run this command once only, and from then on maintain the file manually under a private name, say Bundle/my_bundle.pm. With a clever bundle file you can then simply say cpan> install Bundle::my_bundle then answer a few questions and go out for coffee (possibly even in a different city). Maintaining a bundle definition file means keeping track of two things: dependencies and interactivity. CPAN.pm sometimes fails on calculating dependencies because not all modules define all MakeMaker attributes correctly, so a bundle definition file should specify prerequisites as early as possible. On the other hand, it's annoying that so many distributions need some interactive configuring. So what you can try to accomplish in your private bundle file is to have the packages that need to be configured early in the file and the gentle ones later, so you can go out for coffee after a few minutes and leave CPAN.pm to churn away unattended. =head1 WORKING WITH CPAN.pm BEHIND FIREWALLS Thanks to Graham Barr for contributing the following paragraphs about the interaction between perl, and various firewall configurations. For further information on firewalls, it is recommended to consult the documentation that comes with the I<ncftp> program. If you are unable to go through the firewall with a simple Perl setup, it is likely that you can configure I<ncftp> so that it works through your firewall. =head2 Three basic types of firewalls Firewalls can be categorized into three basic types. =over 4 =item http firewall This is when the firewall machine runs a web server, and to access the outside world, you must do so via that web server. If you set environment variables like http_proxy or ftp_proxy to values beginning with http://, or in your web browser you've proxy information set, then you know you are running behind an http firewall. To access servers outside these types of firewalls with perl (even for ftp), you need LWP or HTTP::Tiny. =item ftp firewall This where the firewall machine runs an ftp server. This kind of firewall will only let you access ftp servers outside the firewall. This is usually done by connecting to the firewall with ftp, then entering a username like "user@outside.host.com". To access servers outside these type of firewalls with perl, you need Net::FTP. =item One-way visibility One-way visibility means these firewalls try to make themselves invisible to users inside the firewall. An FTP data connection is normally created by sending your IP address to the remote server and then listening for the return connection. But the remote server will not be able to connect to you because of the firewall. For these types of firewall, FTP connections need to be done in a passive mode. There are two that I can think off. =over 4 =item SOCKS If you are using a SOCKS firewall, you will need to compile perl and link it with the SOCKS library. This is what is normally called a 'socksified' perl. With this executable you will be able to connect to servers outside the firewall as if it were not there. =item IP Masquerade This is when the firewall implemented in the kernel (via NAT, or networking address translation), it allows you to hide a complete network behind one IP address. With this firewall no special compiling is needed as you can access hosts directly. For accessing ftp servers behind such firewalls you usually need to set the environment variable C<FTP_PASSIVE> or the config variable ftp_passive to a true value. =back =back =head2 Configuring lynx or ncftp for going through a firewall If you can go through your firewall with e.g. lynx, presumably with a command such as /usr/local/bin/lynx -pscott:tiger then you would configure CPAN.pm with the command o conf lynx "/usr/local/bin/lynx -pscott:tiger" That's all. Similarly for ncftp or ftp, you would configure something like o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg" Your mileage may vary... =head1 FAQ =over 4 =item 1) I installed a new version of module X but CPAN keeps saying, I have the old version installed Probably you B<do> have the old version installed. This can happen if a module installs itself into a different directory in the @INC path than it was previously installed. This is not really a CPAN.pm problem, you would have the same problem when installing the module manually. The easiest way to prevent this behaviour is to add the argument C<UNINST=1> to the C<make install> call, and that is why many people add this argument permanently by configuring o conf make_install_arg UNINST=1 =item 2) So why is UNINST=1 not the default? Because there are people who have their precise expectations about who may install where in the @INC path and who uses which @INC array. In fine tuned environments C<UNINST=1> can cause damage. =item 3) I want to clean up my mess, and install a new perl along with all modules I have. How do I go about it? Run the autobundle command for your old perl and optionally rename the resulting bundle file (e.g. Bundle/mybundle.pm), install the new perl with the Configure option prefix, e.g. ./Configure -Dprefix=/usr/local/perl-5.6.78.9 Install the bundle file you produced in the first step with something like cpan> install Bundle::mybundle and you're done. =item 4) When I install bundles or multiple modules with one command there is too much output to keep track of. You may want to configure something like o conf make_arg "| tee -ai /root/.cpan/logs/make.out" o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out" so that STDOUT is captured in a file for later inspection. =item 5) I am not root, how can I install a module in a personal directory? As of CPAN 1.9463, if you do not have permission to write the default perl library directories, CPAN's configuration process will ask you whether you want to bootstrap <local::lib>, which makes keeping a personal perl library directory easy. Another thing you should bear in mind is that the UNINST parameter can be dangerous when you are installing into a private area because you might accidentally remove modules that other people depend on that are not using the private area. =item 6) How to get a package, unwrap it, and make a change before building it? Have a look at the C<look> (!) command. =item 7) I installed a Bundle and had a couple of fails. When I retried, everything resolved nicely. Can this be fixed to work on first try? The reason for this is that CPAN does not know the dependencies of all modules when it starts out. To decide about the additional items to install, it just uses data found in the META.yml file or the generated Makefile. An undetected missing piece breaks the process. But it may well be that your Bundle installs some prerequisite later than some depending item and thus your second try is able to resolve everything. Please note, CPAN.pm does not know the dependency tree in advance and cannot sort the queue of things to install in a topologically correct order. It resolves perfectly well B<if> all modules declare the prerequisites correctly with the PREREQ_PM attribute to MakeMaker or the C<requires> stanza of Module::Build. For bundles which fail and you need to install often, it is recommended to sort the Bundle definition file manually. =item 8) In our intranet, we have many modules for internal use. How can I integrate these modules with CPAN.pm but without uploading the modules to CPAN? Have a look at the CPAN::Site module. =item 9) When I run CPAN's shell, I get an error message about things in my C</etc/inputrc> (or C<~/.inputrc>) file. These are readline issues and can only be fixed by studying readline configuration on your architecture and adjusting the referenced file accordingly. Please make a backup of the C</etc/inputrc> or C<~/.inputrc> and edit them. Quite often harmless changes like uppercasing or lowercasing some arguments solves the problem. =item 10) Some authors have strange characters in their names. Internally CPAN.pm uses the UTF-8 charset. If your terminal is expecting ISO-8859-1 charset, a converter can be activated by setting term_is_latin to a true value in your config file. One way of doing so would be cpan> o conf term_is_latin 1 If other charset support is needed, please file a bug report against CPAN.pm at rt.cpan.org and describe your needs. Maybe we can extend the support or maybe UTF-8 terminals become widely available. Note: this config variable is deprecated and will be removed in a future version of CPAN.pm. It will be replaced with the conventions around the family of $LANG and $LC_* environment variables. =item 11) When an install fails for some reason and then I correct the error condition and retry, CPAN.pm refuses to install the module, saying C<Already tried without success>. Use the force pragma like so force install Foo::Bar Or you can use look Foo::Bar and then C<make install> directly in the subshell. =item 12) How do I install a "DEVELOPER RELEASE" of a module? By default, CPAN will install the latest non-developer release of a module. If you want to install a dev release, you have to specify the partial path starting with the author id to the tarball you wish to install, like so: cpan> install KWILLIAMS/Module-Build-0.27_07.tar.gz Note that you can use the C<ls> command to get this path listed. =item 13) How do I install a module and all its dependencies from the commandline, without being prompted for anything, despite my CPAN configuration (or lack thereof)? CPAN uses ExtUtils::MakeMaker's prompt() function to ask its questions, so if you set the PERL_MM_USE_DEFAULT environment variable, you shouldn't be asked any questions at all (assuming the modules you are installing are nice about obeying that variable as well): % PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install My::Module' =item 14) How do I create a Module::Build based Build.PL derived from an ExtUtils::MakeMaker focused Makefile.PL? http://search.cpan.org/dist/Module-Build-Convert/ =item 15) I'm frequently irritated with the CPAN shell's inability to help me select a good mirror. CPAN can now help you select a "good" mirror, based on which ones have the lowest 'ping' round-trip times. From the shell, use the command 'o conf init urllist' and allow CPAN to automatically select mirrors for you. Beyond that help, the urllist config parameter is yours. You can add and remove sites at will. You should find out which sites have the best up-to-dateness, bandwidth, reliability, etc. and are topologically close to you. Some people prefer fast downloads, others up-to-dateness, others reliability. You decide which to try in which order. Henk P. Penning maintains a site that collects data about CPAN sites: http://mirrors.cpan.org/ Also, feel free to play with experimental features. Run o conf init randomize_urllist ftpstats_period ftpstats_size and choose your favorite parameters. After a few downloads running the C<hosts> command will probably assist you in choosing the best mirror sites. =item 16) Why do I get asked the same questions every time I start the shell? You can make your configuration changes permanent by calling the command C<o conf commit>. Alternatively set the C<auto_commit> variable to true by running C<o conf init auto_commit> and answering the following question with yes. =item 17) Older versions of CPAN.pm had the original root directory of all tarballs in the build directory. Now there are always random characters appended to these directory names. Why was this done? The random characters are provided by File::Temp and ensure that each module's individual build directory is unique. This makes running CPAN.pm in concurrent processes simultaneously safe. =item 18) Speaking of the build directory. Do I have to clean it up myself? You have the choice to set the config variable C<scan_cache> to C<never>. Then you must clean it up yourself. The other possible values, C<atstart> and C<atexit> clean up the build directory when you start (or more precisely, after the first extraction into the build directory) or exit the CPAN shell, respectively. If you never start up the CPAN shell, you probably also have to clean up the build directory yourself. =item 19) How can I switch to sudo instead of local::lib? The following 5 environment veriables need to be reset to the previous values: PATH, PERL5LIB, PERL_LOCAL_LIB_ROOT, PERL_MB_OPT, PERL_MM_OPT; and these two CPAN.pm config variables must be reconfigured: make_install_make_command and mbuild_install_build_command. The five env variables have probably been overwritten in your $HOME/.bashrc or some equivalent. You either find them there and delete their traces and logout/login or you override them temporarily, depending on your exact desire. The two cpanpm config variables can be set with: o conf init /install_.*_command/ probably followed by o conf commit =back =head1 COMPATIBILITY =head2 OLD PERL VERSIONS CPAN.pm is regularly tested to run under 5.005 and assorted newer versions. It is getting more and more difficult to get the minimal prerequisites working on older perls. It is close to impossible to get the whole Bundle::CPAN working there. If you're in the position to have only these old versions, be advised that CPAN is designed to work fine without the Bundle::CPAN installed. To get things going, note that GBARR/Scalar-List-Utils-1.18.tar.gz is compatible with ancient perls and that File::Temp is listed as a prerequisite but CPAN has reasonable workarounds if it is missing. =head2 CPANPLUS This module and its competitor, the CPANPLUS module, are both much cooler than the other. CPAN.pm is older. CPANPLUS was designed to be more modular, but it was never intended to be compatible with CPAN.pm. =head2 CPANMINUS In the year 2010 App::cpanminus was launched as a new approach to a cpan shell with a considerably smaller footprint. Very cool stuff. =head1 SECURITY ADVICE This software enables you to upgrade software on your computer and so is inherently dangerous because the newly installed software may contain bugs and may alter the way your computer works or even make it unusable. Please consider backing up your data before every upgrade. =head1 BUGS Please report bugs via L<http://rt.cpan.org/> Before submitting a bug, please make sure that the traditional method of building a Perl module package from a shell by following the installation instructions of that package still works in your environment. =head1 AUTHOR Andreas Koenig C<< <andk@cpan.org> >> =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L<http://www.perl.com/perl/misc/Artistic.html> =head1 TRANSLATIONS Kawai,Takanori provides a Japanese translation of a very old version of this manpage at L<http://homepage3.nifty.com/hippo2000/perltips/CPAN.htm> =head1 SEE ALSO Many people enter the CPAN shell by running the L<cpan> utility program which is installed in the same directory as perl itself. So if you have this directory in your PATH variable (or some equivalent in your operating system) then typing C<cpan> in a console window will work for you as well. Above that the utility provides several commandline shortcuts. melezhik (Alexey) sent me a link where he published a chef recipe to work with CPAN.pm: http://community.opscode.com/cookbooks/cpan. =cut ����������������������������������������������������������������������������������������������������������man/man3/version.3pm��������������������������������������������������������������������������������0000444�����������������00000033155�15253012307�0010266 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2022-07-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" 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 <jpeacock@cpan.org> .SH "SEE ALSO" .IX Header "SEE ALSO" version::Internals. .PP perl. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Queue.3pm����������������������������������������������������������������������������0000444�����������������00000004546�15253012307�0010515 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Queue 3" .TH CPAN::Queue 3 "2020-05-19" "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" CPAN::Queue \- internal queue support for CPAN.pm .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ����������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/IO::Tty.3pm��������������������������������������������������������������������������������0000444�����������������00000020230�15253012307�0007763 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2023-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" IO::Tty \- Low\-level allocate a pseudo\-Tty, import constants. .SH "VERSION" .IX Header "VERSION" 1.20 .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 <http://sources.redhat.com/cygwin/>. .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 <http://sourceforge.net/projects/expectperl/>. .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 <ylo@cs.hut.fi>, Markus Friedl and Todd C. Miller <Todd.Miller@courtesan.com>. 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/man3/LWP::Protocol::https.3pm�������������������������������������������������������������������0000444�����������������00000007771�15253012307�0012425 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2024-03-11" "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/YAML::Syck.3pm�����������������������������������������������������������������������������0000444�����������������00000025111�15253012307�0010352 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 <https://bugs.debian.org/cgi\-bin/bugreport.cgi?bug=862373> .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 <https://rt.cpan.org/Public/Dist/Display.html?Name=YAML-Syck> 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 <http://github.com/toddr/YAML-Syck> 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 <http://www.yaml.org/> .SH "AUTHORS" .IX Header "AUTHORS" Audrey Tang <cpan@audreyt.org> .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2005\-2009 by Audrey Tang <cpan@audreyt.org>. .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/CPAN::Meta::Requirements.3pm���������������������������������������������������������������0000444�����������������00000030632�15253012307�0013102 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Meta::Requirements 3" .TH CPAN::Meta::Requirements 3 "2023-06-19" "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" CPAN::Meta::Requirements \- a set of version requirements for a CPAN dist .SH "VERSION" .IX Header "VERSION" version 2.143 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use CPAN::Meta::Requirements; \& \& my $build_requires = CPAN::Meta::Requirements\->new; \& \& $build_requires\->add_minimum(\*(AqLibrary::Foo\*(Aq => 1.208); \& \& $build_requires\->add_minimum(\*(AqLibrary::Foo\*(Aq => 2.602); \& \& $build_requires\->add_minimum(\*(AqModule::Bar\*(Aq => \*(Aqv1.2.3\*(Aq); \& \& $METAyml\->{build_requires} = $build_requires\->as_string_hash; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" A CPAN::Meta::Requirements object models a set of version constraints like those specified in the \fI\s-1META\s0.yml\fR or \fI\s-1META\s0.json\fR files in \s-1CPAN\s0 distributions, and as defined by CPAN::Meta::Spec. It can be built up by adding more and more constraints, and it will reduce them to the simplest representation. .PP Logically impossible constraints will be identified immediately by thrown exceptions. .SH "METHODS" .IX Header "METHODS" .SS "new" .IX Subsection "new" .Vb 1 \& my $req = CPAN::Meta::Requirements\->new; .Ve .PP This returns a new CPAN::Meta::Requirements object. It takes an optional hash reference argument. Currently, only one key is supported: .IP "\(bu" 4 \&\f(CW\*(C`bad_version_hook\*(C'\fR \*(-- if provided, when a version cannot be parsed into a version object, this code reference will be called with the invalid version string as first argument, and the module name as second argument. It must return a valid version object. .PP All other keys are ignored. .SS "add_minimum" .IX Subsection "add_minimum" .Vb 1 \& $req\->add_minimum( $module => $version ); .Ve .PP This adds a new minimum version requirement. If the new requirement is redundant to the existing specification, this has no effect. .PP Minimum requirements are inclusive. \f(CW$version\fR is required, along with any greater version number. .PP This method returns the requirements object. .SS "add_maximum" .IX Subsection "add_maximum" .Vb 1 \& $req\->add_maximum( $module => $version ); .Ve .PP This adds a new maximum version requirement. If the new requirement is redundant to the existing specification, this has no effect. .PP Maximum requirements are inclusive. No version strictly greater than the given version is allowed. .PP This method returns the requirements object. .SS "add_exclusion" .IX Subsection "add_exclusion" .Vb 1 \& $req\->add_exclusion( $module => $version ); .Ve .PP This adds a new excluded version. For example, you might use these three method calls: .PP .Vb 2 \& $req\->add_minimum( $module => \*(Aq1.00\*(Aq ); \& $req\->add_maximum( $module => \*(Aq1.82\*(Aq ); \& \& $req\->add_exclusion( $module => \*(Aq1.75\*(Aq ); .Ve .PP Any version between 1.00 and 1.82 inclusive would be acceptable, except for 1.75. .PP This method returns the requirements object. .SS "exact_version" .IX Subsection "exact_version" .Vb 1 \& $req\->exact_version( $module => $version ); .Ve .PP This sets the version required for the given module to \fIexactly\fR the given version. No other version would be considered acceptable. .PP This method returns the requirements object. .SS "version_range_for_module" .IX Subsection "version_range_for_module" .Vb 1 \& $req\->version_range_for_module( $another_req_object ); .Ve .SS "add_requirements" .IX Subsection "add_requirements" .Vb 1 \& $req\->add_requirements( $another_req_object ); .Ve .PP This method adds all the requirements in the given CPAN::Meta::Requirements object to the requirements object on which it was called. If there are any conflicts, an exception is thrown. .PP This method returns the requirements object. .SS "accepts_module" .IX Subsection "accepts_module" .Vb 1 \& my $bool = $req\->accepts_module($module => $version); .Ve .PP Given an module and version, this method returns true if the version specification for the module accepts the provided version. In other words, given: .PP .Vb 1 \& Module => \*(Aq>= 1.00, < 2.00\*(Aq .Ve .PP We will accept 1.00 and 1.75 but not 0.50 or 2.00. .PP For modules that do not appear in the requirements, this method will return true. .SS "clear_requirement" .IX Subsection "clear_requirement" .Vb 1 \& $req\->clear_requirement( $module ); .Ve .PP This removes the requirement for a given module from the object. .PP This method returns the requirements object. .SS "requirements_for_module" .IX Subsection "requirements_for_module" .Vb 1 \& $req\->requirements_for_module( $module ); .Ve .PP This returns a string containing the version requirements for a given module in the format described in CPAN::Meta::Spec or undef if the given module has no requirements. This should only be used for informational purposes such as error messages and should not be interpreted or used for comparison (see \&\*(L"accepts_module\*(R" instead). .SS "structured_requirements_for_module" .IX Subsection "structured_requirements_for_module" .Vb 1 \& $req\->structured_requirements_for_module( $module ); .Ve .PP This returns a data structure containing the version requirements for a given module or undef if the given module has no requirements. This should not be used for version checks (see \*(L"accepts_module\*(R" instead). .PP Added in version 2.134. .SS "required_modules" .IX Subsection "required_modules" This method returns a list of all the modules for which requirements have been specified. .SS "clone" .IX Subsection "clone" .Vb 1 \& $req\->clone; .Ve .PP This method returns a clone of the invocant. The clone and the original object can then be changed independent of one another. .SS "is_simple" .IX Subsection "is_simple" This method returns true if and only if all requirements are inclusive minimums \&\*(-- that is, if their string expression is just the version number. .SS "is_finalized" .IX Subsection "is_finalized" This method returns true if the requirements have been finalized by having the \&\f(CW\*(C`finalize\*(C'\fR method called on them. .SS "finalize" .IX Subsection "finalize" This method marks the requirements finalized. Subsequent attempts to change the requirements will be fatal, \fIif\fR they would result in a change. If they would not alter the requirements, they have no effect. .PP If a finalized set of requirements is cloned, the cloned requirements are not also finalized. .SS "as_string_hash" .IX Subsection "as_string_hash" This returns a reference to a hash describing the requirements using the strings in the CPAN::Meta::Spec specification. .PP For example after the following program: .PP .Vb 1 \& my $req = CPAN::Meta::Requirements\->new; \& \& $req\->add_minimum(\*(AqCPAN::Meta::Requirements\*(Aq => 0.102); \& \& $req\->add_minimum(\*(AqLibrary::Foo\*(Aq => 1.208); \& \& $req\->add_maximum(\*(AqLibrary::Foo\*(Aq => 2.602); \& \& $req\->add_minimum(\*(AqModule::Bar\*(Aq => \*(Aqv1.2.3\*(Aq); \& \& $req\->add_exclusion(\*(AqModule::Bar\*(Aq => \*(Aqv1.2.8\*(Aq); \& \& $req\->exact_version(\*(AqXyzzy\*(Aq => \*(Aq6.01\*(Aq); \& \& my $hashref = $req\->as_string_hash; .Ve .PP \&\f(CW$hashref\fR would contain: .PP .Vb 6 \& { \& \*(AqCPAN::Meta::Requirements\*(Aq => \*(Aq0.102\*(Aq, \& \*(AqLibrary::Foo\*(Aq => \*(Aq>= 1.208, <= 2.206\*(Aq, \& \*(AqModule::Bar\*(Aq => \*(Aq>= v1.2.3, != v1.2.8\*(Aq, \& \*(AqXyzzy\*(Aq => \*(Aq== 6.01\*(Aq, \& } .Ve .SS "add_string_requirement" .IX Subsection "add_string_requirement" .Vb 2 \& $req\->add_string_requirement(\*(AqLibrary::Foo\*(Aq => \*(Aq>= 1.208, <= 2.206\*(Aq); \& $req\->add_string_requirement(\*(AqLibrary::Foo\*(Aq => v1.208); .Ve .PP This method parses the passed in string and adds the appropriate requirement for the given module. A version can be a Perl \*(L"v\-string\*(R". It understands version ranges as described in the \*(L"Version Ranges\*(R" in CPAN::Meta::Spec. For example: .IP "1.3" 4 .IX Item "1.3" .PD 0 .IP ">= 1.3" 4 .IX Item ">= 1.3" .IP "<= 1.3" 4 .IX Item "<= 1.3" .IP "== 1.3" 4 .IX Item "== 1.3" .IP "!= 1.3" 4 .IX Item "!= 1.3" .IP "> 1.3" 4 .IX Item "> 1.3" .IP "< 1.3" 4 .IX Item "< 1.3" .IP ">= 1.3, != 1.5, <= 2.0" 4 .IX Item ">= 1.3, != 1.5, <= 2.0" .PD A version number without an operator is equivalent to specifying a minimum (\f(CW\*(C`>=\*(C'\fR). Extra whitespace is allowed. .SS "from_string_hash" .IX Subsection "from_string_hash" .Vb 2 \& my $req = CPAN::Meta::Requirements\->from_string_hash( \e%hash ); \& my $req = CPAN::Meta::Requirements\->from_string_hash( \e%hash, \e%opts ); .Ve .PP This is an alternate constructor for a CPAN::Meta::Requirements object. It takes a hash of module names and version requirement strings and returns a new CPAN::Meta::Requirements object. As with add_string_requirement, a version can be a Perl \*(L"v\-string\*(R". Optionally, you can supply a hash-reference of options, exactly as with the \*(L"new\*(R" method. .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 <https://github.com/Perl\-Toolchain\-Gang/CPAN\-Meta\-Requirements/issues>. 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 <https://github.com/Perl\-Toolchain\-Gang/CPAN\-Meta\-Requirements> .PP .Vb 1 \& git clone https://github.com/Perl\-Toolchain\-Gang/CPAN\-Meta\-Requirements.git .Ve .SH "AUTHORS" .IX Header "AUTHORS" .IP "\(bu" 4 David Golden <dagolden@cpan.org> .IP "\(bu" 4 Ricardo Signes <rjbs@cpan.org> .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" .IP "\(bu" 4 Ed J <mohawk2@users.noreply.github.com> .IP "\(bu" 4 Graham Knop <haarg@haarg.org> .IP "\(bu" 4 Karen Etheridge <ether@cpan.org> .IP "\(bu" 4 Leon Timmermans <fawaka@gmail.com> .IP "\(bu" 4 Paul Howarth <paul@city\-fan.org> .IP "\(bu" 4 Ricardo Signes <rjbs@semiotic.systems> .IP "\(bu" 4 robario <webmaster@robario.com> .IP "\(bu" 4 Tatsuhiko Miyagawa <miyagawa@bulknews.net> .IP "\(bu" 4 Tatsuhiko Miyagawa <miyagawa@gmail.com> .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2010 by David Golden and Ricardo Signes. .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/POD2::DE::local::lib.3pm�������������������������������������������������������������������0000444�����������������00000054411�15253012307�0011752 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "POD2::DE::local::lib 3" .TH POD2::DE::local::lib 3 "2019-11-14" "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" local::lib~[de] \- Erschaffen und benutzen von Perl Modulen in einem lokalen lib/ Verzeichnis mit PERL5LIB .SH "SYNOPSIS" .IX Header "SYNOPSIS" Im Code \- .PP .Vb 1 \& use local::lib; # Benutzt das Verzeichnis ~/perl5 zum anlegen des lokalen lib/ Verzeichnisses \& \& use local::lib \*(Aq~/foo\*(Aq; # das selbe, aber mit ~/foo \& \& # Oder... \& use FindBin; \& use local::lib "$FindBin::Bin/../support"; # Applikationsspezifische Sammlung von Modulen .Ve .PP Von der Shell \- .PP .Vb 2 \& # Installiert LWP und alle notwendigen Abhängigkeiten in das \*(Aq~/perl5\*(Aq Verzeichnis \& perl \-MCPAN \-Mlocal::lib \-e \*(AqCPAN::install(LWP)\*(Aq \& \& # Gibt die Shell Kommandos aus um die Umgebung vorzubereiten \& $ perl \-Mlocal::lib \& export PERL_MB_OPT=\*(Aq\-\-install_base /home/username/perl5\*(Aq \& export PERL_MM_OPT=\*(AqINSTALL_BASE=/home/username/perl5\*(Aq \& export PERL5LIB=\*(Aq/home/username/perl5/lib/perl5/i386\-linux:/home/username/perl5/lib/perl5\*(Aq \& export PATH="/home/username/perl5/bin:$PATH" .Ve .SS "Die Bootstrapping Methode" .IX Subsection "Die Bootstrapping Methode" Ein typischer Weg um local::lib zu benutzen ist die sogenannte \*(L"Bootstrapping\*(R" Methode. Diese Methode wird benutzt wenn noch kein local::lib auf dem System installiert ist. In diesem Fall kannst du einfach local::lib direkt in deinem Home-Verzeichnis installieren. .PP Selbst wenn du administrative Rechte hast, ist es wichtig das die Umgebungsvariablen von Schritt 4 in deinem Shell Startup Skript gesetzt werden. Ohne diesen Schritt werden die Module von \s-1CPAN\s0 weiterhin im System installiert und auch Perl Skripte die du startest würden das von local::lib erstellte lib/ Verzeichnis nicht nutzen. .PP Standardmäßig installiert sich local::lib in ~/perl5. .PP Windows Benutzern müssen ausserdem dies hier lesen: \&\*(L"Unterschiede bei Benutzung dieses Module mit Win32\*(R". .PP 1. Lade das Tar-Archiv von \s-1CPAN\s0 runter (Suche nach \*(L"Download\*(R" auf der \s-1CPAN\s0 Seite von local::lib) und entpacke es in einem beliebigem Verzeichnis. Um das obige Problem zu vermeiden, sollte man dies als normaler User tun und nicht als root oder Administrator. .PP 2. Starte in dem entstandenen Verzeichnis folgenden Befehl: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap .Ve .PP Wenn das System dir vorschlägt gewisse Dinge eigenständig zu konfigurieren ist es in fast allen Fällen vollkommen in Ordnung einfach \*(L"yes\*(R" zu antworten. .PP Falls du local::lib nicht in das Standard Verzeichnis installieren willst, musst du dieses Verzeichnis als Parameter angeben: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap=~/foo .Ve .PP 3. Danach folgenden Befehl starten: (local::lib erwartet make auf dem System) .PP .Vb 1 \& make test && make install .Ve .PP 4. Nun müssen wir die benötigten Umgebungsvariablen, damit Perl unser neu generiertes lib/ Verzeichnis benutzt. Wenn du bash oder eine andere Bourne Shell benutzt, kannst du es über diesen Weg zu deinem Shell Startup Skript hinzufügen: .PP .Vb 1 \& echo \*(Aqeval $(perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib)\*(Aq >>~/.bashrc .Ve .PP Wenn du C Shell benutzt, du kannst das gleiche hiermit erreichen: .PP .Vb 4 \& /bin/csh \& echo $SHELL \& /bin/csh \& perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib >> ~/.cshrc .Ve .PP Wenn du beim bootstrappen ein anderes Verzeichnis benutzt als das Standardverzeichnis, dann musst du dieses Verzeichnis als Parameter beim Laden des Modules local::lib angeben: .PP .Vb 1 \& echo \*(Aqeval $(perl \-I$HOME/foo/lib/perl5 \-Mlocal::lib=$HOME/foo)\*(Aq >>~/.bashrc .Ve .PP Nachdem diese Änderungen in deinem Shell Startup Skript gemacht wurden, ist es nun wichtig das diese Umgebungsvariablen auch gesetzt sind in deiner aktuellen Umgebung. In Bourne Shells macht man dies z.B. mit \f(CW\*(C`. ~/.bashrc\*(C'\fR, und in C Shell würde man es mit: \&\f(CW\*(C`source ~/.cshrc\*(C'\fR mit. .PP Wenn du eine sehr langsames System hast, oder du unter drakonischen Regulierungen des Plattenplatz leben musst, kann man die automatische Generierung der manpages vom \s-1POD\s0 bei der Installation des Moduls deaktivieren beim bootstrapping mit dem \f(CW\*(C`\-\-no\-manpages\*(C'\fR Parameter: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap \-\-no\-manpages .Ve .PP Um zu vermeiden das man mehrere bootstraps macht um z.B. für verschiedene Applikationen eigene local::lib Installationen zu nutzen, kann man eine dieser Umgebungen benutzen um einfach in beliebigen anderen Verzeichnis Module zu installieren und somit weitere eigenständige lib/ Umgebungen zu bekommen: .PP .Vb 4 \& cd ~/mydir1 \& perl \-Mlocal::lib=./ \& eval $(perl \-Mlocal::lib=./) ### Um die Umgebungsvariablen für die \& ### aktuelle Shell zusetzen \& \& printenv ### Hier kannst du sehen das ~/mydir1 \& ### in der PERL5LIB Umgebungsvariable \& ### steht \& \& perl \-MCPAN \-e install ... ### welche Module auch immer ... \& cd ../mydir2 \& \& ... WIEDERHOLEN ... .Ve .PP Für mehrere Umgebungen in dieser Form brauch man eine Modifikation in der Benutzung von \f(CW\*(C`use FindBin\*(C'\fR in dem \*(L"Im Code\*(R" Beispiel oben. Wenn du sowas machst, und du hast damit z.B. Perl Module nach \f(CW\*(C`~/mydir1/lib\*(C'\fR installiert und du hast ein Script in \f(CW\*(C`~/mydir1/scripts/myscript.pl\*(C'\fR, du musst dort angeben das die Module die es braucht im Verzeichnis \f(CW\*(C`~/mydir1/lib\*(C'\fR liegen. .PP In \f(CW\*(C`~/mydir1/scripts/myscript.pl\*(C'\fR steht dann: .PP .Vb 5 \& use strict; \& use warnings; \& use local::lib "$FindBin::Bin/.."; ### zeigt auf ~/mydir1 und local::lib \& ### findet dort lib \& use lib "$FindBin::Bin/../lib"; ### zeigt auf ~/mydir1/lib .Ve .PP Setze das vor jeden \s-1BEGIN\s0 { ... } Block der die Module braucht die du installiert hast. .SS "Unterschiede bei Benutzung dieses Module mit Win32" .IX Subsection "Unterschiede bei Benutzung dieses Module mit Win32" Um die nötigen Umgebungsvariablen für diese Variablen in der derzeitigen Sitzung mit \f(CW\*(C`CMD.EXE\*(C'\fR zu setzen, kann man folgendes kommando nutzen: .PP .Vb 5 \& C:\e>perl \-Mlocal::lib \& set PERL_MB_OPT=\-\-install_base C:\eDOCUME~1\eADMINI~1\eperl5 \& set PERL_MM_OPT=INSTALL_BASE=C:\eDOCUME~1\eADMINI~1\eperl5 \& set PERL5LIB=C:\eDOCUME~1\eADMINI~1\eperl5\elib\eperl5;C:\eDOCUME~1\eADMINI~1\eperl5\elib\eperl5\eMSWin32\-x86\-multi\-thread \& set PATH=C:\eDOCUME~1\eADMINI~1\eperl5\ebin;%PATH% \& \& ### Um die Umgebungsvariablen für diese Shell alleine zu setzen \& C:\e>perl \-Mlocal::lib > %TEMP%\etmp.bat && %TEMP%\etmp.bat && del %TEMP%\etemp.bat \& ### anstelle von $(perl \-Mlocal::lib=./) in bash. .Ve .PP Wenn du willst das die Umgebungsvariablen dauerhaft gesetzt sind, musst du diese in Systemsteuerung / System dauerhaft selber eintragen oder App::local::lib::Win32Helper benutzen. .PP Die \*(L"~\*(R" wird übersetzt zu dem Benutzer Profil Verzeichnis (das Verzeichnis was beim User als \*(L"Dokumente und Einstellungen\*(R" bekannt ist unter Windows \s-1XP\s0 und vorher oder das \*(L"Benutzer\*(R" Verzeichnis bei Windows Vista und später), solange \&\f(CW$ENV\fR{\s-1HOME\s0} nicht gesetzt ist. Das Verzeichnis wird hierbei zu dem korrekten Kurznamen umgewandelt, und muss daher definitiv existieren, und wird um die nötigen Unterverzeichnise erweitert. .SH "GRUNDPRINZIP" .IX Header "GRUNDPRINZIP" Die Version von den Perl Paketen die man benötigt für spezifische Aufgaben sind sehr häufig nicht die richtigen oder korrekten Versionen auf dem System vorinstalliert. Ein Updaten von diesen Modulen ist in vielen Fällen einfach nicht möglich weil die nötigen Rechte fehlen. Ausserdem ist es generell nicht gut eigenständig die Versionen der Module auf dem System auszutauschen, weil natürlich der Rest des Systems genau die Version erwartet die von der Systemverwaltung auch installiert wurde. .PP local::lib löst dieses Problem, es erlaubt dir dein komplett eigenes Verzeichnis für deine \s-1CPAN\s0 Module zu haben und bist so nicht genötigt die Module vom System zu nutzen oder andersrum andere User nicht mit individuellen Modulwünschen zu Überarbeitung ihres Codes zu zwingen, weil bestimmte Module zentral für alle auf neuere Version upgedatet werden. Die Installation findet hierbei dann z.B. im Home Verzeichnis statt. Es werden nur Umgebungsvariablen gesetzt die das installierte Perl dazu bewegen die im Homeverzeichnis installierten Module zu benutzen, zusätzlich und vorgezogen zu denen auf dem System. .PP Daher muss man sich wenn man ein Paket System benutzt, wie z.b. Debian, garnicht mehr Sorgen machen, irgendwas auf dem System zu verletzten nur durch die Installation von Perl Modulen. .SH "BESCHREIBUNG" .IX Header "BESCHREIBUNG" Dieses Modul bietet eine schnelle und legitime Art und Weise ein sogenanntes bootstrapping zu machen um in einem User Homeverzeichnis eine Sammlung von Modulen zu installieren. Es erstellt auch die nötigen Umgebungsvariablen die benötigt werden um diese Module zu nutzen, passend zu der Shell die der User in der Umgebungsvariable \f(CW\*(C`SHELL\*(C'\fR angegeben hat, um dann direkt passend in die entsprechenden Konfigurationsdateien der Shell einfügt zu werden. .PP Weitergehend ist local::lib in der Lage Module zu nutzen die nicht im standardmäßigen \f(CW@INC\fR Pfad von Perl enthalten sind. Das macht es einfacher für bestimmte Applikationen ein bestimmtes Set von Modulen zu installieren ohne die anderen Module auf dem System in irgendeiner Art anzufassen. Damit es z.B. auch sicherer Module zu installieren die vom Maintainer noch nicht als Release verfügbar sind. .PP Beim Import setzt local::lib die folgenden Umgebungsvariablen zu den nötigen Werten: .IP "\s-1PERL_MB_OPT\s0" 4 .IX Item "PERL_MB_OPT" .PD 0 .IP "\s-1PERL_MM_OPT\s0" 4 .IX Item "PERL_MM_OPT" .IP "\s-1PERL5LIB\s0" 4 .IX Item "PERL5LIB" .IP "\s-1PATH\s0" 4 .IX Item "PATH" .PD Am \s-1PATH\s0 wird natürlich angehangen, und nicht ersetzt. .PP Diese Werte sind dann verfügbar für jeden Code der danach importiert wurde. .SH "ERSTELLEN EINES EIGENSTÄNDIGE SAMMLUNG VON MODULEN" .IX Header "ERSTELLEN EINES EIGENSTÄNDIGE SAMMLUNG VON MODULEN" Mit lib::core::only besteht eine Möglichkeit dieses zutun, aber beachte das hier eine Menge von Fallstricken und Problemen existieren, und man sollte immer darauf achten das man auf einem Perl aufbaut was sowenig wie möglich verändert wurde (d.h. site und vendor Verzeichnis so leer wie möglich). .SH "METHODEN" .IX Header "METHODEN" .SS "ensure_dir_structure_for" .IX Subsection "ensure_dir_structure_for" .ie n .IP "Parameter: $path" 4 .el .IP "Parameter: \f(CW$path\fR" 4 .IX Item "Parameter: $path" .PD 0 .IP "Rückgabewert: Keiner" 4 .IX Item "Rückgabewert: Keiner" .PD .PP Versucht den angegebenen Pfad anzulegen, mit allen nötigen drüberliegenden Verzeichnissen. Im Fehlerfall wird eine Exception geworfen. .SS "print_environment_vars_for" .IX Subsection "print_environment_vars_for" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .IP "Rückgabewert: Keiner" 4 .IX Item "Rückgabewert: Keiner" .PD .PP Gibt die Umgebungsvariablen aus, die benötigt werden um den angegebenen Pfad als Basis Verzeichnis zu nutzen. .SS "build_environment_vars_for" .IX Subsection "build_environment_vars_for" .ie n .IP "Parameter: $pfad, $interpolate" 4 .el .IP "Parameter: \f(CW$pfad\fR, \f(CW$interpolate\fR" 4 .IX Item "Parameter: $pfad, $interpolate" .PD 0 .IP "Rückgabewert: \e%umgebungs_variablen" 4 .IX Item "Rückgabewert: %umgebungs_variablen" .PD .PP Gibt ein Hash zurück mit den Variablen die nötig sind in den Umgebungsvariablen um eine Installation in dem gegebenen Pfad zu benutzen. .SS "setup_env_hash_for" .IX Subsection "setup_env_hash_for" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .IP "Rückgabewert: Keiner" 4 .IX Item "Rückgabewert: Keiner" .PD .PP Setzt die \f(CW%ENV\fR Einträge basierend auf dem Aufruf von \&\*(L"build_environment_vars_for\*(R". .SS "install_base_perl_path" .IX Subsection "install_base_perl_path" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $module_installations_pfad" 4 .el .IP "Rückgabewert: \f(CW$module_installations_pfad\fR" 4 .IX Item "Rückgabewert: $module_installations_pfad" .PD .PP Gibt den Pfad zurück der benutzt wird um Perl Module zu installieren bei dem gegebenen Pfad als Basis. Prinzipiell wird nur \f(CW\*(C`lib\*(C'\fR und \f(CW\*(C`perl5\*(C'\fR als Pfadelemente angehangen. .SS "install_base_arch_path" .IX Subsection "install_base_arch_path" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $architektur_module_installations_pfad" 4 .el .IP "Rückgabewert: \f(CW$architektur_module_installations_pfad\fR" 4 .IX Item "Rückgabewert: $architektur_module_installations_pfad" .PD .PP Gibt den Pfad zurück der benutzt wird um die Architektur\-abhängigen Perl Module zu installieren basirend auf dem angegebenen Pfad als Basis. Basierend auf dem was \*(L"install_base_perl_path\*(R" zurückgibt, and appends the value of \&\f(CW$Config{archname}\fR.asis. .SS "install_base_bin_path" .IX Subsection "install_base_bin_path" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $ausfuehrbare_programme_installations_pfad" 4 .el .IP "Rückgabewert: \f(CW$ausfuehrbare_programme_installations_pfad\fR" 4 .IX Item "Rückgabewert: $ausfuehrbare_programme_installations_pfad" .PD .PP Gibt den Pfad zurück, wo ausführbare Programme installiert werden, basierend auf der Basis des angegebenen Pfad. Basierend auf \*(L"install_base_perl_path\*(R" Rückgabewert, hängt diese Methode noch \f(CW\*(C`bin\*(C'\fR an. .SS "resolve_empty_path" .IX Subsection "resolve_empty_path" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $basis_pfad" 4 .el .IP "Rückgabewert: \f(CW$basis_pfad\fR" 4 .IX Item "Rückgabewert: $basis_pfad" .PD .PP Erstellt und gibt zurück den Pfad der benutzt wird als Basis zur Installation der Module. Standardmäßig dies ist \f(CW\*(C`~/perl5\*(C'\fR. .ie n .SS "resolve_home_path( $path )" .el .SS "resolve_home_path( \f(CW$path\fP )" .IX Subsection "resolve_home_path( $path )" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $home" 4 .el .IP "Rückgabewert: \f(CW$home\fR" 4 .IX Item "Rückgabewert: $home" .PD .PP Versucht das Home Verzeichnis vom aktullen User zu finden. Es wird eine Exception geworfen, wenn kein Home Verzeichnis ermittelt werden konnte. .SS "resolve_relative_path" .IX Subsection "resolve_relative_path" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $absoluter_pfad" 4 .el .IP "Rückgabewert: \f(CW$absoluter_pfad\fR" 4 .IX Item "Rückgabewert: $absoluter_pfad" .PD .PP Macht aus dem angegebenen Pfad einen absoluten Pfad. .SS "resolve_path" .IX Subsection "resolve_path" .ie n .IP "Parameter: $pfad" 4 .el .IP "Parameter: \f(CW$pfad\fR" 4 .IX Item "Parameter: $pfad" .PD 0 .ie n .IP "Rückgabewert: $absoluter_pfad" 4 .el .IP "Rückgabewert: \f(CW$absoluter_pfad\fR" 4 .IX Item "Rückgabewert: $absoluter_pfad" .PD .PP Hierbei wird der Pfad durch die folgende Methoden gegeben, wobei der Rückgabewert der ersten an die nächste weitergeben wird, um die Umgebung zu konfigurieren für die lokale Bibliotheks Installation: \*(L"resolve_empty_path\*(R", \&\*(L"resolve_home_path\*(R", \*(L"resolve_relative_path\*(R". Der daraus resultierende Pfad wird zu \*(L"resolve_empty_path\*(R" übergeben, dessen Resultat dann weitergegeben wird an \*(L"resolve_home_path\*(R", wessen Resultat dann weitergegeben wird an \*(L"resolve_relative_path\*(R". Dieses Resultat wird dann final an \*(L"resolve_path\*(R" übergeben, welches dann den Rückgabewert stellt. .SH "EINE WARNUNG VOR UNINST=1" .IX Header "EINE WARNUNG VOR UNINST=1" Wenn man local::lib in Kombination mit \*(L"make install UNINST=1\*(R" benutzt, muss man vorsichtig sein über die Tatsache das der Prozess über die Neuinstallation eine nicht ausreichende Sicherheit hat bezüglich wo er nun installieren muss. Hierdurch mann es passieren das beim deinstallieren eines Modul u.U. das globale Modul deinstalliert wird (wenn die Rechte vorhanden sind) aber die neue Version nur in der lokalen Version installiert ist. Es ist hier also sehr wichtig das man \*(L"make install UNINST=1\*(R" und local::lib nur gleichzeitig benutzt wenn man sehr sicher darüber ist welche Konsequenzen einem entgegenkommen. .SH "EINSCHRÄNKUNGEN" .IX Header "EINSCHRÄNKUNGEN" Die Werkzeuge von perl, die benutzt werden um die Pakete zu installieren (die sogenannte toolchain), sind leider nicht in der Lage sauber mit Verzeichnissen umzugehen die Leerzeichen enthalten und können daher local::lib nicht direkt in ein solches Verzeichnis installieren. Was du machen kannst ist \fBnach\fR der Installation von local::lib und der Module die du in deiner local::lib haben willst, das gesamte Verzeichnis dahin zu bewegen. local::lib kann mit dem Verzeichnis mit Leerzeichen umgehen. Bitte aufpassen das natürlich eine weitere Installation oder ein Erneuern von Paketen mit dem \s-1CPAN\s0 Programm nicht mehr möglich ist. .PP Die Shell Erkennung ist sehr primitiv. Derzeit ist es so das alles was \*(L"csh\*(R" im Namen hat auch als C Shell eingeordnet wird, und alles andere wird als Bourne Shell betrachet, ausser auf Win32 Systemen. Wenn die \f(CW\*(C`SHELL\*(C'\fR Variable nicht gesetzt ist, eine Bourne Shell wird angenommen. .PP Bootstrap ist leider ein Hack, und wird auf jedenfall \s-1CPAN\s0.pm benutzen für ExtUtils::MakeMaker, auch wenn \s-1CPANPLUS\s0 installiert ist. .PP Es setzt definitiv \s-1PERL5LIB, PERL_MM_OPT\s0 und \s-1PERL_MB_OPT\s0 neu und vernichtet jeden Wert der vorher gesetzt war. .PP Es sollte vielleicht eine automatische Korrektur der \s-1CPAN\s0 Config machen, wenn das nicht schon gemacht wurde. .PP \&\*(L"Patches Welcome\*(R" \- Patches sind immer willkommen beim Autor oder den anderen Mitwirkenden. .PP Auf Win32 Systemen werden die Umgebungsvariablen nicht direkt in die Registrierung geschrieben damit sie auch nach dem Neustarten erhalten bleiben. .SH "FEHLERANALYSE" .IX Header "FEHLERANALYSE" Wenn du local::lib konfiguriert hast \s-1CPAN\s0 Module in deinem Home Verzeichnis zu installieren, und du danach versuchst mit \f(CW\*(C`cpan \-i Foo::Bar\*(C'\fR ein Modul zu installieren, und dabei einen Fehler bekommst, wie: \f(CW\*(C`Warning: You do not have permissions to install into /usr/lib64/perl5/site_perl/5.8.8/x86_64\-linux at /usr/lib64/perl5/5.8.8/Foo/Bar.pm\*(C'\fR und in der installationsausgabe steht irgendwo ein Fehler der sagt \f(CW\*(C`\*(AqINSTALL_BASE\*(Aq is not a known MakeMaker parameter name\*(C'\fR, dann hast du aus irgendeinem Grund dein neue Version von ExtUtils::MakeMaker verloren. .PP Um dies zu korrigieren, einfach nochmal die bootstrapping Methode laufen lassen, wie oben beschrieben. .PP Dann starte \f(CW\*(C`rm \-r ~/.cpan/build/Foo\-Bar*\*(C'\fR .PP Abschliessend dann nochmal mit \f(CW\*(C`cpan \-i Foo::Bar\*(C'\fR installieren und die Probleme sollten verschwunden sein. .SH "UMGEBUNGSVARIABLEN" .IX Header "UMGEBUNGSVARIABLEN" .IP "\s-1SHELL\s0" 4 .IX Item "SHELL" .PD 0 .IP "\s-1COMSPEC\s0" 4 .IX Item "COMSPEC" .PD local::lib schaut in die \f(CW\*(C`SHELL\*(C'\fR Umgebungsvariable um die korrekten Kommandos zu der Shell Konfiguration hinzuzufügen. .Sp Auf Win32 Systemen, \f(CW\*(C`COMSPEC\*(C'\fR wird auch analysiert. .SH "SUPPORT" .IX Header "SUPPORT" \&\s-1IRC:\s0 .PP .Vb 1 \& Wir sind im Channel #local\-lib auf dem Server irc.perl.org. .Ve .SH "AUTOR DER ÜBERSETZUNG" .IX Header "AUTOR DER ÜBERSETZUNG" Torsten Raudssus <torsten@raudssus.de> http://www.raudssus.de/ .SH "URHEBERRECHT" .IX Header "URHEBERRECHT" Copyright (c) 2007 \- 2010 von den local::lib \*(L"\s-1AUTHOR\*(R"\s0 in local::lib und \*(L"\s-1CONTRIBUTORS\*(R"\s0 in local::lib aufgelistet in local::lib. .SH "LIZENZ" .IX Header "LIZENZ" Diese Sammlung ist freie Software und kann unter der selben Lizenz verbreitet werden wie Perl selber. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Version.3pm��������������������������������������������������������������������������0000444�����������������00000006357�15253012307�0011060 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Version 3" .TH CPAN::Version 3 "2018-09-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" CPAN::Version \- utility functions to compare CPAN versions .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use CPAN::Version; \& \& CPAN::Version\->vgt("1.1","1.1.1"); # 1 bc. 1.1 > 1.001001 \& \& CPAN::Version\->vlt("1.1","1.1"); # 0 bc. 1.1 not < 1.1 \& \& CPAN::Version\->vcmp("1.1","1.1.1"); # 1 bc. first is larger \& \& CPAN::Version\->vcmp("1.1.1","1.1"); # \-1 bc. first is smaller \& \& CPAN::Version\->readable(v1.2.3); # "v1.2.3" \& \& CPAN::Version\->vstring("v1.2.3"); # v1.2.3 \& \& CPAN::Version\->float2vv(1.002003); # "v1.2.3" .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module mediates between some version that perl sees in a package and the version that is published by the \s-1CPAN\s0 indexer. .PP It's only written as a helper module for both \s-1CPAN\s0.pm and \s-1CPANPLUS\s0.pm. .PP As it stands it predates version.pm but has the same goal: make version strings visible and comparable. .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/Canary::Stability.3pm����������������������������������������������������������������������0000444�����������������00000010114�15253012307�0012055 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 <schmorp@schmorp.de> \& http://software.schmorp.de/pkg/Canary\-Stability.html .Ve ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Meta::Requirements::Range.3pm��������������������������������������������������������0000444�����������������00000016045�15253012307�0014245 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Meta::Requirements::Range 3" .TH CPAN::Meta::Requirements::Range 3 "2023-06-19" "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" CPAN::Meta::Requirements::Range \- a set of version requirements for a CPAN dist .SH "VERSION" .IX Header "VERSION" version 2.143 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use CPAN::Meta::Requirements::Range; \& \& my $range = CPAN::Meta::Requirements::Range\->with_minimum(1); \& \& $range = $range\->with_maximum(\*(Aqv2.2\*(Aq); \& \& my $stringified = $range\->as_string; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" A CPAN::Meta::Requirements::Range object models a set of version constraints like those specified in the \fI\s-1META\s0.yml\fR or \fI\s-1META\s0.json\fR files in \s-1CPAN\s0 distributions, and as defined by CPAN::Meta::Spec; It can be built up by adding more and more constraints, and it will reduce them to the simplest representation. .PP Logically impossible constraints will be identified immediately by thrown exceptions. .SH "METHODS" .IX Header "METHODS" .SS "with_string_requirement" .IX Subsection "with_string_requirement" .Vb 2 \& $req\->with_string_requirement(\*(Aq>= 1.208, <= 2.206\*(Aq); \& $req\->with_string_requirement(v1.208); .Ve .PP This method parses the passed in string and adds the appropriate requirement. A version can be a Perl \*(L"v\-string\*(R". It understands version ranges as described in the \*(L"Version Ranges\*(R" in CPAN::Meta::Spec. For example: .IP "1.3" 4 .IX Item "1.3" .PD 0 .IP ">= 1.3" 4 .IX Item ">= 1.3" .IP "<= 1.3" 4 .IX Item "<= 1.3" .IP "== 1.3" 4 .IX Item "== 1.3" .IP "!= 1.3" 4 .IX Item "!= 1.3" .IP "> 1.3" 4 .IX Item "> 1.3" .IP "< 1.3" 4 .IX Item "< 1.3" .IP ">= 1.3, != 1.5, <= 2.0" 4 .IX Item ">= 1.3, != 1.5, <= 2.0" .PD A version number without an operator is equivalent to specifying a minimum (\f(CW\*(C`>=\*(C'\fR). Extra whitespace is allowed. .SS "with_range" .IX Subsection "with_range" .Vb 1 \& $range\->with_range($other_range) .Ve .PP This creates a new range object that is a merge two others. .SS "with_exact_version" .IX Subsection "with_exact_version" .Vb 1 \& $range\->with_exact_version( $version ); .Ve .PP This sets the version required to \fIexactly\fR the given version. No other version would be considered acceptable. .PP This method returns the version range object. .SS "with_minimum" .IX Subsection "with_minimum" .Vb 1 \& $range\->with_minimum( $version ); .Ve .PP This adds a new minimum version requirement. If the new requirement is redundant to the existing specification, this has no effect. .PP Minimum requirements are inclusive. \f(CW$version\fR is required, along with any greater version number. .PP This method returns the version range object. .SS "with_maximum" .IX Subsection "with_maximum" .Vb 1 \& $range\->with_maximum( $version ); .Ve .PP This adds a new maximum version requirement. If the new requirement is redundant to the existing specification, this has no effect. .PP Maximum requirements are inclusive. No version strictly greater than the given version is allowed. .PP This method returns the version range object. .SS "with_exclusion" .IX Subsection "with_exclusion" .Vb 1 \& $range\->with_exclusion( $version ); .Ve .PP This adds a new excluded version. For example, you might use these three method calls: .PP .Vb 2 \& $range\->with_minimum( \*(Aq1.00\*(Aq ); \& $range\->with_maximum( \*(Aq1.82\*(Aq ); \& \& $range\->with_exclusion( \*(Aq1.75\*(Aq ); .Ve .PP Any version between 1.00 and 1.82 inclusive would be acceptable, except for 1.75. .PP This method returns the requirements object. .SS "as_struct" .IX Subsection "as_struct" .Vb 1 \& $range\->as_struct( $module ); .Ve .PP This returns a data structure containing the version requirements. This should not be used for version checks (see \*(L"accepts_module\*(R" instead). .SS "as_string" .IX Subsection "as_string" .Vb 1 \& $range\->as_string; .Ve .PP This returns a string containing the version requirements in the format described in CPAN::Meta::Spec. This should only be used for informational purposes such as error messages and should not be interpreted or used for comparison (see \*(L"accepts\*(R" instead). .SS "accepts" .IX Subsection "accepts" .Vb 1 \& my $bool = $range\->accepts($version); .Ve .PP Given a version, this method returns true if the version specification accepts the provided version. In other words, given: .PP .Vb 1 \& \*(Aq>= 1.00, < 2.00\*(Aq .Ve .PP We will accept 1.00 and 1.75 but not 0.50 or 2.00. .SS "is_simple" .IX Subsection "is_simple" This method returns true if and only if the range is an inclusive minimum \&\*(-- that is, if their string expression is just the version number. .SH "AUTHORS" .IX Header "AUTHORS" .IP "\(bu" 4 David Golden <dagolden@cpan.org> .IP "\(bu" 4 Ricardo Signes <rjbs@cpan.org> .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2010 by David Golden and Ricardo Signes. .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/CPAN::Debug.3pm����������������������������������������������������������������������������0000444�����������������00000004542�15253012307�0010453 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Debug 3" .TH CPAN::Debug 3 "2016-08-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" CPAN::Debug \- internal debugging for CPAN.pm .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ��������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/local::lib.3pm�����������������������������������������������������������������������������0000444�����������������00000076022�15253012307�0010546 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "local::lib 3" .TH local::lib 3 "2022-04-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" local::lib \- create and use a local lib/ for perl modules with PERL5LIB .SH "SYNOPSIS" .IX Header "SYNOPSIS" In code \- .PP .Vb 1 \& use local::lib; # sets up a local lib at ~/perl5 \& \& use local::lib \*(Aq~/foo\*(Aq; # same, but ~/foo \& \& # Or... \& use FindBin; \& use local::lib "$FindBin::Bin/../support"; # app\-local support library .Ve .PP From the shell \- .PP .Vb 2 \& # Install LWP and its missing dependencies to the \*(Aq~/perl5\*(Aq directory \& perl \-MCPAN \-Mlocal::lib \-e \*(AqCPAN::install(LWP)\*(Aq \& \& # Just print out useful shell commands \& $ perl \-Mlocal::lib \& PERL_MB_OPT=\*(Aq\-\-install_base /home/username/perl5\*(Aq; export PERL_MB_OPT; \& PERL_MM_OPT=\*(AqINSTALL_BASE=/home/username/perl5\*(Aq; export PERL_MM_OPT; \& PERL5LIB="/home/username/perl5/lib/perl5"; export PERL5LIB; \& PATH="/home/username/perl5/bin:$PATH"; export PATH; \& PERL_LOCAL_LIB_ROOT="/home/usename/perl5:$PERL_LOCAL_LIB_ROOT"; export PERL_LOCAL_LIB_ROOT; .Ve .PP From a \fI.bash_profile\fR or \fI.bashrc\fR file \- .PP .Vb 1 \& eval "$(perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib)" .Ve .SS "The bootstrapping technique" .IX Subsection "The bootstrapping technique" A typical way to install local::lib is using what is known as the \&\*(L"bootstrapping\*(R" technique. You would do this if your system administrator hasn't already installed local::lib. In this case, you'll need to install local::lib in your home directory. .PP Even if you do have administrative privileges, you will still want to set up your environment variables, as discussed in step 4. Without this, you would still install the modules into the system \s-1CPAN\s0 installation and also your Perl scripts will not use the lib/ path you bootstrapped with local::lib. .PP By default local::lib installs itself and the \s-1CPAN\s0 modules into ~/perl5. .PP Windows users must also see \*(L"Differences when using this module under Win32\*(R". .IP "1." 4 Download and unpack the local::lib tarball from \s-1CPAN\s0 (search for \*(L"Download\*(R" on the \s-1CPAN\s0 page about local::lib). Do this as an ordinary user, not as root or administrator. Unpack the file in your home directory or in any other convenient location. .IP "2." 4 Run this: .Sp .Vb 1 \& perl Makefile.PL \-\-bootstrap .Ve .Sp If the system asks you whether it should automatically configure as much as possible, you would typically answer yes. .IP "3." 4 Run this: (local::lib assumes you have make installed on your system) .Sp .Vb 1 \& make test && make install .Ve .IP "4." 4 Now we need to setup the appropriate environment variables, so that Perl starts using our newly generated lib/ directory. If you are using bash or any other Bourne shells, you can add this to your shell startup script this way: .Sp .Vb 1 \& echo \*(Aqeval "$(perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib)"\*(Aq >>~/.bashrc .Ve .Sp If you are using C shell, you can do this as follows: .Sp .Vb 3 \& % echo $SHELL \& /bin/csh \& $ echo \*(Aqeval \`perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib\`\*(Aq >> ~/.cshrc .Ve .Sp After writing your shell configuration file, be sure to re-read it to get the changed settings into your current shell's environment. Bourne shells use \&\f(CW\*(C`. ~/.bashrc\*(C'\fR for this, whereas C shells use \f(CW\*(C`source ~/.cshrc\*(C'\fR. .PP \fIBootstrapping into an alternate directory\fR .IX Subsection "Bootstrapping into an alternate directory" .PP In order to install local::lib into a directory other than the default, you need to specify the name of the directory when you call bootstrap. Then, when setting up the environment variables, both perl and local::lib must be told the location of the bootstrap directory. The setup process would look as follows: .PP .Vb 4 \& perl Makefile.PL \-\-bootstrap=~/foo \& make test && make install \& echo \*(Aqeval "$(perl \-I$HOME/foo/lib/perl5 \-Mlocal::lib=$HOME/foo)"\*(Aq >>~/.bashrc \& . ~/.bashrc .Ve .PP \fIOther bootstrapping options\fR .IX Subsection "Other bootstrapping options" .PP If you're on a slower machine, or are operating under draconian disk space limitations, you can disable the automatic generation of manpages from \s-1POD\s0 when installing modules by using the \f(CW\*(C`\-\-no\-manpages\*(C'\fR argument when bootstrapping: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap \-\-no\-manpages .Ve .PP To avoid doing several bootstrap for several Perl module environments on the same account, for example if you use it for several different deployed applications independently, you can use one bootstrapped local::lib installation to install modules in different directories directly this way: .PP .Vb 7 \& cd ~/mydir1 \& perl \-Mlocal::lib=./ \& eval $(perl \-Mlocal::lib=./) ### To set the environment for this shell alone \& printenv ### You will see that ~/mydir1 is in the PERL5LIB \& perl \-MCPAN \-e install ... ### whatever modules you want \& cd ../mydir2 \& ... REPEAT ... .Ve .PP If you use \fI.bashrc\fR to activate a local::lib automatically, the local::lib will be re-enabled in any sub-shells used, overriding adjustments you may have made in the parent shell. To avoid this, you can initialize the local::lib in \&\fI.bash_profile\fR rather than \fI.bashrc\fR, or protect the local::lib invocation with a \f(CW$SHLVL\fR check: .PP .Vb 1 \& [ $SHLVL \-eq 1 ] && eval "$(perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib)" .Ve .PP If you are working with several \f(CW\*(C`local::lib\*(C'\fR environments, you may want to remove some of them from the current environment without disturbing the others. You can deactivate one environment like this (using bourne sh): .PP .Vb 1 \& eval $(perl \-Mlocal::lib=\-\-deactivate,~/path) .Ve .PP which will generate and run the commands needed to remove \f(CW\*(C`~/path\*(C'\fR from your various search paths. Whichever environment was \fBactivated most recently\fR will remain the target for module installations. That is, if you activate \&\f(CW\*(C`~/path_A\*(C'\fR and then you activate \f(CW\*(C`~/path_B\*(C'\fR, new modules you install will go in \f(CW\*(C`~/path_B\*(C'\fR. If you deactivate \f(CW\*(C`~/path_B\*(C'\fR then modules will be installed into \f(CW\*(C`~/pathA\*(C'\fR \*(-- but if you deactivate \f(CW\*(C`~/path_A\*(C'\fR then they will still be installed in \f(CW\*(C`~/pathB\*(C'\fR because pathB was activated later. .PP You can also ask \f(CW\*(C`local::lib\*(C'\fR to clean itself completely out of the current shell's environment with the \f(CW\*(C`\-\-deactivate\-all\*(C'\fR option. For multiple environments for multiple apps you may need to include a modified version of the \f(CW\*(C`use FindBin\*(C'\fR instructions in the \*(L"In code\*(R" sample above. If you did something like the above, you have a set of Perl modules at \f(CW\*(C`~/mydir1/lib\*(C'\fR. If you have a script at \f(CW\*(C`~/mydir1/scripts/myscript.pl\*(C'\fR, you need to tell it where to find the modules you installed for it at \f(CW\*(C`~/mydir1/lib\*(C'\fR. .PP In \f(CW\*(C`~/mydir1/scripts/myscript.pl\*(C'\fR: .PP .Vb 4 \& use strict; \& use warnings; \& use local::lib "$FindBin::Bin/.."; ### points to ~/mydir1 and local::lib finds lib \& use lib "$FindBin::Bin/../lib"; ### points to ~/mydir1/lib .Ve .PP Put this before any \s-1BEGIN\s0 { ... } blocks that require the modules you installed. .SS "Differences when using this module under Win32" .IX Subsection "Differences when using this module under Win32" To set up the proper environment variables for your current session of \&\f(CW\*(C`CMD.exe\*(C'\fR, you can use this: .PP .Vb 5 \& C:\e>perl \-Mlocal::lib \& set PERL_MB_OPT=\-\-install_base C:\eDOCUME~1\eADMINI~1\eperl5 \& set PERL_MM_OPT=INSTALL_BASE=C:\eDOCUME~1\eADMINI~1\eperl5 \& set PERL5LIB=C:\eDOCUME~1\eADMINI~1\eperl5\elib\eperl5 \& set PATH=C:\eDOCUME~1\eADMINI~1\eperl5\ebin;%PATH% \& \& ### To set the environment for this shell alone \& C:\e>perl \-Mlocal::lib > %TEMP%\etmp.bat && %TEMP%\etmp.bat && del %TEMP%\etmp.bat \& ### instead of $(perl \-Mlocal::lib=./) .Ve .PP If you want the environment entries to persist, you'll need to add them to the Control Panel's System applet yourself or use App::local::lib::Win32Helper. .PP The \*(L"~\*(R" is translated to the user's profile directory (the directory named for the user under \*(L"Documents and Settings\*(R" (Windows \s-1XP\s0 or earlier) or \*(L"Users\*(R" (Windows Vista or later)) unless \f(CW$ENV\fR{\s-1HOME\s0} exists. After that, the home directory is translated to a short name (which means the directory must exist) and the subdirectories are created. .PP \fIPowerShell\fR .IX Subsection "PowerShell" .PP local::lib also supports PowerShell, and can be used with the \&\f(CW\*(C`Invoke\-Expression\*(C'\fR cmdlet. .PP .Vb 1 \& Invoke\-Expression "$(perl \-Mlocal::lib)" .Ve .SH "RATIONALE" .IX Header "RATIONALE" The version of a Perl package on your machine is not always the version you need. Obviously, the best thing to do would be to update to the version you need. However, you might be in a situation where you're prevented from doing this. Perhaps you don't have system administrator privileges; or perhaps you are using a package management system such as Debian, and nobody has yet gotten around to packaging up the version you need. .PP local::lib solves this problem by allowing you to create your own directory of Perl packages downloaded from \s-1CPAN\s0 (in a multi-user system, this would typically be within your own home directory). The existing system Perl installation is not affected; you simply invoke Perl with special options so that Perl uses the packages in your own local package directory rather than the system packages. local::lib arranges things so that your locally installed version of the Perl packages takes precedence over the system installation. .PP If you are using a package management system (such as Debian), you don't need to worry about Debian and \s-1CPAN\s0 stepping on each other's toes. Your local version of the packages will be written to an entirely separate directory from those installed by Debian. .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module provides a quick, convenient way of bootstrapping a user-local Perl module library located within the user's home directory. It also constructs and prints out for the user the list of environment variables using the syntax appropriate for the user's current shell (as specified by the \f(CW\*(C`SHELL\*(C'\fR environment variable), suitable for directly adding to one's shell configuration file. .PP More generally, local::lib allows for the bootstrapping and usage of a directory containing Perl modules outside of Perl's \f(CW@INC\fR. This makes it easier to ship an application with an app-specific copy of a Perl module, or collection of modules. Useful in cases like when an upstream maintainer hasn't applied a patch to a module of theirs that you need for your application. .PP On import, local::lib sets the following environment variables to appropriate values: .IP "\s-1PERL_MB_OPT\s0" 4 .IX Item "PERL_MB_OPT" .PD 0 .IP "\s-1PERL_MM_OPT\s0" 4 .IX Item "PERL_MM_OPT" .IP "\s-1PERL5LIB\s0" 4 .IX Item "PERL5LIB" .IP "\s-1PATH\s0" 4 .IX Item "PATH" .IP "\s-1PERL_LOCAL_LIB_ROOT\s0" 4 .IX Item "PERL_LOCAL_LIB_ROOT" .PD .PP When possible, these will be appended to instead of overwritten entirely. .PP These values are then available for reference by any code after import. .SH "CREATING A SELF-CONTAINED SET OF MODULES" .IX Header "CREATING A SELF-CONTAINED SET OF MODULES" See lib::core::only for one way to do this \- but note that there are a number of caveats, and the best approach is always to perform a build against a clean perl (i.e. site and vendor as close to empty as possible). .SH "IMPORT OPTIONS" .IX Header "IMPORT OPTIONS" Options are values that can be passed to the \f(CW\*(C`local::lib\*(C'\fR import besides the directory to use. They are specified as \f(CW\*(C`use local::lib \*(Aq\-\-option\*(Aq[, path];\*(C'\fR or \f(CW\*(C`perl \-Mlocal::lib=\-\-option[,path]\*(C'\fR. .SS "\-\-deactivate" .IX Subsection "--deactivate" Remove the chosen path (or the default path) from the module search paths if it was added by \f(CW\*(C`local::lib\*(C'\fR, instead of adding it. .SS "\-\-deactivate\-all" .IX Subsection "--deactivate-all" Remove all directories that were added to search paths by \f(CW\*(C`local::lib\*(C'\fR from the search paths. .SS "\-\-quiet" .IX Subsection "--quiet" Don't output any messages about directories being created. .SS "\-\-always" .IX Subsection "--always" Always add directories to environment variables, ignoring if they are already included. .SS "\-\-shelltype" .IX Subsection "--shelltype" Specify the shell type to use for output. By default, the shell will be detected based on the environment. Should be one of: \f(CW\*(C`bourne\*(C'\fR, \f(CW\*(C`csh\*(C'\fR, \&\f(CW\*(C`cmd\*(C'\fR, or \f(CW\*(C`powershell\*(C'\fR. .SS "\-\-no\-create" .IX Subsection "--no-create" Prevents \f(CW\*(C`local::lib\*(C'\fR from creating directories when activating dirs. This is likely to cause issues on Win32 systems. .SH "CLASS METHODS" .IX Header "CLASS METHODS" .SS "ensure_dir_structure_for" .IX Subsection "ensure_dir_structure_for" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .IP "Return value: None" 4 .IX Item "Return value: None" .PD .PP Attempts to create a local::lib directory, including subdirectories and all required parent directories. Throws an exception on failure. .SS "print_environment_vars_for" .IX Subsection "print_environment_vars_for" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .IP "Return value: None" 4 .IX Item "Return value: None" .PD .PP Prints to standard output the variables listed above, properly set to use the given path as the base directory. .SS "build_environment_vars_for" .IX Subsection "build_environment_vars_for" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: %environment_vars" 4 .el .IP "Return value: \f(CW%environment_vars\fR" 4 .IX Item "Return value: %environment_vars" .PD .PP Returns a hash with the variables listed above, properly set to use the given path as the base directory. .SS "setup_env_hash_for" .IX Subsection "setup_env_hash_for" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .IP "Return value: None" 4 .IX Item "Return value: None" .PD .PP Constructs the \f(CW%ENV\fR keys for the given path, by calling \&\*(L"build_environment_vars_for\*(R". .SS "active_paths" .IX Subsection "active_paths" .IP "Arguments: None" 4 .IX Item "Arguments: None" .PD 0 .ie n .IP "Return value: @paths" 4 .el .IP "Return value: \f(CW@paths\fR" 4 .IX Item "Return value: @paths" .PD .PP Returns a list of active \f(CW\*(C`local::lib\*(C'\fR paths, according to the \&\f(CW\*(C`PERL_LOCAL_LIB_ROOT\*(C'\fR environment variable and verified against what is really in \f(CW@INC\fR. .SS "install_base_perl_path" .IX Subsection "install_base_perl_path" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $install_base_perl_path" 4 .el .IP "Return value: \f(CW$install_base_perl_path\fR" 4 .IX Item "Return value: $install_base_perl_path" .PD .PP Returns a path describing where to install the Perl modules for this local library installation. Appends the directories \f(CW\*(C`lib\*(C'\fR and \f(CW\*(C`perl5\*(C'\fR to the given path. .SS "lib_paths_for" .IX Subsection "lib_paths_for" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: @lib_paths" 4 .el .IP "Return value: \f(CW@lib_paths\fR" 4 .IX Item "Return value: @lib_paths" .PD .PP Returns the list of paths perl will search for libraries, given a base path. This includes the base path itself, the architecture specific subdirectory, and perl version specific subdirectories. These paths may not all exist. .SS "install_base_bin_path" .IX Subsection "install_base_bin_path" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $install_base_bin_path" 4 .el .IP "Return value: \f(CW$install_base_bin_path\fR" 4 .IX Item "Return value: $install_base_bin_path" .PD .PP Returns a path describing where to install the executable programs for this local library installation. Appends the directory \f(CW\*(C`bin\*(C'\fR to the given path. .SS "installer_options_for" .IX Subsection "installer_options_for" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: %installer_env_vars" 4 .el .IP "Return value: \f(CW%installer_env_vars\fR" 4 .IX Item "Return value: %installer_env_vars" .PD .PP Returns a hash of environment variables that should be set to cause installation into the given path. .SS "resolve_empty_path" .IX Subsection "resolve_empty_path" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $base_path" 4 .el .IP "Return value: \f(CW$base_path\fR" 4 .IX Item "Return value: $base_path" .PD .PP Builds and returns the base path into which to set up the local module installation. Defaults to \f(CW\*(C`~/perl5\*(C'\fR. .SS "resolve_home_path" .IX Subsection "resolve_home_path" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $home_path" 4 .el .IP "Return value: \f(CW$home_path\fR" 4 .IX Item "Return value: $home_path" .PD .PP Attempts to find the user's home directory. If no definite answer is available, throws an exception. .SS "resolve_relative_path" .IX Subsection "resolve_relative_path" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $absolute_path" 4 .el .IP "Return value: \f(CW$absolute_path\fR" 4 .IX Item "Return value: $absolute_path" .PD .PP Translates the given path into an absolute path. .SS "resolve_path" .IX Subsection "resolve_path" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $absolute_path" 4 .el .IP "Return value: \f(CW$absolute_path\fR" 4 .IX Item "Return value: $absolute_path" .PD .PP Calls the following in a pipeline, passing the result from the previous to the next, in an attempt to find where to configure the environment for a local library installation: \*(L"resolve_empty_path\*(R", \*(L"resolve_home_path\*(R", \&\*(L"resolve_relative_path\*(R". Passes the given path argument to \&\*(L"resolve_empty_path\*(R" which then returns a result that is passed to \&\*(L"resolve_home_path\*(R", which then has its result passed to \&\*(L"resolve_relative_path\*(R". The result of this final call is returned from \&\*(L"resolve_path\*(R". .SH "OBJECT INTERFACE" .IX Header "OBJECT INTERFACE" .SS "new" .IX Subsection "new" .ie n .IP "Arguments: %attributes" 4 .el .IP "Arguments: \f(CW%attributes\fR" 4 .IX Item "Arguments: %attributes" .PD 0 .ie n .IP "Return value: $local_lib" 4 .el .IP "Return value: \f(CW$local_lib\fR" 4 .IX Item "Return value: $local_lib" .PD .PP Constructs a new \f(CW\*(C`local::lib\*(C'\fR object, representing the current state of \&\f(CW@INC\fR and the relevant environment variables. .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" .SS "roots" .IX Subsection "roots" An arrayref representing active \f(CW\*(C`local::lib\*(C'\fR directories. .SS "inc" .IX Subsection "inc" An arrayref representing \f(CW@INC\fR. .SS "libs" .IX Subsection "libs" An arrayref representing the \s-1PERL5LIB\s0 environment variable. .SS "bins" .IX Subsection "bins" An arrayref representing the \s-1PATH\s0 environment variable. .SS "extra" .IX Subsection "extra" A hashref of extra environment variables (e.g. \f(CW\*(C`PERL_MM_OPT\*(C'\fR and \&\f(CW\*(C`PERL_MB_OPT\*(C'\fR) .SS "no_create" .IX Subsection "no_create" If set, \f(CW\*(C`local::lib\*(C'\fR will not try to create directories when activating them. .SH "OBJECT METHODS" .IX Header "OBJECT METHODS" .SS "clone" .IX Subsection "clone" .ie n .IP "Arguments: %attributes" 4 .el .IP "Arguments: \f(CW%attributes\fR" 4 .IX Item "Arguments: %attributes" .PD 0 .ie n .IP "Return value: $local_lib" 4 .el .IP "Return value: \f(CW$local_lib\fR" 4 .IX Item "Return value: $local_lib" .PD .PP Constructs a new \f(CW\*(C`local::lib\*(C'\fR object based on the existing one, overriding the specified attributes. .SS "activate" .IX Subsection "activate" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $new_local_lib" 4 .el .IP "Return value: \f(CW$new_local_lib\fR" 4 .IX Item "Return value: $new_local_lib" .PD .PP Constructs a new instance with the specified path active. .SS "deactivate" .IX Subsection "deactivate" .ie n .IP "Arguments: $path" 4 .el .IP "Arguments: \f(CW$path\fR" 4 .IX Item "Arguments: $path" .PD 0 .ie n .IP "Return value: $new_local_lib" 4 .el .IP "Return value: \f(CW$new_local_lib\fR" 4 .IX Item "Return value: $new_local_lib" .PD .PP Constructs a new instance with the specified path deactivated. .SS "deactivate_all" .IX Subsection "deactivate_all" .IP "Arguments: None" 4 .IX Item "Arguments: None" .PD 0 .ie n .IP "Return value: $new_local_lib" 4 .el .IP "Return value: \f(CW$new_local_lib\fR" 4 .IX Item "Return value: $new_local_lib" .PD .PP Constructs a new instance with all \f(CW\*(C`local::lib\*(C'\fR directories deactivated. .SS "environment_vars_string" .IX Subsection "environment_vars_string" .ie n .IP "Arguments: [ $shelltype ]" 4 .el .IP "Arguments: [ \f(CW$shelltype\fR ]" 4 .IX Item "Arguments: [ $shelltype ]" .PD 0 .ie n .IP "Return value: $shell_env_string" 4 .el .IP "Return value: \f(CW$shell_env_string\fR" 4 .IX Item "Return value: $shell_env_string" .PD .PP Returns a string to set up the \f(CW\*(C`local::lib\*(C'\fR, meant to be run by a shell. .SS "build_environment_vars" .IX Subsection "build_environment_vars" .IP "Arguments: None" 4 .IX Item "Arguments: None" .PD 0 .ie n .IP "Return value: %environment_vars" 4 .el .IP "Return value: \f(CW%environment_vars\fR" 4 .IX Item "Return value: %environment_vars" .PD .PP Returns a hash with the variables listed above, properly set to use the given path as the base directory. .SS "setup_env_hash" .IX Subsection "setup_env_hash" .IP "Arguments: None" 4 .IX Item "Arguments: None" .PD 0 .IP "Return value: None" 4 .IX Item "Return value: None" .PD .PP Constructs the \f(CW%ENV\fR keys for the given path, by calling \&\*(L"build_environment_vars\*(R". .SS "setup_local_lib" .IX Subsection "setup_local_lib" Constructs the \f(CW%ENV\fR hash using \*(L"setup_env_hash\*(R", and set up \f(CW@INC\fR. .SH "A WARNING ABOUT UNINST=1" .IX Header "A WARNING ABOUT UNINST=1" Be careful about using local::lib in combination with \*(L"make install UNINST=1\*(R". The idea of this feature is that will uninstall an old version of a module before installing a new one. However it lacks a safety check that the old version and the new version will go in the same directory. Used in combination with local::lib, you can potentially delete a globally accessible version of a module while installing the new version in a local place. Only combine \*(L"make install UNINST=1\*(R" and local::lib if you understand these possible consequences. .SH "LIMITATIONS" .IX Header "LIMITATIONS" .IP "\(bu" 4 Directory names with spaces in them are not well supported by the perl toolchain and the programs it uses. Pure-perl distributions should support spaces, but problems are more likely with dists that require compilation. A workaround you can do is moving your local::lib to a directory with spaces \&\fBafter\fR you installed all modules inside your local::lib bootstrap. But be aware that you can't update or install \s-1CPAN\s0 modules after the move. .IP "\(bu" 4 Rather basic shell detection. Right now anything with csh in its name is assumed to be a C shell or something compatible, and everything else is assumed to be Bourne, except on Win32 systems. If the \f(CW\*(C`SHELL\*(C'\fR environment variable is not set, a Bourne-compatible shell is assumed. .IP "\(bu" 4 Kills any existing \s-1PERL_MM_OPT\s0 or \s-1PERL_MB_OPT.\s0 .IP "\(bu" 4 Should probably auto-fixup \s-1CPAN\s0 config if not already done. .IP "\(bu" 4 On \s-1VMS\s0 and MacOS Classic (pre-OS X), local::lib loads File::Spec. This means any File::Spec version installed in the local::lib will be ignored by scripts using local::lib. A workaround for this is using \&\f(CW\*(C`use lib "$local_lib/lib/perl5";\*(C'\fR instead of using \f(CW\*(C`local::lib\*(C'\fR directly. .IP "\(bu" 4 Conflicts with ExtUtils::MakeMaker's \f(CW\*(C`PREFIX\*(C'\fR option. \&\f(CW\*(C`local::lib\*(C'\fR uses the \f(CW\*(C`INSTALL_BASE\*(C'\fR option, as it has more predictable and sane behavior. If something attempts to use the \f(CW\*(C`PREFIX\*(C'\fR option when running a \fIMakefile.PL\fR, ExtUtils::MakeMaker will refuse to run, as the two options conflict. This can be worked around by temporarily unsetting the \&\f(CW\*(C`PERL_MM_OPT\*(C'\fR environment variable. .IP "\(bu" 4 Conflicts with Module::Build's \f(CW\*(C`\-\-prefix\*(C'\fR option. Similar to the previous limitation, but any \f(CW\*(C`\-\-prefix\*(C'\fR option specified will be ignored. This can be worked around by temporarily unsetting the \f(CW\*(C`PERL_MB_OPT\*(C'\fR environment variable. .PP Patches very much welcome for any of the above. .IP "\(bu" 4 On Win32 systems, does not have a way to write the created environment variables to the registry, so that they can persist through a reboot. .SH "TROUBLESHOOTING" .IX Header "TROUBLESHOOTING" If you've configured local::lib to install \s-1CPAN\s0 modules somewhere in to your home directory, and at some point later you try to install a module with \f(CW\*(C`cpan \&\-i Foo::Bar\*(C'\fR, but it fails with an error like: \f(CW\*(C`Warning: You do not have permissions to install into /usr/lib64/perl5/site_perl/5.8.8/x86_64\-linux at /usr/lib64/perl5/5.8.8/Foo/Bar.pm\*(C'\fR and buried within the install log is an error saying \f(CW\*(C`\*(AqINSTALL_BASE\*(Aq is not a known MakeMaker parameter name\*(C'\fR, then you've somehow lost your updated ExtUtils::MakeMaker module. .PP To remedy this situation, rerun the bootstrapping procedure documented above. .PP Then, run \f(CW\*(C`rm \-r ~/.cpan/build/Foo\-Bar*\*(C'\fR .PP Finally, re-run \f(CW\*(C`cpan \-i Foo::Bar\*(C'\fR and it should install without problems. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" .IP "\s-1SHELL\s0" 4 .IX Item "SHELL" .PD 0 .IP "\s-1COMSPEC\s0" 4 .IX Item "COMSPEC" .PD local::lib looks at the user's \f(CW\*(C`SHELL\*(C'\fR environment variable when printing out commands to add to the shell configuration file. .Sp On Win32 systems, \f(CW\*(C`COMSPEC\*(C'\fR is also examined. .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 4 Perl Advent article, 2011 <http://perladvent.org/2011/2011-12-01.html> .SH "SUPPORT" .IX Header "SUPPORT" \&\s-1IRC:\s0 .PP .Vb 1 \& Join #toolchain on irc.perl.org. .Ve .SH "AUTHOR" .IX Header "AUTHOR" Matt S Trout <mst@shadowcat.co.uk> http://www.shadowcat.co.uk/ .PP auto_install fixes kindly sponsored by http://www.takkle.com/ .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" Patches to correctly output commands for csh style shells, as well as some documentation additions, contributed by Christopher Nehren <apeiron@cpan.org>. .PP Doc patches for a custom local::lib directory, more cleanups in the english documentation and a german documentation contributed by Torsten Raudssus <torsten@raudssus.de>. .PP Hans Dieter Pearcey <hdp@cpan.org> sent in some additional tests for ensuring things will install properly, submitted a fix for the bug causing problems with writing Makefiles during bootstrapping, contributed an example program, and submitted yet another fix to ensure that local::lib can install and bootstrap properly. Many, many thanks! .PP pattern of Freenode \s-1IRC\s0 contributed the beginnings of the Troubleshooting section. Many thanks! .PP Patch to add Win32 support contributed by Curtis Jewell <csjewell@cpan.org>. .PP Warnings for missing \s-1PATH/PERL5LIB\s0 (as when not running interactively) silenced by a patch from Marco Emilio Poleggi. .PP Mark Stosberg <mark@summersault.com> provided the code for the now deleted \&'\-\-self\-contained' option. .PP Documentation patches to make win32 usage clearer by David Mertens <dcmertens.perl@gmail.com> (run4flat). .PP Brazilian portuguese translation and minor doc patches contributed by Breno G. de Oliveira <garu@cpan.org>. .PP Improvements to stacking multiple local::lib dirs and removing them from the environment later on contributed by Andrew Rodland <arodland@cpan.org>. .PP Patch for Carp version mismatch contributed by Hakim Cassimally <osfameron@cpan.org>. .PP Rewrite of internals and numerous bug fixes and added features contributed by Graham Knop <haarg@haarg.org>. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2007 \- 2013 the local::lib \*(L"\s-1AUTHOR\*(R"\s0 and \*(L"\s-1CONTRIBUTORS\*(R"\s0 as listed above. .SH "LICENSE" .IX Header "LICENSE" 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/Try::Tiny.3pm������������������������������������������������������������������������������0000444�����������������00000050500�15253012307�0010400 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "Try::Tiny 3" .TH Try::Tiny 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" Try::Tiny \- Minimal try/catch with proper preservation of $@ .SH "VERSION" .IX Header "VERSION" version 0.31 .SH "SYNOPSIS" .IX Header "SYNOPSIS" You can use Try::Tiny's \f(CW\*(C`try\*(C'\fR and \f(CW\*(C`catch\*(C'\fR to expect and handle exceptional conditions, avoiding quirks in Perl and common mistakes: .PP .Vb 6 \& # handle errors with a catch handler \& try { \& die "foo"; \& } catch { \& warn "caught error: $_"; # not $@ \& }; .Ve .PP You can also use it like a standalone \f(CW\*(C`eval\*(C'\fR to catch and ignore any error conditions. Obviously, this is an extreme measure not to be undertaken lightly: .PP .Vb 4 \& # just silence errors \& try { \& die "foo"; \& }; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module provides bare bones \f(CW\*(C`try\*(C'\fR/\f(CW\*(C`catch\*(C'\fR/\f(CW\*(C`finally\*(C'\fR statements that are designed to minimize common mistakes with eval blocks, and \s-1NOTHING\s0 else. .PP This is unlike TryCatch which provides a nice syntax and avoids adding another call stack layer, and supports calling \f(CW\*(C`return\*(C'\fR from the \f(CW\*(C`try\*(C'\fR block to return from the parent subroutine. These extra features come at a cost of a few dependencies, namely Devel::Declare and Scope::Upper which are occasionally problematic, and the additional catch filtering uses Moose type constraints which may not be desirable either. .PP The main focus of this module is to provide simple and reliable error handling for those having a hard time installing TryCatch, but who still want to write correct \f(CW\*(C`eval\*(C'\fR blocks without 5 lines of boilerplate each time. .PP It's designed to work as correctly as possible in light of the various pathological edge cases (see \*(L"\s-1BACKGROUND\*(R"\s0) and to be compatible with any style of error values (simple strings, references, objects, overloaded objects, etc). .PP If the \f(CW\*(C`try\*(C'\fR block dies, it returns the value of the last statement executed in the \f(CW\*(C`catch\*(C'\fR block, if there is one. Otherwise, it returns \f(CW\*(C`undef\*(C'\fR in scalar context or the empty list in list context. The following examples all assign \f(CW"bar"\fR to \f(CW$x\fR: .PP .Vb 3 \& my $x = try { die "foo" } catch { "bar" }; \& my $x = try { die "foo" } || "bar"; \& my $x = (try { die "foo" }) // "bar"; \& \& my $x = eval { die "foo" } || "bar"; .Ve .PP You can add \f(CW\*(C`finally\*(C'\fR blocks, yielding the following: .PP .Vb 3 \& my $x; \& try { die \*(Aqfoo\*(Aq } finally { $x = \*(Aqbar\*(Aq }; \& try { die \*(Aqfoo\*(Aq } catch { warn "Got a die: $_" } finally { $x = \*(Aqbar\*(Aq }; .Ve .PP \&\f(CW\*(C`finally\*(C'\fR blocks are always executed making them suitable for cleanup code which cannot be handled using local. You can add as many \f(CW\*(C`finally\*(C'\fR blocks to a given \f(CW\*(C`try\*(C'\fR block as you like. .PP Note that adding a \f(CW\*(C`finally\*(C'\fR block without a preceding \f(CW\*(C`catch\*(C'\fR block suppresses any errors. This behaviour is consistent with using a standalone \&\f(CW\*(C`eval\*(C'\fR, but it is not consistent with \f(CW\*(C`try\*(C'\fR/\f(CW\*(C`finally\*(C'\fR patterns found in other programming languages, such as Java, Python, Javascript or C#. If you learned the \f(CW\*(C`try\*(C'\fR/\f(CW\*(C`finally\*(C'\fR pattern from one of these languages, watch out for this. .SH "EXPORTS" .IX Header "EXPORTS" All functions are exported by default using Exporter. .PP If you need to rename the \f(CW\*(C`try\*(C'\fR, \f(CW\*(C`catch\*(C'\fR or \f(CW\*(C`finally\*(C'\fR keyword consider using Sub::Import to get Sub::Exporter's flexibility. .IP "try (&;@)" 4 .IX Item "try (&;@)" Takes one mandatory \f(CW\*(C`try\*(C'\fR subroutine, an optional \f(CW\*(C`catch\*(C'\fR subroutine and \f(CW\*(C`finally\*(C'\fR subroutine. .Sp The mandatory subroutine is evaluated in the context of an \f(CW\*(C`eval\*(C'\fR block. .Sp If no error occurred the value from the first block is returned, preserving list/scalar context. .Sp If there was an error and the second subroutine was given it will be invoked with the error in \f(CW$_\fR (localized) and as that block's first and only argument. .Sp \&\f(CW$@\fR does \fBnot\fR contain the error. Inside the \f(CW\*(C`catch\*(C'\fR block it has the same value it had before the \f(CW\*(C`try\*(C'\fR block was executed. .Sp Note that the error may be false, but if that happens the \f(CW\*(C`catch\*(C'\fR block will still be invoked. .Sp Once all execution is finished then the \f(CW\*(C`finally\*(C'\fR block, if given, will execute. .IP "catch (&;@)" 4 .IX Item "catch (&;@)" Intended to be used in the second argument position of \f(CW\*(C`try\*(C'\fR. .Sp Returns a reference to the subroutine it was given but blessed as \&\f(CW\*(C`Try::Tiny::Catch\*(C'\fR which allows try to decode correctly what to do with this code reference. .Sp .Vb 1 \& catch { ... } .Ve .Sp Inside the \f(CW\*(C`catch\*(C'\fR block the caught error is stored in \f(CW$_\fR, while previous value of \f(CW$@\fR is still available for use. This value may or may not be meaningful depending on what happened before the \f(CW\*(C`try\*(C'\fR, but it might be a good idea to preserve it in an error stack. .Sp For code that captures \f(CW$@\fR when throwing new errors (i.e. Class::Throwable), you'll need to do: .Sp .Vb 1 \& local $@ = $_; .Ve .IP "finally (&;@)" 4 .IX Item "finally (&;@)" .Vb 3 \& try { ... } \& catch { ... } \& finally { ... }; .Ve .Sp Or .Sp .Vb 2 \& try { ... } \& finally { ... }; .Ve .Sp Or even .Sp .Vb 3 \& try { ... } \& finally { ... } \& catch { ... }; .Ve .Sp Intended to be the second or third element of \f(CW\*(C`try\*(C'\fR. \f(CW\*(C`finally\*(C'\fR blocks are always executed in the event of a successful \f(CW\*(C`try\*(C'\fR or if \f(CW\*(C`catch\*(C'\fR is run. This allows you to locate cleanup code which cannot be done via \f(CW\*(C`local()\*(C'\fR e.g. closing a file handle. .Sp When invoked, the \f(CW\*(C`finally\*(C'\fR block is passed the error that was caught. If no error was caught, it is passed nothing. (Note that the \f(CW\*(C`finally\*(C'\fR block does not localize \f(CW$_\fR with the error, since unlike in a \f(CW\*(C`catch\*(C'\fR block, there is no way to know if \f(CW\*(C`$_ == undef\*(C'\fR implies that there were no errors.) In other words, the following code does just what you would expect: .Sp .Vb 11 \& try { \& die_sometimes(); \& } catch { \& # ...code run in case of error \& } finally { \& if (@_) { \& print "The try block died with: @_\en"; \& } else { \& print "The try block ran without error.\en"; \& } \& }; .Ve .Sp \&\fBYou must always do your own error handling in the \f(CB\*(C`finally\*(C'\fB block\fR. \f(CW\*(C`Try::Tiny\*(C'\fR will not do anything about handling possible errors coming from code located in these blocks. .Sp Furthermore \fBexceptions in \f(CB\*(C`finally\*(C'\fB blocks are not trappable and are unable to influence the execution of your program\fR. This is due to limitation of \&\f(CW\*(C`DESTROY\*(C'\fR\-based scope guards, which \f(CW\*(C`finally\*(C'\fR is implemented on top of. This may change in a future version of Try::Tiny. .Sp In the same way \f(CW\*(C`catch()\*(C'\fR blesses the code reference this subroutine does the same except it bless them as \f(CW\*(C`Try::Tiny::Finally\*(C'\fR. .SH "BACKGROUND" .IX Header "BACKGROUND" There are a number of issues with \f(CW\*(C`eval\*(C'\fR. .SS "Clobbering $@" .IX Subsection "Clobbering $@" When you run an \f(CW\*(C`eval\*(C'\fR block and it succeeds, \f(CW$@\fR will be cleared, potentially clobbering an error that is currently being caught. .PP This causes action at a distance, clearing previous errors your caller may have not yet handled. .PP \&\f(CW$@\fR must be properly localized before invoking \f(CW\*(C`eval\*(C'\fR in order to avoid this issue. .PP More specifically, before Perl version 5.14.0 \&\f(CW$@\fR was clobbered at the beginning of the \f(CW\*(C`eval\*(C'\fR, which also made it impossible to capture the previous error before you die (for instance when making exception objects with error stacks). .PP For this reason \f(CW\*(C`try\*(C'\fR will actually set \f(CW$@\fR to its previous value (the one available before entering the \f(CW\*(C`try\*(C'\fR block) in the beginning of the \f(CW\*(C`eval\*(C'\fR block. .SS "Localizing $@ silently masks errors" .IX Subsection "Localizing $@ silently masks errors" Inside an \f(CW\*(C`eval\*(C'\fR block, \f(CW\*(C`die\*(C'\fR behaves sort of like: .PP .Vb 4 \& sub die { \& $@ = $_[0]; \& return_undef_from_eval(); \& } .Ve .PP This means that if you were polite and localized \f(CW$@\fR you can't die in that scope, or your error will be discarded (printing \*(L"Something's wrong\*(R" instead). .PP The workaround is very ugly: .PP .Vb 5 \& my $error = do { \& local $@; \& eval { ... }; \& $@; \& }; \& \& ... \& die $error; .Ve .SS "$@ might not be a true value" .IX Subsection "$@ might not be a true value" This code is wrong: .PP .Vb 3 \& if ( $@ ) { \& ... \& } .Ve .PP because due to the previous caveats it may have been unset. .PP \&\f(CW$@\fR could also be an overloaded error object that evaluates to false, but that's asking for trouble anyway. .PP The classic failure mode (fixed in Perl 5.14.0) is: .PP .Vb 3 \& sub Object::DESTROY { \& eval { ... } \& } \& \& eval { \& my $obj = Object\->new; \& \& die "foo"; \& }; \& \& if ( $@ ) { \& \& } .Ve .PP In this case since \f(CW\*(C`Object::DESTROY\*(C'\fR is not localizing \f(CW$@\fR but still uses \&\f(CW\*(C`eval\*(C'\fR, it will set \f(CW$@\fR to \f(CW""\fR. .PP The destructor is called when the stack is unwound, after \f(CW\*(C`die\*(C'\fR sets \f(CW$@\fR to \&\f(CW"foo at Foo.pm line 42\en"\fR, so by the time \f(CW\*(C`if ( $@ )\*(C'\fR is evaluated it has been cleared by \f(CW\*(C`eval\*(C'\fR in the destructor. .PP The workaround for this is even uglier than the previous ones. Even though we can't save the value of \f(CW$@\fR from code that doesn't localize, we can at least be sure the \f(CW\*(C`eval\*(C'\fR was aborted due to an error: .PP .Vb 2 \& my $failed = not eval { \& ... \& \& return 1; \& }; .Ve .PP This is because an \f(CW\*(C`eval\*(C'\fR that caught a \f(CW\*(C`die\*(C'\fR will always return a false value. .SH "ALTERNATE SYNTAX" .IX Header "ALTERNATE SYNTAX" Using Perl 5.10 you can use \*(L"Switch statements\*(R" in perlsyn (but please don't, because that syntax has since been deprecated because there was too much unexpected magical behaviour). .PP The \f(CW\*(C`catch\*(C'\fR block is invoked in a topicalizer context (like a \f(CW\*(C`given\*(C'\fR block), but note that you can't return a useful value from \f(CW\*(C`catch\*(C'\fR using the \f(CW\*(C`when\*(C'\fR blocks without an explicit \f(CW\*(C`return\*(C'\fR. .PP This is somewhat similar to Perl 6's \f(CW\*(C`CATCH\*(C'\fR blocks. You can use it to concisely match errors: .PP .Vb 6 \& try { \& require Foo; \& } catch { \& when (/^Can\*(Aqt locate .*?\e.pm in \e@INC/) { } # ignore \& default { die $_ } \& }; .Ve .SH "CAVEATS" .IX Header "CAVEATS" .IP "\(bu" 4 \&\f(CW@_\fR is not available within the \f(CW\*(C`try\*(C'\fR block, so you need to copy your argument list. In case you want to work with argument values directly via \f(CW@_\fR aliasing (i.e. allow \f(CW\*(C`$_[1] = "foo"\*(C'\fR), you need to pass \f(CW@_\fR by reference: .Sp .Vb 4 \& sub foo { \& my ( $self, @args ) = @_; \& try { $self\->bar(@args) } \& } .Ve .Sp or .Sp .Vb 5 \& sub bar_in_place { \& my $self = shift; \& my $args = \e@_; \& try { $_ = $self\->bar($_) for @$args } \& } .Ve .IP "\(bu" 4 \&\f(CW\*(C`return\*(C'\fR returns from the \f(CW\*(C`try\*(C'\fR block, not from the parent sub (note that this is also how \f(CW\*(C`eval\*(C'\fR works, but not how TryCatch works): .Sp .Vb 7 \& sub parent_sub { \& try { \& die; \& } \& catch { \& return; \& }; \& \& say "this text WILL be displayed, even though an exception is thrown"; \& } .Ve .Sp Instead, you should capture the return value: .Sp .Vb 6 \& sub parent_sub { \& my $success = try { \& die; \& 1; \& }; \& return unless $success; \& \& say "This text WILL NEVER appear!"; \& } \& # OR \& sub parent_sub_with_catch { \& my $success = try { \& die; \& 1; \& } \& catch { \& # do something with $_ \& return undef; #see note \& }; \& return unless $success; \& \& say "This text WILL NEVER appear!"; \& } .Ve .Sp Note that if you have a \f(CW\*(C`catch\*(C'\fR block, it must return \f(CW\*(C`undef\*(C'\fR for this to work, since if a \f(CW\*(C`catch\*(C'\fR block exists, its return value is returned in place of \f(CW\*(C`undef\*(C'\fR when an exception is thrown. .IP "\(bu" 4 \&\f(CW\*(C`try\*(C'\fR introduces another caller stack frame. Sub::Uplevel is not used. Carp will not report this when using full stack traces, though, because \&\f(CW%Carp::Internal\fR is used. This lack of magic is considered a feature. .IP "\(bu" 4 The value of \f(CW$_\fR in the \f(CW\*(C`catch\*(C'\fR block is not guaranteed to be the value of the exception thrown (\f(CW$@\fR) in the \f(CW\*(C`try\*(C'\fR block. There is no safe way to ensure this, since \f(CW\*(C`eval\*(C'\fR may be used unhygienically in destructors. The only guarantee is that the \f(CW\*(C`catch\*(C'\fR will be called if an exception is thrown. .IP "\(bu" 4 The return value of the \f(CW\*(C`catch\*(C'\fR block is not ignored, so if testing the result of the expression for truth on success, be sure to return a false value from the \f(CW\*(C`catch\*(C'\fR block: .Sp .Vb 4 \& my $obj = try { \& MightFail\->new; \& } catch { \& ... \& \& return; # avoid returning a true value; \& }; \& \& return unless $obj; .Ve .IP "\(bu" 4 \&\f(CW$SIG{_\|_DIE_\|_}\fR is still in effect. .Sp Though it can be argued that \f(CW$SIG{_\|_DIE_\|_}\fR should be disabled inside of \&\f(CW\*(C`eval\*(C'\fR blocks, since it isn't people have grown to rely on it. Therefore in the interests of compatibility, \f(CW\*(C`try\*(C'\fR does not disable \f(CW$SIG{_\|_DIE_\|_}\fR for the scope of the error throwing code. .IP "\(bu" 4 Lexical \f(CW$_\fR may override the one set by \f(CW\*(C`catch\*(C'\fR. .Sp For example Perl 5.10's \f(CW\*(C`given\*(C'\fR form uses a lexical \f(CW$_\fR, creating some confusing behavior: .Sp .Vb 10 \& given ($foo) { \& when (...) { \& try { \& ... \& } catch { \& warn $_; # will print $foo, not the error \& warn $_[0]; # instead, get the error like this \& } \& } \& } .Ve .Sp Note that this behavior was changed once again in Perl5 version 18 <https://metacpan.org/module/perldelta#given-now-aliases-the-global-_>. However, since the entirety of lexical \f(CW$_\fR is now considered experimental <https://metacpan.org/module/perldelta#Lexical-_-is-now-experimental>, it is unclear whether the new version 18 behavior is final. .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "Syntax::Keyword::Try" 4 .IX Item "Syntax::Keyword::Try" Only available on perls >= 5.14, with a slightly different syntax (e.g. no trailing \f(CW\*(C`;\*(C'\fR because it's actually a keyword, not a sub, but this means you can \f(CW\*(C`return\*(C'\fR and \f(CW\*(C`next\*(C'\fR within it). Use Feature::Compat::Try to automatically switch to the native \f(CW\*(C`try\*(C'\fR syntax in newer perls (when available). See also Try Catch Exception Handling. .IP "TryCatch" 4 .IX Item "TryCatch" Much more feature complete, more convenient semantics, but at the cost of implementation complexity. .IP "autodie" 4 .IX Item "autodie" Automatic error throwing for builtin functions and more. Also designed to work well with \f(CW\*(C`given\*(C'\fR/\f(CW\*(C`when\*(C'\fR. .IP "Throwable" 4 .IX Item "Throwable" A lightweight role for rolling your own exception classes. .IP "Error" 4 .IX Item "Error" Exception object implementation with a \f(CW\*(C`try\*(C'\fR statement. Does not localize \&\f(CW$@\fR. .IP "Exception::Class::TryCatch" 4 .IX Item "Exception::Class::TryCatch" Provides a \f(CW\*(C`catch\*(C'\fR statement, but properly calling \f(CW\*(C`eval\*(C'\fR is your responsibility. .Sp The \f(CW\*(C`try\*(C'\fR keyword pushes \f(CW$@\fR onto an error stack, avoiding some of the issues with \f(CW$@\fR, but you still need to localize to prevent clobbering. .SH "LIGHTNING TALK" .IX Header "LIGHTNING TALK" I gave a lightning talk about this module, you can see the slides (Firefox only): .PP <http://web.archive.org/web/20100628040134/http://nothingmuch.woobling.org/talks/takahashi.xul> .PP Or read the source: .PP <http://web.archive.org/web/20100305133605/http://nothingmuch.woobling.org/talks/yapc_asia_2009/try_tiny.yml> .SH "SUPPORT" .IX Header "SUPPORT" Bugs may be submitted through the \s-1RT\s0 bug tracker <https://rt.cpan.org/Public/Dist/Display.html?Name=Try-Tiny> (or bug\-Try\-Tiny@rt.cpan.org <mailto:bug-Try-Tiny@rt.cpan.org>). .SH "AUTHORS" .IX Header "AUTHORS" .IP "\(bu" 4 יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org> .IP "\(bu" 4 Jesse Luehrs <doy@tozt.net> .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" .IP "\(bu" 4 Karen Etheridge <ether@cpan.org> .IP "\(bu" 4 Peter Rabbitson <ribasushi@cpan.org> .IP "\(bu" 4 Ricardo Signes <rjbs@cpan.org> .IP "\(bu" 4 Mark Fowler <mark@twoshortplanks.com> .IP "\(bu" 4 Graham Knop <haarg@haarg.org> .IP "\(bu" 4 Aristotle Pagaltzis <pagaltzis@gmx.de> .IP "\(bu" 4 Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> .IP "\(bu" 4 Lukas Mai <l.mai@web.de> .IP "\(bu" 4 Alex <alex@koban.(none)> .IP "\(bu" 4 anaxagoras <walkeraj@gmail.com> .IP "\(bu" 4 Andrew Yates <ayates@haddock.local> .IP "\(bu" 4 awalker <awalker@sourcefire.com> .IP "\(bu" 4 chromatic <chromatic@wgz.org> .IP "\(bu" 4 cm-perl <cm\-perl@users.noreply.github.com> .IP "\(bu" 4 David Lowe <davidl@lokku.com> .IP "\(bu" 4 Glenn Fowler <cebjyre@cpan.org> .IP "\(bu" 4 Hans Dieter Pearcey <hdp@weftsoar.net> .IP "\(bu" 4 Jens Berthold <jens@jebecs.de> .IP "\(bu" 4 Jonathan Yu <JAWNSY@cpan.org> .IP "\(bu" 4 Marc Mims <marc@questright.com> .IP "\(bu" 4 Mark Stosberg <mark@stosberg.com> .IP "\(bu" 4 Pali <pali@cpan.org> .IP "\(bu" 4 Paul Howarth <paul@city\-fan.org> .IP "\(bu" 4 Rudolf Leermakers <rudolf@hatsuseno.org> .SH "COPYRIGHT AND LICENCE" .IX Header "COPYRIGHT AND LICENCE" This software is Copyright (c) 2009 by יובל קוג'מן (Yuval Kogman). .PP This is free software, licensed under: .PP .Vb 1 \& The MIT (X11) License .Ve ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/version::Internals.3pm���������������������������������������������������������������������0000444�����������������00000073113�15253012307�0012330 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2022-07-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" 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 <jpeacock@cpan.org> .SH "SEE ALSO" .IX Header "SEE ALSO" perl. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Admin.3pm����������������������������������������������������������������������������0000444�����������������00000010446�15253012307�0010455 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Admin 3" .TH CPAN::Admin 3 "2018-11-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" .Vb 1 \& CPAN::Admin \- A CPAN Shell for CPAN admins .Ve .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& perl \-MCPAN::Admin \-e shell .Ve .SH "STATUS" .IX Header "STATUS" Note: this module is currently not maintained. If you need it and fix it for your needs, please submit patches. .SH "DESCRIPTION" .IX Header "DESCRIPTION" CPAN::Admin is a subclass of \s-1CPAN\s0 that adds the commands \f(CW\*(C`register\*(C'\fR and \f(CW\*(C`modsearch\*(C'\fR to the \s-1CPAN\s0 shell. .PP \&\f(CW\*(C`register\*(C'\fR calls \f(CW\*(C`get\*(C'\fR on the named module, assembles a couple of informations (description, language), and calls Netscape with the \&\-remote argument so that a form is filled with all the assembled informations and the registration can be performed with a single click. If the command line has more than one argument, register does not run a \f(CW\*(C`get\*(C'\fR, instead it interprets the rest of the line as \s-1DSLI\s0 status, description, and userid and sends them to netscape such that the form is again mostly filled and can be edited or confirmed with a single click. CPAN::Admin never performs the submission click for you, it is only intended to fill in the form on \s-1PAUSE\s0 and leave the confirmation to you. .PP \&\f(CW\*(C`modsearch\*(C'\fR simply passes the arguments to the search engine for the modules@perl.org mailing list at <http://www.xray.mpe.mpg.de> where all registration requests are stored. It does so in the same way as register, namely with the \f(CW\*(C`netscape \-remote\*(C'\fR command. .PP An experimental feature has also been added, namely to color already registered modules in listings. If you have Term::ANSIColor installed, the u, r, and m commands will show already registered modules in green. .SH "PREREQUISITES" .IX Header "PREREQUISITES" URI::Escape, a browser available in the path, the browser must understand the \-remote switch (as far as I know, this is only available on \s-1UNIX\s0); coloring of registered modules is only available if Term::ANSIColor is installed. .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::FirstTime.3pm������������������������������������������������������������������������0000444�����������������00000066415�15253012307�0011342 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::FirstTime 3" .TH CPAN::FirstTime 3 "2022-04-03" "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" CPAN::FirstTime \- Utility for CPAN::Config file Initialization .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBCPAN::FirstTime::init()\fR .SH "DESCRIPTION" .IX Header "DESCRIPTION" The init routine asks a few questions and writes a CPAN/Config.pm or CPAN/MyConfig.pm file (depending on what it is currently using). .PP In the following all questions and explanations regarding config variables are collected. .IP "allow_installing_module_downgrades" 2 .IX Item "allow_installing_module_downgrades" The \s-1CPAN\s0 shell can watch the \f(CW\*(C`blib/\*(C'\fR directories that are built up before running \f(CW\*(C`make test\*(C'\fR to determine whether the current distribution will end up with modules being overwritten with decreasing module version numbers. It can then let the build of this distro fail when it discovers a downgrade. .Sp Do you want to allow installing distros with decreasing module versions compared to what you have installed (yes, no, ask/yes, ask/no)? .IP "allow_installing_outdated_dists" 2 .IX Item "allow_installing_outdated_dists" The \s-1CPAN\s0 shell can watch the \f(CW\*(C`blib/\*(C'\fR directories that are built up before running \f(CW\*(C`make test\*(C'\fR to determine whether the current distribution contains modules that are indexed with a distro with a higher distro-version number than the current one. It can then let the build of this distro fail when it would not represent the most up-to-date version of the distro. .Sp Note: choosing anything but 'yes' for this option will need CPAN::DistnameInfo being installed for taking effect. .Sp Do you want to allow installing distros that are not indexed as the highest distro-version for all contained modules (yes, no, ask/yes, ask/no)? .IP "auto_commit" 2 .IX Item "auto_commit" Normally \s-1CPAN\s0.pm keeps config variables in memory and changes need to be saved in a separate 'o conf commit' command to make them permanent between sessions. If you set the 'auto_commit' option to true, changes to a config variable are always automatically committed to disk. .Sp Always commit changes to config variables to disk? .IP "build_cache" 2 .IX Item "build_cache" \&\s-1CPAN\s0.pm can limit the size of the disk area for keeping the build directories with all the intermediate files. .Sp Cache size for build directory (in \s-1MB\s0)? .IP "build_dir" 2 .IX Item "build_dir" Directory where the build process takes place? .IP "build_dir_reuse" 2 .IX Item "build_dir_reuse" Until version 1.88 \s-1CPAN\s0.pm never trusted the contents of the build_dir directory between sessions. Since 1.88_58 \s-1CPAN\s0.pm has a YAML-based mechanism that makes it possible to share the contents of the build_dir/ directory between different sessions with the same version of perl. People who prefer to test things several days before installing will like this feature because it saves a lot of time. .Sp If you say yes to the following question, \s-1CPAN\s0 will try to store enough information about the build process so that it can pick up in future sessions at the same state of affairs as it left a previous session. .Sp Store and re-use state information about distributions between \&\s-1CPAN\s0.pm sessions? .IP "build_requires_install_policy" 2 .IX Item "build_requires_install_policy" When a module declares another one as a 'build_requires' prerequisite this means that the other module is only needed for building or testing the module but need not be installed permanently. In this case you may wish to install that other module nonetheless or just keep it in the 'build_dir' directory to have it available only temporarily. Installing saves time on future installations but makes the perl installation bigger. .Sp You can choose if you want to always install (yes), never install (no) or be always asked. In the latter case you can set the default answer for the question to yes (ask/yes) or no (ask/no). .Sp Policy on installing 'build_requires' modules (yes, no, ask/yes, ask/no)? .IP "cache_metadata" 2 .IX Item "cache_metadata" To considerably speed up the initial \s-1CPAN\s0 shell startup, it is possible to use Storable to create a cache of metadata. If Storable is not available, the normal index mechanism will be used. .Sp Note: this mechanism is not used when use_sqlite is on and SQLite is running. .Sp Cache metadata (yes/no)? .IP "check_sigs" 2 .IX Item "check_sigs" \&\s-1CPAN\s0 packages can be digitally signed by authors and thus verified with the security provided by strong cryptography. The exact mechanism is defined in the Module::Signature module. While this is generally considered a good thing, it is not always convenient to the end user to install modules that are signed incorrectly or where the key of the author is not available or where some prerequisite for Module::Signature has a bug and so on. .Sp With the check_sigs parameter you can turn signature checking on and off. The default is off for now because the whole tool chain for the functionality is not yet considered mature by some. The author of \&\s-1CPAN\s0.pm would recommend setting it to true most of the time and turning it off only if it turns out to be annoying. .Sp Note that if you do not have Module::Signature installed, no signature checks will be performed at all. .Sp Always try to check and verify signatures if a \s-1SIGNATURE\s0 file is in the package and Module::Signature is installed (yes/no)? .IP "cleanup_after_install" 2 .IX Item "cleanup_after_install" Users who install modules and do not intend to look back, can free occupied disk space quickly by letting \s-1CPAN\s0.pm cleanup each build directory immediately after a successful install. .Sp Remove build directory after a successful install? (yes/no)? .IP "colorize_output" 2 .IX Item "colorize_output" When you have Term::ANSIColor installed, you can turn on colorized output to have some visual differences between normal \s-1CPAN\s0.pm output, warnings, debugging output, and the output of the modules being installed. Set your favorite colors after some experimenting with the Term::ANSIColor module. .Sp Please note that on Windows platforms colorized output also requires the Win32::Console::ANSI module. .Sp Do you want to turn on colored output? .IP "colorize_print" 2 .IX Item "colorize_print" Color for normal output? .IP "colorize_warn" 2 .IX Item "colorize_warn" Color for warnings? .IP "colorize_debug" 2 .IX Item "colorize_debug" Color for debugging messages? .IP "commandnumber_in_prompt" 2 .IX Item "commandnumber_in_prompt" The prompt of the cpan shell can contain the current command number for easier tracking of the session or be a plain string. .Sp Do you want the command number in the prompt (yes/no)? .IP "connect_to_internet_ok" 2 .IX Item "connect_to_internet_ok" If you have never defined your own \f(CW\*(C`urllist\*(C'\fR in your configuration then \f(CW\*(C`CPAN.pm\*(C'\fR will be hesitant to use the built in default sites for downloading. It will ask you once per session if a connection to the internet is \s-1OK\s0 and only if you say yes, it will try to connect. But to avoid this question, you can choose your favorite download sites once and get away with it. Or, if you have no favorite download sites answer yes to the following question. .Sp If no urllist has been chosen yet, would you prefer \s-1CPAN\s0.pm to connect to the built-in default sites without asking? (yes/no)? .IP "ftp_passive" 2 .IX Item "ftp_passive" Shall we always set the \s-1FTP_PASSIVE\s0 environment variable when dealing with ftp download (yes/no)? .IP "ftpstats_period" 2 .IX Item "ftpstats_period" Statistics about downloads are truncated by size and period simultaneously. .Sp How many days shall we keep statistics about downloads? .IP "ftpstats_size" 2 .IX Item "ftpstats_size" Statistics about downloads are truncated by size and period simultaneously. Setting this to zero or negative disables download statistics. .Sp How many items shall we keep in the statistics about downloads? .IP "getcwd" 2 .IX Item "getcwd" \&\s-1CPAN\s0.pm changes the current working directory often and needs to determine its own current working directory. Per default it uses Cwd::cwd but if this doesn't work on your system for some reason, alternatives can be configured according to the following table: .Sp .Vb 5 \& cwd Cwd::cwd \& getcwd Cwd::getcwd \& fastcwd Cwd::fastcwd \& getdcwd Cwd::getdcwd \& backtickcwd external command cwd .Ve .Sp Preferred method for determining the current working directory? .IP "halt_on_failure" 2 .IX Item "halt_on_failure" Normally, \s-1CPAN\s0.pm continues processing the full list of targets and dependencies, even if one of them fails. However, you can specify that \s-1CPAN\s0 should halt after the first failure. (Note that optional recommended or suggested modules that fail will not cause a halt.) .Sp Do you want to halt on failure (yes/no)? .IP "histfile" 2 .IX Item "histfile" If you have one of the readline packages (Term::ReadLine::Perl, Term::ReadLine::Gnu, possibly others) installed, the interactive \s-1CPAN\s0 shell will have history support. The next two questions deal with the filename of the history file and with its size. If you do not want to set this variable, please hit \s-1SPACE ENTER\s0 to the following question. .Sp File to save your history? .IP "histsize" 2 .IX Item "histsize" Number of lines to save? .IP "inactivity_timeout" 2 .IX Item "inactivity_timeout" Sometimes you may wish to leave the processes run by \s-1CPAN\s0 alone without caring about them. Because the Makefile.PL or the Build.PL sometimes contains question you're expected to answer, you can set a timer that will kill a 'perl Makefile.PL' process after the specified time in seconds. .Sp If you set this value to 0, these processes will wait forever. This is the default and recommended setting. .Sp Timeout for inactivity during {Makefile,Build}.PL? .IP "index_expire" 2 .IX Item "index_expire" The \s-1CPAN\s0 indexes are usually rebuilt once or twice per hour, but the typical \s-1CPAN\s0 mirror mirrors only once or twice per day. Depending on the quality of your mirror and your desire to be on the bleeding edge, you may want to set the following value to more or less than one day (which is the default). It determines after how many days \s-1CPAN\s0.pm downloads new indexes. .Sp Let the index expire after how many days? .IP "inhibit_startup_message" 2 .IX Item "inhibit_startup_message" When the \s-1CPAN\s0 shell is started it normally displays a greeting message that contains the running version and the status of readline support. .Sp Do you want to turn this message off? .IP "keep_source_where" 2 .IX Item "keep_source_where" Unless you are accessing the \s-1CPAN\s0 on your filesystem via a file: \s-1URL, CPAN\s0.pm needs to keep the source files it downloads somewhere. Please supply a directory where the downloaded files are to be kept. .Sp Download target directory? .IP "load_module_verbosity" 2 .IX Item "load_module_verbosity" When \s-1CPAN\s0.pm loads a module it needs for some optional feature, it usually reports about module name and version. Choose 'v' to get this message, 'none' to suppress it. .Sp Verbosity level for loading modules (none or v)? .IP "makepl_arg" 2 .IX Item "makepl_arg" Every Makefile.PL is run by perl in a separate process. Likewise we run 'make' and 'make install' in separate processes. If you have any parameters (e.g. \s-1PREFIX, UNINST\s0 or the like) you want to pass to the calls, please specify them here. .Sp If you don't understand this question, just press \s-1ENTER.\s0 .Sp Typical frequently used settings: .Sp .Vb 1 \& PREFIX=~/perl # non\-root users (please see manual for more hints) .Ve .Sp Parameters for the 'perl Makefile.PL' command? .IP "make_arg" 2 .IX Item "make_arg" Parameters for the 'make' command? Typical frequently used setting: .Sp .Vb 1 \& \-j3 # dual processor system (on GNU make) .Ve .Sp Your choice: .IP "make_install_arg" 2 .IX Item "make_install_arg" Parameters for the 'make install' command? Typical frequently used setting: .Sp .Vb 2 \& UNINST=1 # to always uninstall potentially conflicting files \& # (but do NOT use with local::lib or INSTALL_BASE) .Ve .Sp Your choice: .IP "make_install_make_command" 2 .IX Item "make_install_make_command" Do you want to use a different make command for 'make install'? Cautious people will probably prefer: .Sp .Vb 5 \& su root \-c make \& or \& sudo make \& or \& /path1/to/sudo \-u admin_account /path2/to/make .Ve .Sp or some such. Your choice: .IP "mbuildpl_arg" 2 .IX Item "mbuildpl_arg" A Build.PL is run by perl in a separate process. Likewise we run \&'./Build' and './Build install' in separate processes. If you have any parameters you want to pass to the calls, please specify them here. .Sp Typical frequently used settings: .Sp .Vb 1 \& \-\-install_base /home/xxx # different installation directory .Ve .Sp Parameters for the 'perl Build.PL' command? .IP "mbuild_arg" 2 .IX Item "mbuild_arg" Parameters for the './Build' command? Setting might be: .Sp .Vb 1 \& \-\-extra_linker_flags \-L/usr/foo/lib # non\-standard library location .Ve .Sp Your choice: .IP "mbuild_install_arg" 2 .IX Item "mbuild_install_arg" Parameters for the './Build install' command? Typical frequently used setting: .Sp .Vb 2 \& \-\-uninst 1 # uninstall conflicting files \& # (but do NOT use with local::lib or INSTALL_BASE) .Ve .Sp Your choice: .IP "mbuild_install_build_command" 2 .IX Item "mbuild_install_build_command" Do you want to use a different command for './Build install'? Sudo users will probably prefer: .Sp .Vb 5 \& su root \-c ./Build \& or \& sudo ./Build \& or \& /path1/to/sudo \-u admin_account ./Build .Ve .Sp or some such. Your choice: .IP "pager" 2 .IX Item "pager" What is your favorite pager program? .IP "prefer_installer" 2 .IX Item "prefer_installer" When you have Module::Build installed and a module comes with both a Makefile.PL and a Build.PL, which shall have precedence? .Sp The main two standard installer modules are the old and well established ExtUtils::MakeMaker (for short: \s-1EUMM\s0) which uses the Makefile.PL. And the next generation installer Module::Build (\s-1MB\s0) which works with the Build.PL (and often comes with a Makefile.PL too). If a module comes only with one of the two we will use that one but if both are supplied then a decision must be made between \s-1EUMM\s0 and \&\s-1MB.\s0 See also http://rt.cpan.org/Ticket/Display.html?id=29235 for a discussion about the right default. .Sp Or, as a third option you can choose \s-1RAND\s0 which will make a random decision (something regular \s-1CPAN\s0 testers will enjoy). .Sp In case you can choose between running a Makefile.PL or a Build.PL, which installer would you prefer (\s-1EUMM\s0 or \s-1MB\s0 or \s-1RAND\s0)? .IP "prefs_dir" 2 .IX Item "prefs_dir" \&\s-1CPAN\s0.pm can store customized build environments based on regular expressions for distribution names. These are \s-1YAML\s0 files where the default options for \s-1CPAN\s0.pm and the environment can be overridden and dialog sequences can be stored that can later be executed by an Expect.pm object. The \s-1CPAN\s0.pm distribution comes with some prefab \s-1YAML\s0 files that cover sample distributions that can be used as blueprints to store your own prefs. Please check out the distroprefs/ directory of the \s-1CPAN\s0.pm distribution to get a quick start into the prefs system. .Sp Directory where to store default options/environment/dialogs for building modules that need some customization? .IP "prerequisites_policy" 2 .IX Item "prerequisites_policy" The \s-1CPAN\s0 module can detect when a module which you are trying to build depends on prerequisites. If this happens, it can build the prerequisites for you automatically ('follow'), ask you for confirmation ('ask'), or just ignore them ('ignore'). Choosing \&'follow' also sets \s-1PERL_AUTOINSTALL\s0 and \s-1PERL_EXTUTILS_AUTOINSTALL\s0 for \&\*(L"\-\-defaultdeps\*(R" if not already set. .Sp Please set your policy to one of the three values. .Sp Policy on building prerequisites (follow, ask or ignore)? .IP "pushy_https" 2 .IX Item "pushy_https" Boolean. Defaults to true. If this option is true, the cpan shell will use https://cpan.org/ to download stuff from the \s-1CPAN.\s0 It will fall back to http://cpan.org/ if it can't handle https for some reason (missing modules, missing programs). Whenever it falls back to the http protocol, it will issue a warning. .Sp If this option is true, the option \f(CW\*(C`urllist\*(C'\fR will be ignored. Consequently, if you want to work with local mirrors via your own configured list of URLs, you will have to choose no below. .Sp Do you want to turn the pushy_https behaviour on? .IP "randomize_urllist" 2 .IX Item "randomize_urllist" \&\s-1CPAN\s0.pm can introduce some randomness when using hosts for download that are configured in the urllist parameter. Enter a numeric value between 0 and 1 to indicate how often you want to let \s-1CPAN\s0.pm try a random host from the urllist. A value of one specifies to always use a random host as the first try. A value of zero means no randomness at all. Anything in between specifies how often, on average, a random host should be tried first. .Sp Randomize parameter .IP "recommends_policy" 2 .IX Item "recommends_policy" (Experimental feature!) Some \s-1CPAN\s0 modules recommend additional, optional dependencies. These should generally be installed except in resource constrained environments. When this policy is true, recommended modules will be included with required modules. .Sp Include recommended modules? .IP "scan_cache" 2 .IX Item "scan_cache" By default, each time the \s-1CPAN\s0 module is started, cache scanning is performed to keep the cache size in sync ('atstart'). Alternatively, scanning and cleanup can happen when \s-1CPAN\s0 exits ('atexit'). To prevent any cache cleanup, answer 'never'. .Sp Perform cache scanning ('atstart', 'atexit' or 'never')? .IP "shell" 2 .IX Item "shell" What is your favorite shell? .IP "show_unparsable_versions" 2 .IX Item "show_unparsable_versions" During the 'r' command \s-1CPAN\s0.pm finds modules without version number. When the command finishes, it prints a report about this. If you want this report to be very verbose, say yes to the following variable. .Sp Show all individual modules that have no \f(CW$VERSION\fR? .IP "show_upload_date" 2 .IX Item "show_upload_date" The 'd' and the 'm' command normally only show you information they have in their in-memory database and thus will never connect to the internet. If you set the 'show_upload_date' variable to true, 'm' and \&'d' will additionally show you the upload date of the module or distribution. Per default this feature is off because it may require a net connection to get at the upload date. .Sp Always try to show upload date with 'd' and 'm' command (yes/no)? .IP "show_zero_versions" 2 .IX Item "show_zero_versions" During the 'r' command \s-1CPAN\s0.pm finds modules with a version number of zero. When the command finishes, it prints a report about this. If you want this report to be very verbose, say yes to the following variable. .Sp Show all individual modules that have a \f(CW$VERSION\fR of zero? .IP "suggests_policy" 2 .IX Item "suggests_policy" (Experimental feature!) Some \s-1CPAN\s0 modules suggest additional, optional dependencies. These 'suggest' dependencies provide enhanced operation. When this policy is true, suggested modules will be included with required modules. .Sp Include suggested modules? .IP "tar_verbosity" 2 .IX Item "tar_verbosity" When \s-1CPAN\s0.pm uses the tar command, which switch for the verbosity shall be used? Choose 'none' for quiet operation, 'v' for file name listing, 'vv' for full listing. .Sp Tar command verbosity level (none or v or vv)? .IP "term_is_latin" 2 .IX Item "term_is_latin" The next option deals with the charset (a.k.a. character set) your terminal supports. In general, \s-1CPAN\s0 is English speaking territory, so the charset does not matter much but some \s-1CPAN\s0 have names that are outside the \s-1ASCII\s0 range. If your terminal supports \s-1UTF\-8,\s0 you should say no to the next question. If it expects \s-1ISO\-8859\-1\s0 (also known as \&\s-1LATIN1\s0) then you should say yes. If it supports neither, your answer does not matter because you will not be able to read the names of some authors anyway. If you answer no, names will be output in \s-1UTF\-8.\s0 .Sp Your terminal expects \s-1ISO\-8859\-1\s0 (yes/no)? .IP "term_ornaments" 2 .IX Item "term_ornaments" When using Term::ReadLine, you can turn ornaments on so that your input stands out against the output from \s-1CPAN\s0.pm. .Sp Do you want to turn ornaments on? .IP "test_report" 2 .IX Item "test_report" The goal of the \s-1CPAN\s0 Testers project (http://testers.cpan.org/) is to test as many \s-1CPAN\s0 packages as possible on as many platforms as possible. This provides valuable feedback to module authors and potential users to identify bugs or platform compatibility issues and improves the overall quality and value of \s-1CPAN.\s0 .Sp One way you can contribute is to send test results for each module that you install. If you install the CPAN::Reporter module, you have the option to automatically generate and deliver test reports to \s-1CPAN\s0 Testers whenever you run tests on a \s-1CPAN\s0 package. .Sp See the CPAN::Reporter documentation for additional details and configuration settings. If your firewall blocks outgoing traffic, you may need to configure CPAN::Reporter before sending reports. .Sp Generate test reports if CPAN::Reporter is installed (yes/no)? .IP "perl5lib_verbosity" 2 .IX Item "perl5lib_verbosity" When \s-1CPAN\s0.pm extends \f(CW@INC\fR via \s-1PERL5LIB,\s0 it prints a list of directories added (or a summary of how many directories are added). Choose 'v' to get this message, 'none' to suppress it. .Sp Verbosity level for \s-1PERL5LIB\s0 changes (none or v)? .IP "prefer_external_tar" 2 .IX Item "prefer_external_tar" Per default all untar operations are done with the perl module Archive::Tar; by setting this variable to true the external tar command is used if available; on Unix this is usually preferred because they have a reliable and fast gnutar implementation. .Sp Use the external tar program instead of Archive::Tar? .IP "trust_test_report_history" 2 .IX Item "trust_test_report_history" When a distribution has already been tested by CPAN::Reporter on this machine, \s-1CPAN\s0 can skip the test phase and just rely on the test report history instead. .Sp Note that this will not apply to distributions that failed tests because of missing dependencies. Also, tests can be run regardless of the history using \*(L"force\*(R". .Sp Do you want to rely on the test report history (yes/no)? .IP "urllist_ping_external" 2 .IX Item "urllist_ping_external" When automatic selection of the nearest cpan mirrors is performed, turn on the use of the external ping via Net::Ping::External. This is recommended in the case the local network has a transparent proxy. .Sp Do you want to use the external ping command when autoselecting mirrors? .IP "urllist_ping_verbose" 2 .IX Item "urllist_ping_verbose" When automatic selection of the nearest cpan mirrors is performed, this option can be used to turn on verbosity during the selection process. .Sp Do you want to see verbosity turned on when autoselecting mirrors? .IP "use_prompt_default" 2 .IX Item "use_prompt_default" When this is true, \s-1CPAN\s0 will set \s-1PERL_MM_USE_DEFAULT\s0 to a true value. This causes ExtUtils::MakeMaker (and compatible) prompts to use default values instead of stopping to prompt you to answer questions. It also sets \s-1NONINTERACTIVE_TESTING\s0 to a true value to signal more generally that distributions should not try to interact with you. .Sp Do you want to use prompt defaults (yes/no)? .IP "use_sqlite" 2 .IX Item "use_sqlite" CPAN::SQLite is a layer between the index files that are downloaded from the \s-1CPAN\s0 and \s-1CPAN\s0.pm that speeds up metadata queries and reduces memory consumption of \s-1CPAN\s0.pm considerably. .Sp Use CPAN::SQLite if available? (yes/no)? .IP "version_timeout" 2 .IX Item "version_timeout" This timeout prevents \s-1CPAN\s0 from hanging when trying to parse a pathologically coded \f(CW$VERSION\fR from a module. .Sp The default is 15 seconds. If you set this value to 0, no timeout will occur, but this is not recommended. .Sp Timeout for parsing module versions? .IP "yaml_load_code" 2 .IX Item "yaml_load_code" Both \s-1YAML\s0.pm and YAML::Syck are capable of deserialising code. As this requires a string eval, which might be a security risk, you can use this option to enable or disable the deserialisation of code via CPAN::DeferredCode. (Note: This does not work under perl 5.6) .Sp Do you want to enable code deserialisation (yes/no)? .IP "yaml_module" 2 .IX Item "yaml_module" At the time of this writing (2009\-03) there are three \s-1YAML\s0 implementations working: \s-1YAML,\s0 YAML::Syck, and \s-1YAML::XS.\s0 The latter two are faster but need a C compiler installed on your system. There may be more alternative \s-1YAML\s0 conforming modules. When I tried two other players, YAML::Tiny and YAML::Perl, they seemed not powerful enough to work with \s-1CPAN\s0.pm. This may have changed in the meantime. .Sp Which \s-1YAML\s0 implementation would you prefer? .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/Types::Serialiser::Error.3pm���������������������������������������������������������������0000444�����������������00000005215�15253012307�0013306 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 <schmorp@schmorp.de> \& http://home.schmorp.de/ .Ve �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Mirrors.3pm��������������������������������������������������������������������������0000444�����������������00000021312�15253012307�0011054 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Mirrors 3" .TH CPAN::Mirrors 3 "2020-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" CPAN::Mirrors \- Get CPAN mirror information and select a fast one .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use CPAN::Mirrors; \& \& my $mirrors = CPAN::Mirrors\->new( $mirrored_by_file ); \& \& my $seen = {}; \& \& my $best_continent = $mirrors\->find_best_continents( { seen => $seen } ); \& my @mirrors = $mirrors\->get_mirrors_by_continents( $best_continent ); \& \& my $callback = sub { \& my( $m ) = @_; \& printf "%s = %s\en", $m\->hostname, $m\->rtt \& }; \& $mirrors\->get_mirrors_timings( \e@mirrors, $seen, $callback, %args ); \& \& @mirrors = sort { $a\->rtt <=> $b\->rtt } @mirrors; \& \& print "Best mirrors are ", map( { $_\->rtt } @mirrors[0..3] ), "\en"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" .IP "new( \s-1LOCAL_FILE_NAME\s0 )" 4 .IX Item "new( LOCAL_FILE_NAME )" Create a new CPAN::Mirrors object from \s-1LOCAL_FILE_NAME.\s0 This file should look like that in http://www.cpan.org/MIRRORED.BY . .IP "\fBcontinents()\fR" 4 .IX Item "continents()" Return a list of continents based on those defined in \fI\s-1MIRRORED.BY\s0\fR. .IP "countries( [\s-1CONTINENTS\s0] )" 4 .IX Item "countries( [CONTINENTS] )" Return a list of countries based on those defined in \fI\s-1MIRRORED.BY\s0\fR. It only returns countries for the continents you specify (as defined in \f(CW\*(C`continents\*(C'\fR). If you don't specify any continents, it returns all of the countries listed in \fI\s-1MIRRORED.BY\s0\fR. .IP "mirrors( [\s-1COUNTRIES\s0] )" 4 .IX Item "mirrors( [COUNTRIES] )" Return a list of mirrors based on those defined in \fI\s-1MIRRORED.BY\s0\fR. It only returns mirrors for the countries you specify (as defined in \f(CW\*(C`countries\*(C'\fR). If you don't specify any countries, it returns all of the mirrors listed in \fI\s-1MIRRORED.BY\s0\fR. .IP "get_mirrors_by_countries( [\s-1COUNTRIES\s0] )" 4 .IX Item "get_mirrors_by_countries( [COUNTRIES] )" A more sensible synonym for mirrors. .IP "get_mirrors_by_continents( [\s-1CONTINENTS\s0] )" 4 .IX Item "get_mirrors_by_continents( [CONTINENTS] )" Return a list of mirrors for all of continents you specify. If you don't specify any continents, it returns all of the mirrors. .Sp You can specify a single continent or an array reference of continents. .IP "get_countries_by_continents( [\s-1CONTINENTS\s0] )" 4 .IX Item "get_countries_by_continents( [CONTINENTS] )" A more sensible synonym for countries. .IP "default_mirror" 4 .IX Item "default_mirror" Returns the default mirror, http://www.cpan.org/ . This mirror uses dynamic \s-1DNS\s0 to give a close mirror. .IP "best_mirrors" 4 .IX Item "best_mirrors" \&\f(CW\*(C`best_mirrors\*(C'\fR checks for the best mirrors based on the list of continents you pass, or, without that, all continents, as defined by \f(CW\*(C`CPAN::Mirrored::By\*(C'\fR. It pings each mirror, up to the value of \&\f(CW\*(C`how_many\*(C'\fR. In list context, it returns up to \f(CW\*(C`how_many\*(C'\fR mirrors. In scalar context, it returns the single best mirror. .Sp Arguments .Sp .Vb 5 \& how_many \- the number of mirrors to return. Default: 1 \& callback \- a callback for find_best_continents \& verbose \- true or false on all the whining and moaning. Default: false \& continents \- an array ref of the continents to check \& external_ping \- if true, use external ping via Net::Ping::External. Default: false .Ve .Sp If you don't specify the continents, \f(CW\*(C`best_mirrors\*(C'\fR calls \&\f(CW\*(C`find_best_continents\*(C'\fR to get the list of continents to check. .Sp If you don't have Net::Ping v2.13 or later, needed for timings, this returns the default mirror. .Sp \&\f(CW\*(C`external_ping\*(C'\fR should be set and then \f(CW\*(C`Net::Ping::External\*(C'\fR needs to be installed, if the local network has a transparent proxy. .IP "get_n_random_mirrors_by_continents( N, [\s-1CONTINENTS\s0] )" 4 .IX Item "get_n_random_mirrors_by_continents( N, [CONTINENTS] )" Returns up to N random mirrors for the specified continents. Specify the continents as an array reference. .ie n .IP "get_mirrors_timings( \s-1MIRROR_LIST, SEEN, CALLBACK,\s0 %ARGS );" 4 .el .IP "get_mirrors_timings( \s-1MIRROR_LIST, SEEN, CALLBACK,\s0 \f(CW%ARGS\fR );" 4 .IX Item "get_mirrors_timings( MIRROR_LIST, SEEN, CALLBACK, %ARGS );" Pings the listed mirrors and returns a list of mirrors sorted in ascending ping times. .Sp \&\f(CW\*(C`MIRROR_LIST\*(C'\fR is an anonymous array of \f(CW\*(C`CPAN::Mirrored::By\*(C'\fR objects to ping. .Sp The optional argument \f(CW\*(C`SEEN\*(C'\fR is a hash reference used to track the mirrors you've already pinged. .Sp The optional argument \f(CW\*(C`CALLBACK\*(C'\fR is a subroutine reference to call after each ping. It gets the \f(CW\*(C`CPAN::Mirrored::By\*(C'\fR object after each ping. .IP "find_best_continents( \s-1HASH_REF\s0 );" 4 .IX Item "find_best_continents( HASH_REF );" \&\f(CW\*(C`find_best_continents\*(C'\fR goes through each continent and pings \f(CW\*(C`N\*(C'\fR random mirrors on that continent. It then orders the continents by ascending median ping time. In list context, it returns the ordered list of continent. In scalar context, it returns the same list as an anonymous array. .Sp Arguments: .Sp .Vb 6 \& n \- the number of hosts to ping for each continent. Default: 3 \& seen \- a hashref of cached hostname ping times \& verbose \- true or false for noisy or quiet. Default: false \& callback \- a subroutine to run after each ping. \& ping_cache_limit \- how long, in seconds, to reuse previous ping times. \& Default: 1 day .Ve .Sp The \f(CW\*(C`seen\*(C'\fR hash has hostnames as keys and anonymous arrays as values. The anonymous array is a triplet of a \f(CW\*(C`CPAN::Mirrored::By\*(C'\fR object, a ping time, and the epoch time for the measurement. .Sp The callback subroutine gets the \f(CW\*(C`CPAN::Mirrored::By\*(C'\fR object, the ping time, and measurement time (the same things in the \f(CW\*(C`seen\*(C'\fR hashref) as arguments. \f(CW\*(C`find_best_continents\*(C'\fR doesn't care what the callback does and ignores the return value. .Sp With a low value for \f(CW\*(C`N\*(C'\fR, a single mirror might skew the results enough to choose a worse continent. If you have that problem, try a larger value. .SH "AUTHOR" .IX Header "AUTHOR" Andreas Koenig \f(CW\*(C`<andk@cpan.org>\*(C'\fR, David Golden \f(CW\*(C`<dagolden@cpan.org>\*(C'\fR, brian d foy \f(CW\*(C`<bdfoy@cpan.org>\*(C'\fR .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP See <http://www.perl.com/perl/misc/Artistic.html> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Kwalify.3pm��������������������������������������������������������������������������0000444�����������������00000006724�15253012307�0011037 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Kwalify 3" .TH CPAN::Kwalify 3 "2012-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" CPAN::Kwalify \- Interface between CPAN.pm and Kwalify.pm .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use CPAN::Kwalify; \& validate($schema_name, $data, $file, $doc); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" .ie n .IP "_validate($schema_name, $data, $file, $doc)" 4 .el .IP "_validate($schema_name, \f(CW$data\fR, \f(CW$file\fR, \f(CW$doc\fR)" 4 .IX Item "_validate($schema_name, $data, $file, $doc)" \&\f(CW$schema_name\fR is the name of a supported schema. Currently only \&\f(CW\*(C`distroprefs\*(C'\fR is supported. \f(CW$data\fR is the data to be validated. \f(CW$file\fR is the absolute path to the file the data are coming from. \f(CW$doc\fR is the index of the document within \f(CW$doc\fR that is to be validated. The last two arguments are only there for better error reporting. .Sp Relies on being called from within \s-1CPAN\s0.pm. .Sp Dies if something fails. Does not return anything useful. .IP "yaml($schema_name)" 4 .IX Item "yaml($schema_name)" Returns the \s-1YAML\s0 text of that schema. Dies if something fails. .SH "AUTHOR" .IX Header "AUTHOR" Andreas Koenig \f(CW\*(C`<andk@cpan.org>\*(C'\fR .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP See <http://www.perl.com/perl/misc/Artistic.html> ��������������������������������������������man/man3/CPAN::Nox.3pm������������������������������������������������������������������������������0000444�����������������00000005441�15253012307�0010170 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Nox 3" .TH CPAN::Nox 3 "2016-08-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" CPAN::Nox \- Wrapper around CPAN.pm without using any XS module .SH "SYNOPSIS" .IX Header "SYNOPSIS" Interactive mode: .PP .Vb 1 \& perl \-MCPAN::Nox \-e shell; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This package has the same functionality as \s-1CPAN\s0.pm, but tries to prevent the usage of compiled extensions during its own execution. Its primary purpose is a rescue in case you upgraded perl and broke binary compatibility somehow. .SH "LICENSE" .IX Header "LICENSE" 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-1CPAN\s0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN.3pm�����������������������������������������������������������������������������������0000444�����������������00000340457�15253012307�0007330 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN 3" .TH CPAN 3 "2023-05-10" "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" CPAN \- query, download and build perl modules from CPAN sites .SH "SYNOPSIS" .IX Header "SYNOPSIS" Interactive mode: .PP .Vb 1 \& perl \-MCPAN \-e shell .Ve .PP \&\-\-or\*(-- .PP .Vb 1 \& cpan .Ve .PP Basic commands: .PP .Vb 1 \& # Modules: \& \& cpan> install Acme::Meta # in the shell \& \& CPAN::Shell\->install("Acme::Meta"); # in perl \& \& # Distributions: \& \& cpan> install NWCLARK/Acme\-Meta\-0.02.tar.gz # in the shell \& \& CPAN::Shell\-> \& install("NWCLARK/Acme\-Meta\-0.02.tar.gz"); # in perl \& \& # module objects: \& \& $mo = CPAN::Shell\->expandany($mod); \& $mo = CPAN::Shell\->expand("Module",$mod); # same thing \& \& # distribution objects: \& \& $do = CPAN::Shell\->expand("Module",$mod)\->distribution; \& $do = CPAN::Shell\->expandany($distro); # same thing \& $do = CPAN::Shell\->expand("Distribution", \& $distro); # same thing .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The \s-1CPAN\s0 module automates or at least simplifies the make and install of perl modules and extensions. It includes some primitive searching capabilities and knows how to use \s-1LWP,\s0 HTTP::Tiny, Net::FTP and certain external download clients to fetch distributions from the net. .PP These are fetched from one or more mirrored \s-1CPAN\s0 (Comprehensive Perl Archive Network) sites and unpacked in a dedicated directory. .PP The \s-1CPAN\s0 module also supports named and versioned \&\fIbundles\fR of modules. Bundles simplify handling of sets of related modules. See Bundles below. .PP The package contains a session manager and a cache manager. The session manager keeps track of what has been fetched, built, and installed in the current session. The cache manager keeps track of the disk space occupied by the make processes and deletes excess space using a simple \s-1FIFO\s0 mechanism. .PP All methods provided are accessible in a programmer style and in an interactive shell style. .ie n .SS "CPAN::shell([$prompt, $command]) Starting Interactive Mode" .el .SS "CPAN::shell([$prompt, \f(CW$command\fP]) Starting Interactive Mode" .IX Subsection "CPAN::shell([$prompt, $command]) Starting Interactive Mode" Enter interactive mode by running .PP .Vb 1 \& perl \-MCPAN \-e shell .Ve .PP or .PP .Vb 1 \& cpan .Ve .PP which puts you into a readline interface. If \f(CW\*(C`Term::ReadKey\*(C'\fR and either of \f(CW\*(C`Term::ReadLine::Perl\*(C'\fR or \f(CW\*(C`Term::ReadLine::Gnu\*(C'\fR are installed, history and command completion are supported. .PP Once at the command line, type \f(CW\*(C`h\*(C'\fR for one-page help screen; the rest should be self-explanatory. .PP The function call \f(CW\*(C`shell\*(C'\fR takes two optional arguments: one the prompt, the second the default initial command line (the latter only works if a real ReadLine interface module is installed). .PP The most common uses of the interactive modes are .IP "Searching for authors, bundles, distribution files and modules" 2 .IX Item "Searching for authors, bundles, distribution files and modules" There are corresponding one-letter commands \f(CW\*(C`a\*(C'\fR, \f(CW\*(C`b\*(C'\fR, \f(CW\*(C`d\*(C'\fR, and \f(CW\*(C`m\*(C'\fR for each of the four categories and another, \f(CW\*(C`i\*(C'\fR for any of the mentioned four. Each of the four entities is implemented as a class with slightly differing methods for displaying an object. .Sp Arguments to these commands are either strings exactly matching the identification string of an object, or regular expressions matched case-insensitively against various attributes of the objects. The parser only recognizes a regular expression when you enclose it with slashes. .Sp The principle is that the number of objects found influences how an item is displayed. If the search finds one item, the result is displayed with the rather verbose method \f(CW\*(C`as_string\*(C'\fR, but if more than one is found, each object is displayed with the terse method \&\f(CW\*(C`as_glimpse\*(C'\fR. .Sp Examples: .Sp .Vb 10 \& cpan> m Acme::MetaSyntactic \& Module id = Acme::MetaSyntactic \& CPAN_USERID BOOK (Philippe Bruhat (BooK) <[...]>) \& CPAN_VERSION 0.99 \& CPAN_FILE B/BO/BOOK/Acme\-MetaSyntactic\-0.99.tar.gz \& UPLOAD_DATE 2006\-11\-06 \& MANPAGE Acme::MetaSyntactic \- Themed metasyntactic variables names \& INST_FILE /usr/local/lib/perl/5.10.0/Acme/MetaSyntactic.pm \& INST_VERSION 0.99 \& cpan> a BOOK \& Author id = BOOK \& EMAIL [...] \& FULLNAME Philippe Bruhat (BooK) \& cpan> d BOOK/Acme\-MetaSyntactic\-0.99.tar.gz \& Distribution id = B/BO/BOOK/Acme\-MetaSyntactic\-0.99.tar.gz \& CPAN_USERID BOOK (Philippe Bruhat (BooK) <[...]>) \& CONTAINSMODS Acme::MetaSyntactic Acme::MetaSyntactic::Alias [...] \& UPLOAD_DATE 2006\-11\-06 \& cpan> m /lorem/ \& Module = Acme::MetaSyntactic::loremipsum (BOOK/Acme\-MetaSyntactic\-0.99.tar.gz) \& Module Text::Lorem (ADEOLA/Text\-Lorem\-0.3.tar.gz) \& Module Text::Lorem::More (RKRIMEN/Text\-Lorem\-More\-0.12.tar.gz) \& Module Text::Lorem::More::Source (RKRIMEN/Text\-Lorem\-More\-0.12.tar.gz) \& cpan> i /berlin/ \& Distribution BEATNIK/Filter\-NumberLines\-0.02.tar.gz \& Module = DateTime::TimeZone::Europe::Berlin (DROLSKY/DateTime\-TimeZone\-0.7904.tar.gz) \& Module Filter::NumberLines (BEATNIK/Filter\-NumberLines\-0.02.tar.gz) \& Author [...] .Ve .Sp The examples illustrate several aspects: the first three queries target modules, authors, or distros directly and yield exactly one result. The last two use regular expressions and yield several results. The last one targets all of bundles, modules, authors, and distros simultaneously. When more than one result is available, they are printed in one-line format. .ie n .IP """get"", ""make"", ""test"", ""install"", ""clean"" modules or distributions" 2 .el .IP "\f(CWget\fR, \f(CWmake\fR, \f(CWtest\fR, \f(CWinstall\fR, \f(CWclean\fR modules or distributions" 2 .IX Item "get, make, test, install, clean modules or distributions" These commands take any number of arguments and investigate what is necessary to perform the action. Argument processing is as follows: .Sp .Vb 5 \& known module name in format Foo/Bar.pm module \& other embedded slash distribution \& \- with trailing slash dot directory \& enclosing slashes regexp \& known module name in format Foo::Bar module .Ve .Sp If the argument is a distribution file name (recognized by embedded slashes), it is processed. If it is a module, \s-1CPAN\s0 determines the distribution file in which this module is included and processes that, following any dependencies named in the module's \s-1META\s0.yml or Makefile.PL (this behavior is controlled by the configuration parameter \f(CW\*(C`prerequisites_policy\*(C'\fR). If an argument is enclosed in slashes it is treated as a regular expression: it is expanded and if the result is a single object (distribution, bundle or module), this object is processed. .Sp Example: .Sp .Vb 3 \& install Dummy::Perl # installs the module \& install AUXXX/Dummy\-Perl\-3.14.tar.gz # installs that distribution \& install /Dummy\-Perl\-3.14/ # same if the regexp is unambiguous .Ve .Sp \&\f(CW\*(C`get\*(C'\fR downloads a distribution file and untars or unzips it, \f(CW\*(C`make\*(C'\fR builds it, \f(CW\*(C`test\*(C'\fR runs the test suite, and \f(CW\*(C`install\*(C'\fR installs it. .Sp Any \f(CW\*(C`make\*(C'\fR or \f(CW\*(C`test\*(C'\fR is run unconditionally. An .Sp .Vb 1 \& install <distribution_file> .Ve .Sp is also run unconditionally. But for .Sp .Vb 1 \& install <module> .Ve .Sp \&\s-1CPAN\s0 checks whether an install is needed and prints \&\fImodule up to date\fR if the distribution file containing the module doesn't need updating. .Sp \&\s-1CPAN\s0 also keeps track of what it has done within the current session and doesn't try to build a package a second time regardless of whether it succeeded or not. It does not repeat a test run if the test has been run successfully before. Same for install runs. .Sp The \f(CW\*(C`force\*(C'\fR pragma may precede another command (currently: \f(CW\*(C`get\*(C'\fR, \&\f(CW\*(C`make\*(C'\fR, \f(CW\*(C`test\*(C'\fR, or \f(CW\*(C`install\*(C'\fR) to execute the command from scratch and attempt to continue past certain errors. See the section below on the \f(CW\*(C`force\*(C'\fR and the \f(CW\*(C`fforce\*(C'\fR pragma. .Sp The \f(CW\*(C`notest\*(C'\fR pragma skips the test part in the build process. .Sp Example: .Sp .Vb 1 \& cpan> notest install Tk .Ve .Sp A \f(CW\*(C`clean\*(C'\fR command results in a .Sp .Vb 1 \& make clean .Ve .Sp being executed within the distribution file's working directory. .ie n .IP """readme"", ""perldoc"", ""look"" module or distribution" 2 .el .IP "\f(CWreadme\fR, \f(CWperldoc\fR, \f(CWlook\fR module or distribution" 2 .IX Item "readme, perldoc, look module or distribution" \&\f(CW\*(C`readme\*(C'\fR displays the \s-1README\s0 file of the associated distribution. \&\f(CW\*(C`Look\*(C'\fR gets and untars (if not yet done) the distribution file, changes to the appropriate directory and opens a subshell process in that directory. \f(CW\*(C`perldoc\*(C'\fR displays the module's pod documentation in html or plain text format. .ie n .IP """ls"" author" 2 .el .IP "\f(CWls\fR author" 2 .IX Item "ls author" .PD 0 .ie n .IP """ls"" globbing_expression" 2 .el .IP "\f(CWls\fR globbing_expression" 2 .IX Item "ls globbing_expression" .PD The first form lists all distribution files in and below an author's \&\s-1CPAN\s0 directory as stored in the \s-1CHECKSUMS\s0 files distributed on \&\s-1CPAN.\s0 The listing recurses into subdirectories. .Sp The second form limits or expands the output with shell globbing as in the following examples: .Sp .Vb 3 \& ls JV/make* \& ls GSAR/*make* \& ls */*make* .Ve .Sp The last example is very slow and outputs extra progress indicators that break the alignment of the result. .Sp Note that globbing only lists directories explicitly asked for, for example FOO/* will not list FOO/bar/Acme\-Sthg\-n.nn.tar.gz. This may be regarded as a bug that may be changed in some future version. .ie n .IP """failed""" 2 .el .IP "\f(CWfailed\fR" 2 .IX Item "failed" The \f(CW\*(C`failed\*(C'\fR command reports all distributions that failed on one of \&\f(CW\*(C`make\*(C'\fR, \f(CW\*(C`test\*(C'\fR or \f(CW\*(C`install\*(C'\fR for some reason in the currently running shell session. .IP "Persistence between sessions" 2 .IX Item "Persistence between sessions" If the \f(CW\*(C`YAML\*(C'\fR or the \f(CW\*(C`YAML::Syck\*(C'\fR module is installed a record of the internal state of all modules is written to disk after each step. The files contain a signature of the currently running perl version for later perusal. .Sp If the configurations variable \f(CW\*(C`build_dir_reuse\*(C'\fR is set to a true value, then \s-1CPAN\s0.pm reads the collected \s-1YAML\s0 files. If the stored signature matches the currently running perl, the stored state is loaded into memory such that persistence between sessions is effectively established. .ie n .IP "The ""force"" and the ""fforce"" pragma" 2 .el .IP "The \f(CWforce\fR and the \f(CWfforce\fR pragma" 2 .IX Item "The force and the fforce pragma" To speed things up in complex installation scenarios, \s-1CPAN\s0.pm keeps track of what it has already done and refuses to do some things a second time. A \f(CW\*(C`get\*(C'\fR, a \f(CW\*(C`make\*(C'\fR, and an \f(CW\*(C`install\*(C'\fR are not repeated. A \f(CW\*(C`test\*(C'\fR is repeated only if the previous test was unsuccessful. The diagnostic message when \s-1CPAN\s0.pm refuses to do something a second time is one of \fIHas already been \fR\f(CW\*(C`unwrapped|made|tested successfully\*(C'\fR or something similar. Another situation where \s-1CPAN\s0 refuses to act is an \&\f(CW\*(C`install\*(C'\fR if the corresponding \f(CW\*(C`test\*(C'\fR was not successful. .Sp In all these cases, the user can override this stubborn behaviour by prepending the command with the word force, for example: .Sp .Vb 4 \& cpan> force get Foo \& cpan> force make AUTHOR/Bar\-3.14.tar.gz \& cpan> force test Baz \& cpan> force install Acme::Meta .Ve .Sp Each \fIforced\fR command is executed with the corresponding part of its memory erased. .Sp The \f(CW\*(C`fforce\*(C'\fR pragma is a variant that emulates a \f(CW\*(C`force get\*(C'\fR which erases the entire memory followed by the action specified, effectively restarting the whole get/make/test/install procedure from scratch. .IP "Lockfile" 2 .IX Item "Lockfile" Interactive sessions maintain a lockfile, by default \f(CW\*(C`~/.cpan/.lock\*(C'\fR. Batch jobs can run without a lockfile and not disturb each other. .Sp The shell offers to run in \fIdowngraded mode\fR when another process is holding the lockfile. This is an experimental feature that is not yet tested very well. This second shell then does not write the history file, does not use the metadata file, and has a different prompt. .IP "Signals" 2 .IX Item "Signals" \&\s-1CPAN\s0.pm installs signal handlers for \s-1SIGINT\s0 and \s-1SIGTERM.\s0 While you are in the cpan-shell, it is intended that you can press \f(CW\*(C`^C\*(C'\fR anytime and return to the cpan-shell prompt. A \s-1SIGTERM\s0 will cause the cpan-shell to clean up and leave the shell loop. You can emulate the effect of a \&\s-1SIGTERM\s0 by sending two consecutive SIGINTs, which usually means by pressing \f(CW\*(C`^C\*(C'\fR twice. .Sp \&\s-1CPAN\s0.pm ignores \s-1SIGPIPE.\s0 If the user sets \f(CW\*(C`inactivity_timeout\*(C'\fR, a \&\s-1SIGALRM\s0 is used during the run of the \f(CW\*(C`perl Makefile.PL\*(C'\fR or \f(CW\*(C`perl Build.PL\*(C'\fR subprocess. A \s-1SIGALRM\s0 is also used during module version parsing, and is controlled by \f(CW\*(C`version_timeout\*(C'\fR. .SS "CPAN::Shell" .IX Subsection "CPAN::Shell" The commands available in the shell interface are methods in the package CPAN::Shell. If you enter the shell command, your input is split by the \fBText::ParseWords::shellwords()\fR routine, which acts like most shells do. The first word is interpreted as the method to be invoked, and the rest of the words are treated as the method's arguments. Continuation lines are supported by ending a line with a literal backslash. .SS "autobundle" .IX Subsection "autobundle" \&\f(CW\*(C`autobundle\*(C'\fR writes a bundle file into the \&\f(CW\*(C`$CPAN::Config\->{cpan_home}/Bundle\*(C'\fR directory. The file contains a list of all modules that are both available from \s-1CPAN\s0 and currently installed within \f(CW@INC\fR. Duplicates of each distribution are suppressed. The name of the bundle file is based on the current date and a counter, e.g. \fIBundle/Snapshot_2012_05_21_00.pm\fR. This is installed again by running \f(CW\*(C`cpan Bundle::Snapshot_2012_05_21_00\*(C'\fR, or installing \&\f(CW\*(C`Bundle::Snapshot_2012_05_21_00\*(C'\fR from the \s-1CPAN\s0 shell. .PP Return value: path to the written file. .SS "hosts" .IX Subsection "hosts" Note: this feature is still in alpha state and may change in future versions of \s-1CPAN\s0.pm .PP This commands provides a statistical overview over recent download activities. The data for this is collected in the \s-1YAML\s0 file \&\f(CW\*(C`FTPstats.yml\*(C'\fR in your \f(CW\*(C`cpan_home\*(C'\fR directory. If no \s-1YAML\s0 module is configured or \s-1YAML\s0 not installed, no stats are provided. .IP "install_tested" 4 .IX Item "install_tested" Install all distributions that have been tested successfully but have not yet been installed. See also \f(CW\*(C`is_tested\*(C'\fR. .IP "is_tested" 4 .IX Item "is_tested" List all build directories of distributions that have been tested successfully but have not yet been installed. See also \&\f(CW\*(C`install_tested\*(C'\fR. .SS "mkmyconfig" .IX Subsection "mkmyconfig" \&\fBmkmyconfig()\fR writes your own CPAN::MyConfig file into your \f(CW\*(C`~/.cpan/\*(C'\fR directory so that you can save your own preferences instead of the system-wide ones. .SS "r [Module|/Regexp/]..." .IX Subsection "r [Module|/Regexp/]..." scans current perl installation for modules that have a newer version available on \s-1CPAN\s0 and provides a list of them. If called without argument, all potential upgrades are listed; if called with arguments the list is filtered to the modules and regexps given as arguments. .PP The listing looks something like this: .PP .Vb 10 \& Package namespace installed latest in CPAN file \& CPAN 1.94_64 1.9600 ANDK/CPAN\-1.9600.tar.gz \& CPAN::Reporter 1.1801 1.1902 DAGOLDEN/CPAN\-Reporter\-1.1902.tar.gz \& YAML 0.70 0.73 INGY/YAML\-0.73.tar.gz \& YAML::Syck 1.14 1.17 AVAR/YAML\-Syck\-1.17.tar.gz \& YAML::Tiny 1.44 1.50 ADAMK/YAML\-Tiny\-1.50.tar.gz \& CGI 3.43 3.55 MARKSTOS/CGI.pm\-3.55.tar.gz \& Module::Build::YAML 1.40 1.41 DAGOLDEN/Module\-Build\-0.3800.tar.gz \& TAP::Parser::Result::YAML 3.22 3.23 ANDYA/Test\-Harness\-3.23.tar.gz \& YAML::XS 0.34 0.35 INGY/YAML\-LibYAML\-0.35.tar.gz .Ve .PP It suppresses duplicates in the column \f(CW\*(C`in CPAN file\*(C'\fR such that distributions with many upgradeable modules are listed only once. .PP Note that the list is not sorted. .SS "recent ***EXPERIMENTAL COMMAND***" .IX Subsection "recent ***EXPERIMENTAL COMMAND***" The \f(CW\*(C`recent\*(C'\fR command downloads a list of recent uploads to \s-1CPAN\s0 and displays them \fIslowly\fR. While the command is running, a \f(CW$SIG\fR{\s-1INT\s0} exits the loop after displaying the current item. .PP \&\fBNote\fR: This command requires XML::LibXML installed. .PP \&\fBNote\fR: This whole command currently is just a hack and will probably change in future versions of \s-1CPAN\s0.pm, but the general approach will likely remain. .PP \&\fBNote\fR: See also smoke .SS "recompile" .IX Subsection "recompile" \&\fBrecompile()\fR is a special command that takes no argument and runs the make/test/install cycle with brute force over all installed dynamically loadable extensions (a.k.a. \s-1XS\s0 modules) with 'force' in effect. The primary purpose of this command is to finish a network installation. Imagine you have a common source tree for two different architectures. You decide to do a completely independent fresh installation. You start on one architecture with the help of a Bundle file produced earlier. \s-1CPAN\s0 installs the whole Bundle for you, but when you try to repeat the job on the second architecture, \s-1CPAN\s0 responds with a \f(CW"Foo up to date"\fR message for all modules. So you invoke \s-1CPAN\s0's recompile on the second architecture and you're done. .PP Another popular use for \f(CW\*(C`recompile\*(C'\fR is to act as a rescue in case your perl breaks binary compatibility. If one of the modules that \s-1CPAN\s0 uses is in turn depending on binary compatibility (so you cannot run \s-1CPAN\s0 commands), then you should try the CPAN::Nox module for recovery. .SS "report Bundle|Distribution|Module" .IX Subsection "report Bundle|Distribution|Module" The \f(CW\*(C`report\*(C'\fR command temporarily turns on the \f(CW\*(C`test_report\*(C'\fR config variable, then runs the \f(CW\*(C`force test\*(C'\fR command with the given arguments. The \f(CW\*(C`force\*(C'\fR pragma reruns the tests and repeats every step that might have failed before. .SS "smoke ***EXPERIMENTAL COMMAND***" .IX Subsection "smoke ***EXPERIMENTAL COMMAND***" \&\fB*** \s-1WARNING:\s0 this command downloads and executes software from \s-1CPAN\s0 to your computer of completely unknown status. You should never do this with your normal account and better have a dedicated well separated and secured machine to do this. ***\fR .PP The \f(CW\*(C`smoke\*(C'\fR command takes the list of recent uploads to \s-1CPAN\s0 as provided by the \f(CW\*(C`recent\*(C'\fR command and tests them all. While the command is running \f(CW$SIG\fR{\s-1INT\s0} is defined to mean that the current item shall be skipped. .PP \&\fBNote\fR: This whole command currently is just a hack and will probably change in future versions of \s-1CPAN\s0.pm, but the general approach will likely remain. .PP \&\fBNote\fR: See also recent .SS "upgrade [Module|/Regexp/]..." .IX Subsection "upgrade [Module|/Regexp/]..." The \f(CW\*(C`upgrade\*(C'\fR command first runs an \f(CW\*(C`r\*(C'\fR command with the given arguments and then installs the newest versions of all modules that were listed by that. .ie n .SS "The four ""CPAN::*"" Classes: Author, Bundle, Module, Distribution" .el .SS "The four \f(CWCPAN::*\fP Classes: Author, Bundle, Module, Distribution" .IX Subsection "The four CPAN::* Classes: Author, Bundle, Module, Distribution" Although it may be considered internal, the class hierarchy does matter for both users and programmer. \s-1CPAN\s0.pm deals with the four classes mentioned above, and those classes all share a set of methods. Classical single polymorphism is in effect. A metaclass object registers all objects of all kinds and indexes them with a string. The strings referencing objects have a separated namespace (well, not completely separated): .PP .Vb 1 \& Namespace Class \& \& words containing a "/" (slash) Distribution \& words starting with Bundle:: Bundle \& everything else Module or Author .Ve .PP Modules know their associated Distribution objects. They always refer to the most recent official release. Developers may mark their releases as unstable development versions (by inserting an underscore into the module version number which will also be reflected in the distribution name when you run 'make dist'), so the really hottest and newest distribution is not always the default. If a module Foo circulates on \s-1CPAN\s0 in both version 1.23 and 1.23_90, \s-1CPAN\s0.pm offers a convenient way to install version 1.23 by saying .PP .Vb 1 \& install Foo .Ve .PP This would install the complete distribution file (say BAR/Foo\-1.23.tar.gz) with all accompanying material. But if you would like to install version 1.23_90, you need to know where the distribution file resides on \s-1CPAN\s0 relative to the authors/id/ directory. If the author is \s-1BAR,\s0 this might be BAR/Foo\-1.23_90.tar.gz; so you would have to say .PP .Vb 1 \& install BAR/Foo\-1.23_90.tar.gz .Ve .PP The first example will be driven by an object of the class CPAN::Module, the second by an object of class CPAN::Distribution. .SS "Integrating local directories" .IX Subsection "Integrating local directories" Note: this feature is still in alpha state and may change in future versions of \s-1CPAN\s0.pm .PP Distribution objects are normally distributions from the \s-1CPAN,\s0 but there is a slightly degenerate case for Distribution objects, too, of projects held on the local disk. These distribution objects have the same name as the local directory and end with a dot. A dot by itself is also allowed for the current directory at the time \s-1CPAN\s0.pm was used. All actions such as \f(CW\*(C`make\*(C'\fR, \f(CW\*(C`test\*(C'\fR, and \f(CW\*(C`install\*(C'\fR are applied directly to that directory. This gives the command \f(CW\*(C`cpan .\*(C'\fR an interesting touch: while the normal mantra of installing a \s-1CPAN\s0 module without \s-1CPAN\s0.pm is one of .PP .Vb 5 \& perl Makefile.PL perl Build.PL \& ( go and get prerequisites ) \& make ./Build \& make test ./Build test \& make install ./Build install .Ve .PP the command \f(CW\*(C`cpan .\*(C'\fR does all of this at once. It figures out which of the two mantras is appropriate, fetches and installs all prerequisites, takes care of them recursively, and finally finishes the installation of the module in the current directory, be it a \s-1CPAN\s0 module or not. .PP The typical usage case is for private modules or working copies of projects from remote repositories on the local disk. .SS "Redirection" .IX Subsection "Redirection" The usual shell redirection symbols \f(CW\*(C` | \*(C'\fR and \f(CW\*(C`>\*(C'\fR are recognized by the cpan shell \fBonly when surrounded by whitespace\fR. So piping to pager or redirecting output into a file works somewhat as in a normal shell, with the stipulation that you must type extra spaces. .SS "Plugin support ***EXPERIMENTAL***" .IX Subsection "Plugin support ***EXPERIMENTAL***" Plugins are objects that implement any of currently eight methods: .PP .Vb 8 \& pre_get \& post_get \& pre_make \& post_make \& pre_test \& post_test \& pre_install \& post_install .Ve .PP The \f(CW\*(C`plugin_list\*(C'\fR configuration parameter holds a list of strings of the form .PP .Vb 1 \& Modulename=arg0,arg1,arg2,arg3,... .Ve .PP eg: .PP .Vb 1 \& CPAN::Plugin::Flurb=dir,/opt/pkgs/flurb/raw,verbose,1 .Ve .PP At run time, each listed plugin is instantiated as a singleton object by running the equivalent of this pseudo code: .PP .Vb 3 \& my $plugin = <string representation from config>; \& <generate Modulename and arguments from $plugin>; \& my $p = $instance{$plugin} ||= Modulename\->new($arg0,$arg1,...); .Ve .PP The generated singletons are kept around from instantiation until the end of the shell session. <plugin_list> can be reconfigured at any time at run time. While the cpan shell is running, it checks all activated plugins at each of the 8 reference points listed above and runs the respective method if it is implemented for that object. The method is called with the active CPAN::Distribution object passed in as an argument. .SH "CONFIGURATION" .IX Header "CONFIGURATION" When the \s-1CPAN\s0 module is used for the first time, a configuration dialogue tries to determine a couple of site specific options. The result of the dialog is stored in a hash reference \f(CW $CPAN::Config \fR in a file CPAN/Config.pm. .PP Default values defined in the CPAN/Config.pm file can be overridden in a user specific file: CPAN/MyConfig.pm. Such a file is best placed in \f(CW\*(C`$HOME/.cpan/CPAN/MyConfig.pm\*(C'\fR, because \f(CW\*(C`$HOME/.cpan\*(C'\fR is added to the search path of the \s-1CPAN\s0 module before the \fBuse()\fR or \&\fBrequire()\fR statements. The mkmyconfig command writes this file for you. .PP The \f(CW\*(C`o conf\*(C'\fR command has various bells and whistles: .IP "completion support" 4 .IX Item "completion support" If you have a ReadLine module installed, you can hit \s-1TAB\s0 at any point of the commandline and \f(CW\*(C`o conf\*(C'\fR will offer you completion for the built-in subcommands and/or config variable names. .IP "displaying some help: o conf help" 4 .IX Item "displaying some help: o conf help" Displays a short help .IP "displaying current values: o conf [\s-1KEY\s0]" 4 .IX Item "displaying current values: o conf [KEY]" Displays the current value(s) for this config variable. Without \s-1KEY,\s0 displays all subcommands and config variables. .Sp Example: .Sp .Vb 1 \& o conf shell .Ve .Sp If \s-1KEY\s0 starts and ends with a slash, the string in between is treated as a regular expression and only keys matching this regexp are displayed .Sp Example: .Sp .Vb 1 \& o conf /color/ .Ve .IP "changing of scalar values: o conf \s-1KEY VALUE\s0" 4 .IX Item "changing of scalar values: o conf KEY VALUE" Sets the config variable \s-1KEY\s0 to \s-1VALUE.\s0 The empty string can be specified as usual in shells, with \f(CW\*(Aq\*(Aq\fR or \f(CW""\fR .Sp Example: .Sp .Vb 1 \& o conf wget /usr/bin/wget .Ve .IP "changing of list values: o conf \s-1KEY\s0 SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST" 4 .IX Item "changing of list values: o conf KEY SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST" If a config variable name ends with \f(CW\*(C`list\*(C'\fR, it is a list. \f(CW\*(C`o conf KEY shift\*(C'\fR removes the first element of the list, \f(CW\*(C`o conf KEY pop\*(C'\fR removes the last element of the list. \f(CW\*(C`o conf KEYS unshift LIST\*(C'\fR prepends a list of values to the list, \f(CW\*(C`o conf KEYS push LIST\*(C'\fR appends a list of valued to the list. .Sp Likewise, \f(CW\*(C`o conf KEY splice LIST\*(C'\fR passes the \s-1LIST\s0 to the corresponding splice command. .Sp Finally, any other list of arguments is taken as a new list value for the \s-1KEY\s0 variable discarding the previous value. .Sp Examples: .Sp .Vb 3 \& o conf urllist unshift http://cpan.dev.local/CPAN \& o conf urllist splice 3 1 \& o conf urllist http://cpan1.local http://cpan2.local ftp://ftp.perl.org .Ve .IP "reverting to saved: o conf defaults" 4 .IX Item "reverting to saved: o conf defaults" Reverts all config variables to the state in the saved config file. .IP "saving the config: o conf commit" 4 .IX Item "saving the config: o conf commit" Saves all config variables to the current config file (CPAN/Config.pm or CPAN/MyConfig.pm that was loaded at start). .PP The configuration dialog can be started any time later again by issuing the command \f(CW\*(C` o conf init \*(C'\fR in the \s-1CPAN\s0 shell. A subset of the configuration dialog can be run by issuing \f(CW\*(C`o conf init WORD\*(C'\fR where \s-1WORD\s0 is any valid config variable or a regular expression. .SS "Config Variables" .IX Subsection "Config Variables" The following keys in the hash reference \f(CW$CPAN::Config\fR are currently defined: .PP .Vb 10 \& allow_installing_module_downgrades \& allow or disallow installing module downgrades \& allow_installing_outdated_dists \& allow or disallow installing modules that are \& indexed in the cpan index pointing to a distro \& with a higher distro\-version number \& applypatch path to external prg \& auto_commit commit all changes to config variables to disk \& build_cache size of cache for directories to build modules \& build_dir locally accessible directory to build modules \& build_dir_reuse boolean if distros in build_dir are persistent \& build_requires_install_policy \& to install or not to install when a module is \& only needed for building. yes|no|ask/yes|ask/no \& bzip2 path to external prg \& cache_metadata use serializer to cache metadata \& check_sigs if signatures should be verified \& cleanup_after_install \& remove build directory immediately after a \& successful install and remember that for the \& duration of the session \& colorize_debug Term::ANSIColor attributes for debugging output \& colorize_output boolean if Term::ANSIColor should colorize output \& colorize_print Term::ANSIColor attributes for normal output \& colorize_warn Term::ANSIColor attributes for warnings \& commandnumber_in_prompt \& boolean if you want to see current command number \& commands_quote preferred character to use for quoting external \& commands when running them. Defaults to double \& quote on Windows, single tick everywhere else; \& can be set to space to disable quoting \& connect_to_internet_ok \& whether to ask if opening a connection is ok before \& urllist is specified \& cpan_home local directory reserved for this package \& curl path to external prg \& dontload_hash DEPRECATED \& dontload_list arrayref: modules in the list will not be \& loaded by the CPAN::has_inst() routine \& ftp path to external prg \& ftp_passive if set, the environment variable FTP_PASSIVE is set \& for downloads \& ftp_proxy proxy host for ftp requests \& ftpstats_period max number of days to keep download statistics \& ftpstats_size max number of items to keep in the download statistics \& getcwd see below \& gpg path to external prg \& gzip location of external program gzip \& halt_on_failure stop processing after the first failure of queued \& items or dependencies \& histfile file to maintain history between sessions \& histsize maximum number of lines to keep in histfile \& http_proxy proxy host for http requests \& inactivity_timeout breaks interactive Makefile.PLs or Build.PLs \& after this many seconds inactivity. Set to 0 to \& disable timeouts. \& index_expire refetch index files after this many days \& inhibit_startup_message \& if true, suppress the startup message \& keep_source_where directory in which to keep the source (if we do) \& load_module_verbosity \& report loading of optional modules used by CPAN.pm \& lynx path to external prg \& make location of external make program \& make_arg arguments that should always be passed to \*(Aqmake\*(Aq \& make_install_make_command \& the make command for running \*(Aqmake install\*(Aq, for \& example \*(Aqsudo make\*(Aq \& make_install_arg same as make_arg for \*(Aqmake install\*(Aq \& makepl_arg arguments passed to \*(Aqperl Makefile.PL\*(Aq \& mbuild_arg arguments passed to \*(Aq./Build\*(Aq \& mbuild_install_arg arguments passed to \*(Aq./Build install\*(Aq \& mbuild_install_build_command \& command to use instead of \*(Aq./Build\*(Aq when we are \& in the install stage, for example \*(Aqsudo ./Build\*(Aq \& mbuildpl_arg arguments passed to \*(Aqperl Build.PL\*(Aq \& ncftp path to external prg \& ncftpget path to external prg \& no_proxy don\*(Aqt proxy to these hosts/domains (comma separated list) \& pager location of external program more (or any pager) \& password your password if you CPAN server wants one \& patch path to external prg \& patches_dir local directory containing patch files \& perl5lib_verbosity verbosity level for PERL5LIB additions \& plugin_list list of active hooks (see Plugin support above \& and the CPAN::Plugin module) \& prefer_external_tar \& per default all untar operations are done with \& Archive::Tar; by setting this variable to true \& the external tar command is used if available \& prefer_installer legal values are MB and EUMM: if a module comes \& with both a Makefile.PL and a Build.PL, use the \& former (EUMM) or the latter (MB); if the module \& comes with only one of the two, that one will be \& used no matter the setting \& prerequisites_policy \& what to do if you are missing module prerequisites \& (\*(Aqfollow\*(Aq automatically, \*(Aqask\*(Aq me, or \*(Aqignore\*(Aq) \& For \*(Aqfollow\*(Aq, also sets PERL_AUTOINSTALL and \& PERL_EXTUTILS_AUTOINSTALL for "\-\-defaultdeps" if \& not already set \& prefs_dir local directory to store per\-distro build options \& proxy_user username for accessing an authenticating proxy \& proxy_pass password for accessing an authenticating proxy \& pushy_https use https to cpan.org when possible, otherwise use http \& to cpan.org and issue a warning \& randomize_urllist add some randomness to the sequence of the urllist \& recommends_policy whether recommended prerequisites should be included \& scan_cache controls scanning of cache (\*(Aqatstart\*(Aq, \*(Aqatexit\*(Aq or \*(Aqnever\*(Aq) \& shell your favorite shell \& show_unparsable_versions \& boolean if r command tells which modules are versionless \& show_upload_date boolean if commands should try to determine upload date \& show_zero_versions boolean if r command tells for which modules $version==0 \& suggests_policy whether suggested prerequisites should be included \& tar location of external program tar \& tar_verbosity verbosity level for the tar command \& term_is_latin deprecated: if true Unicode is translated to ISO\-8859\-1 \& (and nonsense for characters outside latin range) \& term_ornaments boolean to turn ReadLine ornamenting on/off \& test_report email test reports (if CPAN::Reporter is installed) \& trust_test_report_history \& skip testing when previously tested ok (according to \& CPAN::Reporter history) \& unzip location of external program unzip \& urllist arrayref to nearby CPAN sites (or equivalent locations) \& urllist_ping_external \& use external ping command when autoselecting mirrors \& urllist_ping_verbose \& increase verbosity when autoselecting mirrors \& use_prompt_default set PERL_MM_USE_DEFAULT for configure/make/test/install \& use_sqlite use CPAN::SQLite for metadata storage (fast and lean) \& username your username if you CPAN server wants one \& version_timeout stops version parsing after this many seconds. \& Default is 15 secs. Set to 0 to disable. \& wait_list arrayref to a wait server to try (See CPAN::WAIT) \& wget path to external prg \& yaml_load_code enable YAML code deserialisation via CPAN::DeferredCode \& yaml_module which module to use to read/write YAML files .Ve .PP You can set and query each of these options interactively in the cpan shell with the \f(CW\*(C`o conf\*(C'\fR or the \f(CW\*(C`o conf init\*(C'\fR command as specified below. .ie n .IP """o conf <scalar option>""" 2 .el .IP "\f(CWo conf <scalar option>\fR" 2 .IX Item "o conf <scalar option>" prints the current value of the \fIscalar option\fR .ie n .IP """o conf <scalar option> <value>""" 2 .el .IP "\f(CWo conf <scalar option> <value>\fR" 2 .IX Item "o conf <scalar option> <value>" Sets the value of the \fIscalar option\fR to \fIvalue\fR .ie n .IP """o conf <list option>""" 2 .el .IP "\f(CWo conf <list option>\fR" 2 .IX Item "o conf <list option>" prints the current value of the \fIlist option\fR in MakeMaker's neatvalue format. .ie n .IP """o conf <list option> [shift|pop]""" 2 .el .IP "\f(CWo conf <list option> [shift|pop]\fR" 2 .IX Item "o conf <list option> [shift|pop]" shifts or pops the array in the \fIlist option\fR variable .ie n .IP """o conf <list option> [unshift|push|splice] <list>""" 2 .el .IP "\f(CWo conf <list option> [unshift|push|splice] <list>\fR" 2 .IX Item "o conf <list option> [unshift|push|splice] <list>" works like the corresponding perl commands. .IP "interactive editing: o conf init [MATCH|LIST]" 2 .IX Item "interactive editing: o conf init [MATCH|LIST]" Runs an interactive configuration dialog for matching variables. Without argument runs the dialog over all supported config variables. To specify a \s-1MATCH\s0 the argument must be enclosed by slashes. .Sp Examples: .Sp .Vb 2 \& o conf init ftp_passive ftp_proxy \& o conf init /color/ .Ve .Sp Note: this method of setting config variables often provides more explanation about the functioning of a variable than the manpage. .SS "CPAN::anycwd($path): Note on config variable getcwd" .IX Subsection "CPAN::anycwd($path): Note on config variable getcwd" \&\s-1CPAN\s0.pm changes the current working directory often and needs to determine its own current working directory. By default it uses Cwd::cwd, but if for some reason this doesn't work on your system, configure alternatives according to the following table: .IP "cwd" 4 .IX Item "cwd" Calls Cwd::cwd .IP "getcwd" 4 .IX Item "getcwd" Calls Cwd::getcwd .IP "fastcwd" 4 .IX Item "fastcwd" Calls Cwd::fastcwd .IP "getdcwd" 4 .IX Item "getdcwd" Calls Cwd::getdcwd .IP "backtickcwd" 4 .IX Item "backtickcwd" Calls the external command cwd. .SS "Note on the format of the urllist parameter" .IX Subsection "Note on the format of the urllist parameter" urllist parameters are URLs according to \s-1RFC 1738.\s0 We do a little guessing if your \s-1URL\s0 is not compliant, but if you have problems with \&\f(CW\*(C`file\*(C'\fR URLs, please try the correct format. Either: .PP .Vb 1 \& file://localhost/whatever/ftp/pub/CPAN/ .Ve .PP or .PP .Vb 1 \& file:///home/ftp/pub/CPAN/ .Ve .SS "The urllist parameter has CD-ROM support" .IX Subsection "The urllist parameter has CD-ROM support" The \f(CW\*(C`urllist\*(C'\fR parameter of the configuration table contains a list of URLs used for downloading. If the list contains any \&\f(CW\*(C`file\*(C'\fR URLs, \s-1CPAN\s0 always tries there first. This feature is disabled for index files. So the recommendation for the owner of a CD-ROM with \s-1CPAN\s0 contents is: include your local, possibly outdated CD-ROM as a \f(CW\*(C`file\*(C'\fR \s-1URL\s0 at the end of urllist, e.g. .PP .Vb 1 \& o conf urllist push file://localhost/CDROM/CPAN .Ve .PP \&\s-1CPAN\s0.pm will then fetch the index files from one of the \s-1CPAN\s0 sites that come at the beginning of urllist. It will later check for each module to see whether there is a local copy of the most recent version. .PP Another peculiarity of urllist is that the site that we could successfully fetch the last file from automatically gets a preference token and is tried as the first site for the next request. So if you add a new site at runtime it may happen that the previously preferred site will be tried another time. This means that if you want to disallow a site for the next transfer, it must be explicitly removed from urllist. .SS "Maintaining the urllist parameter" .IX Subsection "Maintaining the urllist parameter" If you have \s-1YAML\s0.pm (or some other \s-1YAML\s0 module configured in \&\f(CW\*(C`yaml_module\*(C'\fR) installed, \s-1CPAN\s0.pm collects a few statistical data about recent downloads. You can view the statistics with the \f(CW\*(C`hosts\*(C'\fR command or inspect them directly by looking into the \f(CW\*(C`FTPstats.yml\*(C'\fR file in your \f(CW\*(C`cpan_home\*(C'\fR directory. .PP To get some interesting statistics, it is recommended that \&\f(CW\*(C`randomize_urllist\*(C'\fR be set; this introduces some amount of randomness into the \s-1URL\s0 selection. .ie n .SS "The ""requires"" and ""build_requires"" dependency declarations" .el .SS "The \f(CWrequires\fP and \f(CWbuild_requires\fP dependency declarations" .IX Subsection "The requires and build_requires dependency declarations" Since \s-1CPAN\s0.pm version 1.88_51 modules declared as \f(CW\*(C`build_requires\*(C'\fR by a distribution are treated differently depending on the config variable \f(CW\*(C`build_requires_install_policy\*(C'\fR. By setting \&\f(CW\*(C`build_requires_install_policy\*(C'\fR to \f(CW\*(C`no\*(C'\fR, such a module is not installed. It is only built and tested, and then kept in the list of tested but uninstalled modules. As such, it is available during the build of the dependent module by integrating the path to the \&\f(CW\*(C`blib/arch\*(C'\fR and \f(CW\*(C`blib/lib\*(C'\fR directories in the environment variable \&\s-1PERL5LIB.\s0 If \f(CW\*(C`build_requires_install_policy\*(C'\fR is set to \f(CW\*(C`yes\*(C'\fR, then both modules declared as \f(CW\*(C`requires\*(C'\fR and those declared as \&\f(CW\*(C`build_requires\*(C'\fR are treated alike. By setting to \f(CW\*(C`ask/yes\*(C'\fR or \&\f(CW\*(C`ask/no\*(C'\fR, \s-1CPAN\s0.pm asks the user and sets the default accordingly. .SS "Configuration of the allow_installing_* parameters" .IX Subsection "Configuration of the allow_installing_* parameters" The \f(CW\*(C`allow_installing_*\*(C'\fR parameters are evaluated during the \f(CW\*(C`make\*(C'\fR phase. If set to \f(CW\*(C`yes\*(C'\fR, they allow the testing and the installation of the current distro and otherwise have no effect. If set to \f(CW\*(C`no\*(C'\fR, they may abort the build (preventing testing and installing), depending on the contents of the \&\f(CW\*(C`blib/\*(C'\fR directory. The \f(CW\*(C`blib/\*(C'\fR directory is the directory that holds all the files that would usually be installed in the \f(CW\*(C`install\*(C'\fR phase. .PP \&\f(CW\*(C`allow_installing_outdated_dists\*(C'\fR compares the \f(CW\*(C`blib/\*(C'\fR directory with the \s-1CPAN\s0 index. If it finds something there that belongs, according to the index, to a different dist, it aborts the current build. .PP \&\f(CW\*(C`allow_installing_module_downgrades\*(C'\fR compares the \f(CW\*(C`blib/\*(C'\fR directory with already installed modules, actually their version numbers, as determined by ExtUtils::MakeMaker or equivalent. If a to-be-installed module would downgrade an already installed module, the current build is aborted. .PP An interesting twist occurs when a distroprefs document demands the installation of an outdated dist via goto while \&\f(CW\*(C`allow_installing_outdated_dists\*(C'\fR forbids it. Without additional provisions, this would let the \f(CW\*(C`allow_installing_outdated_dists\*(C'\fR win and the distroprefs lose. So the proper arrangement in such a case is to write a second distroprefs document for the distro that \f(CW\*(C`goto\*(C'\fR points to and overrule the \f(CW\*(C`cpanconfig\*(C'\fR there. E.g.: .PP .Vb 9 \& \-\-\- \& match: \& distribution: "^MAUKE/Keyword\-Simple\-0.04.tar.gz" \& goto: "MAUKE/Keyword\-Simple\-0.03.tar.gz" \& \-\-\- \& match: \& distribution: "^MAUKE/Keyword\-Simple\-0.03.tar.gz" \& cpanconfig: \& allow_installing_outdated_dists: yes .Ve .SS "Configuration for individual distributions (\fIDistroprefs\fP)" .IX Subsection "Configuration for individual distributions (Distroprefs)" (\fBNote:\fR This feature has been introduced in \s-1CPAN\s0.pm 1.8854) .PP Distributions on \s-1CPAN\s0 usually behave according to what we call the \&\s-1CPAN\s0 mantra. Or since the advent of Module::Build we should talk about two mantras: .PP .Vb 4 \& perl Makefile.PL perl Build.PL \& make ./Build \& make test ./Build test \& make install ./Build install .Ve .PP But some modules cannot be built with this mantra. They try to get some extra data from the user via the environment, extra arguments, or interactively\*(--thus disturbing the installation of large bundles like Phalanx100 or modules with many dependencies like Plagger. .PP The distroprefs system of \f(CW\*(C`CPAN.pm\*(C'\fR addresses this problem by allowing the user to specify extra informations and recipes in \s-1YAML\s0 files to either .IP "\(bu" 4 pass additional arguments to one of the four commands, .IP "\(bu" 4 set environment variables .IP "\(bu" 4 instantiate an Expect object that reads from the console, waits for some regular expressions and enters some answers .IP "\(bu" 4 temporarily override assorted \f(CW\*(C`CPAN.pm\*(C'\fR configuration variables .IP "\(bu" 4 specify dependencies the original maintainer forgot .IP "\(bu" 4 disable the installation of an object altogether .PP See the \s-1YAML\s0 and Data::Dumper files that come with the \f(CW\*(C`CPAN.pm\*(C'\fR distribution in the \f(CW\*(C`distroprefs/\*(C'\fR directory for examples. .SS "Filenames" .IX Subsection "Filenames" The \s-1YAML\s0 files themselves must have the \f(CW\*(C`.yml\*(C'\fR extension; all other files are ignored (for two exceptions see \fIFallback Data::Dumper and Storable\fR below). The containing directory can be specified in \&\f(CW\*(C`CPAN.pm\*(C'\fR in the \f(CW\*(C`prefs_dir\*(C'\fR config variable. Try \f(CW\*(C`o conf init prefs_dir\*(C'\fR in the \s-1CPAN\s0 shell to set and activate the distroprefs system. .PP Every \s-1YAML\s0 file may contain arbitrary documents according to the \s-1YAML\s0 specification, and every document is treated as an entity that can specify the treatment of a single distribution. .PP Filenames can be picked arbitrarily; \f(CW\*(C`CPAN.pm\*(C'\fR always reads all files (in alphabetical order) and takes the key \f(CW\*(C`match\*(C'\fR (see below in \fILanguage Specs\fR) as a hashref containing match criteria that determine if the current distribution matches the \s-1YAML\s0 document or not. .SS "Fallback Data::Dumper and Storable" .IX Subsection "Fallback Data::Dumper and Storable" If neither your configured \f(CW\*(C`yaml_module\*(C'\fR nor \s-1YAML\s0.pm is installed, \&\s-1CPAN\s0.pm falls back to using Data::Dumper and Storable and looks for files with the extensions \f(CW\*(C`.dd\*(C'\fR or \f(CW\*(C`.st\*(C'\fR in the \f(CW\*(C`prefs_dir\*(C'\fR directory. These files are expected to contain one or more hashrefs. For Data::Dumper generated files, this is expected to be done with by defining \f(CW$VAR1\fR, \f(CW$VAR2\fR, etc. The \s-1YAML\s0 shell would produce these with the command .PP .Vb 1 \& ysh < somefile.yml > somefile.dd .Ve .PP For Storable files the rule is that they must be constructed such that \&\f(CW\*(C`Storable::retrieve(file)\*(C'\fR returns an array reference and the array elements represent one distropref object each. The conversion from \&\s-1YAML\s0 would look like so: .PP .Vb 3 \& perl \-MYAML=LoadFile \-MStorable=nstore \-e \*(Aq \& @y=LoadFile(shift); \& nstore(\e@y, shift)\*(Aq somefile.yml somefile.st .Ve .PP In bootstrapping situations it is usually sufficient to translate only a few \s-1YAML\s0 files to Data::Dumper for crucial modules like \&\f(CW\*(C`YAML::Syck\*(C'\fR, \f(CW\*(C`YAML.pm\*(C'\fR and \f(CW\*(C`Expect.pm\*(C'\fR. If you prefer Storable over Data::Dumper, remember to pull out a Storable version that writes an older format than all the other Storable versions that will need to read them. .SS "Blueprint" .IX Subsection "Blueprint" The following example contains all supported keywords and structures with the exception of \f(CW\*(C`eexpect\*(C'\fR which can be used instead of \&\f(CW\*(C`expect\*(C'\fR. .PP .Vb 10 \& \-\-\- \& comment: "Demo" \& match: \& module: "Dancing::Queen" \& distribution: "^CHACHACHA/Dancing\-" \& not_distribution: "\e.zip$" \& perl: "/usr/local/cariba\-perl/bin/perl" \& perlconfig: \& archname: "freebsd" \& not_cc: "gcc" \& env: \& DANCING_FLOOR: "Shubiduh" \& disabled: 1 \& cpanconfig: \& make: gmake \& pl: \& args: \& \- "\-\-somearg=specialcase" \& \& env: {} \& \& expect: \& \- "Which is your favorite fruit" \& \- "apple\en" \& \& make: \& args: \& \- all \& \- extra\-all \& \& env: {} \& \& expect: [] \& \& commandline: "echo SKIPPING make" \& \& test: \& args: [] \& \& env: {} \& \& expect: [] \& \& install: \& args: [] \& \& env: \& WANT_TO_INSTALL: YES \& \& expect: \& \- "Do you really want to install" \& \- "y\en" \& \& patches: \& \- "ABCDE/Fedcba\-3.14\-ABCDE\-01.patch" \& \& depends: \& configure_requires: \& LWP: 5.8 \& build_requires: \& Test::Exception: 0.25 \& requires: \& Spiffy: 0.30 .Ve .SS "Language Specs" .IX Subsection "Language Specs" Every \s-1YAML\s0 document represents a single hash reference. The valid keys in this hash are as follows: .IP "comment [scalar]" 4 .IX Item "comment [scalar]" A comment .IP "cpanconfig [hash]" 4 .IX Item "cpanconfig [hash]" Temporarily override assorted \f(CW\*(C`CPAN.pm\*(C'\fR configuration variables. .Sp Supported are: \f(CW\*(C`build_requires_install_policy\*(C'\fR, \f(CW\*(C`check_sigs\*(C'\fR, \&\f(CW\*(C`make\*(C'\fR, \f(CW\*(C`make_install_make_command\*(C'\fR, \f(CW\*(C`prefer_installer\*(C'\fR, \&\f(CW\*(C`test_report\*(C'\fR. Please report as a bug when you need another one supported. .IP "depends [hash] *** \s-1EXPERIMENTAL FEATURE\s0 ***" 4 .IX Item "depends [hash] *** EXPERIMENTAL FEATURE ***" All three types, namely \f(CW\*(C`configure_requires\*(C'\fR, \f(CW\*(C`build_requires\*(C'\fR, and \&\f(CW\*(C`requires\*(C'\fR are supported in the way specified in the \s-1META\s0.yml specification. The current implementation \fImerges\fR the specified dependencies with those declared by the package maintainer. In a future implementation this may be changed to override the original declaration. .IP "disabled [boolean]" 4 .IX Item "disabled [boolean]" Specifies that this distribution shall not be processed at all. .IP "features [array] *** \s-1EXPERIMENTAL FEATURE\s0 ***" 4 .IX Item "features [array] *** EXPERIMENTAL FEATURE ***" Experimental implementation to deal with optional_features from \&\s-1META\s0.yml. Still needs coordination with installer software and currently works only for \s-1META\s0.yml declaring \f(CW\*(C`dynamic_config=0\*(C'\fR. Use with caution. .IP "goto [string]" 4 .IX Item "goto [string]" The canonical name of a delegate distribution to install instead. Useful when a new version, although it tests \s-1OK\s0 itself, breaks something else or a developer release or a fork is already uploaded that is better than the last released version. .IP "install [hash]" 4 .IX Item "install [hash]" Processing instructions for the \f(CW\*(C`make install\*(C'\fR or \f(CW\*(C`./Build install\*(C'\fR phase of the \s-1CPAN\s0 mantra. See below under \fIProcessing Instructions\fR. .IP "make [hash]" 4 .IX Item "make [hash]" Processing instructions for the \f(CW\*(C`make\*(C'\fR or \f(CW\*(C`./Build\*(C'\fR phase of the \&\s-1CPAN\s0 mantra. See below under \fIProcessing Instructions\fR. .IP "match [hash]" 4 .IX Item "match [hash]" A hashref with one or more of the keys \f(CW\*(C`distribution\*(C'\fR, \f(CW\*(C`module\*(C'\fR, \&\f(CW\*(C`perl\*(C'\fR, \f(CW\*(C`perlconfig\*(C'\fR, and \f(CW\*(C`env\*(C'\fR that specify whether a document is targeted at a specific \s-1CPAN\s0 distribution or installation. Keys prefixed with \f(CW\*(C`not_\*(C'\fR negates the corresponding match. .Sp The corresponding values are interpreted as regular expressions. The \&\f(CW\*(C`distribution\*(C'\fR related one will be matched against the canonical distribution name, e.g. \*(L"AUTHOR/Foo\-Bar\-3.14.tar.gz\*(R". .Sp The \f(CW\*(C`module\*(C'\fR related one will be matched against \fIall\fR modules contained in the distribution until one module matches. .Sp The \f(CW\*(C`perl\*(C'\fR related one will be matched against \f(CW$^X\fR (but with the absolute path). .Sp The value associated with \f(CW\*(C`perlconfig\*(C'\fR is itself a hashref that is matched against corresponding values in the \f(CW%Config::Config\fR hash living in the \f(CW\*(C`Config.pm\*(C'\fR module. Keys prefixed with \f(CW\*(C`not_\*(C'\fR negates the corresponding match. .Sp The value associated with \f(CW\*(C`env\*(C'\fR is itself a hashref that is matched against corresponding values in the \f(CW%ENV\fR hash. Keys prefixed with \f(CW\*(C`not_\*(C'\fR negates the corresponding match. .Sp If more than one restriction of \f(CW\*(C`module\*(C'\fR, \f(CW\*(C`distribution\*(C'\fR, etc. is specified, the results of the separately computed match values must all match. If so, the hashref represented by the \&\s-1YAML\s0 document is returned as the preference structure for the current distribution. .IP "patches [array]" 4 .IX Item "patches [array]" An array of patches on \s-1CPAN\s0 or on the local disk to be applied in order via an external patch program. If the value for the \f(CW\*(C`\-p\*(C'\fR parameter is \f(CW0\fR or \f(CW1\fR is determined by reading the patch beforehand. The path to each patch is either an absolute path on the local filesystem or relative to a patch directory specified in the \&\f(CW\*(C`patches_dir\*(C'\fR configuration variable or in the format of a canonical distro name. For examples please consult the distroprefs/ directory in the \s-1CPAN\s0.pm distribution (these examples are not installed by default). .Sp Note: if the \f(CW\*(C`applypatch\*(C'\fR program is installed and \f(CW\*(C`CPAN::Config\*(C'\fR knows about it \fBand\fR a patch is written by the \f(CW\*(C`makepatch\*(C'\fR program, then \f(CW\*(C`CPAN.pm\*(C'\fR lets \f(CW\*(C`applypatch\*(C'\fR apply the patch. Both \f(CW\*(C`makepatch\*(C'\fR and \f(CW\*(C`applypatch\*(C'\fR are available from \s-1CPAN\s0 in the \f(CW\*(C`JV/makepatch\-*\*(C'\fR distribution. .IP "pl [hash]" 4 .IX Item "pl [hash]" Processing instructions for the \f(CW\*(C`perl Makefile.PL\*(C'\fR or \f(CW\*(C`perl Build.PL\*(C'\fR phase of the \s-1CPAN\s0 mantra. See below under \fIProcessing Instructions\fR. .IP "test [hash]" 4 .IX Item "test [hash]" Processing instructions for the \f(CW\*(C`make test\*(C'\fR or \f(CW\*(C`./Build test\*(C'\fR phase of the \s-1CPAN\s0 mantra. See below under \fIProcessing Instructions\fR. .SS "Processing Instructions" .IX Subsection "Processing Instructions" .IP "args [array]" 4 .IX Item "args [array]" Arguments to be added to the command line .IP "commandline" 4 .IX Item "commandline" A full commandline to run via \f(CW\*(C`system()\*(C'\fR. During execution, the environment variable \s-1PERL\s0 is set to $^X (but with an absolute path). If \f(CW\*(C`commandline\*(C'\fR is specified, \&\f(CW\*(C`args\*(C'\fR is not used. .IP "eexpect [hash]" 4 .IX Item "eexpect [hash]" Extended \f(CW\*(C`expect\*(C'\fR. This is a hash reference with four allowed keys, \&\f(CW\*(C`mode\*(C'\fR, \f(CW\*(C`timeout\*(C'\fR, \f(CW\*(C`reuse\*(C'\fR, and \f(CW\*(C`talk\*(C'\fR. .Sp You must install the \f(CW\*(C`Expect\*(C'\fR module to use \f(CW\*(C`eexpect\*(C'\fR. \s-1CPAN\s0.pm does not install it for you. .Sp \&\f(CW\*(C`mode\*(C'\fR may have the values \f(CW\*(C`deterministic\*(C'\fR for the case where all questions come in the order written down and \f(CW\*(C`anyorder\*(C'\fR for the case where the questions may come in any order. The default mode is \&\f(CW\*(C`deterministic\*(C'\fR. .Sp \&\f(CW\*(C`timeout\*(C'\fR denotes a timeout in seconds. Floating-point timeouts are \&\s-1OK.\s0 With \f(CW\*(C`mode=deterministic\*(C'\fR, the timeout denotes the timeout per question; with \f(CW\*(C`mode=anyorder\*(C'\fR it denotes the timeout per byte received from the stream or questions. .Sp \&\f(CW\*(C`talk\*(C'\fR is a reference to an array that contains alternating questions and answers. Questions are regular expressions and answers are literal strings. The Expect module watches the stream from the execution of the external program (\f(CW\*(C`perl Makefile.PL\*(C'\fR, \f(CW\*(C`perl Build.PL\*(C'\fR, \f(CW\*(C`make\*(C'\fR, etc.). .Sp For \f(CW\*(C`mode=deterministic\*(C'\fR, the \s-1CPAN\s0.pm injects the corresponding answer as soon as the stream matches the regular expression. .Sp For \f(CW\*(C`mode=anyorder\*(C'\fR \s-1CPAN\s0.pm answers a question as soon as the timeout is reached for the next byte in the input stream. In this mode you can use the \f(CW\*(C`reuse\*(C'\fR parameter to decide what will happen with a question-answer pair after it has been used. In the default case (reuse=0) it is removed from the array, avoiding being used again accidentally. If you want to answer the question \f(CW\*(C`Do you really want to do that\*(C'\fR several times, then it must be included in the array at least as often as you want this answer to be given. Setting the parameter \f(CW\*(C`reuse\*(C'\fR to 1 makes this repetition unnecessary. .IP "env [hash]" 4 .IX Item "env [hash]" Environment variables to be set during the command .IP "expect [array]" 4 .IX Item "expect [array]" You must install the \f(CW\*(C`Expect\*(C'\fR module to use \f(CW\*(C`expect\*(C'\fR. \s-1CPAN\s0.pm does not install it for you. .Sp \&\f(CW\*(C`expect: <array>\*(C'\fR is a short notation for this \f(CW\*(C`eexpect\*(C'\fR: .Sp .Vb 4 \& eexpect: \& mode: deterministic \& timeout: 15 \& talk: <array> .Ve .ie n .SS "Schema verification with ""Kwalify""" .el .SS "Schema verification with \f(CWKwalify\fP" .IX Subsection "Schema verification with Kwalify" If you have the \f(CW\*(C`Kwalify\*(C'\fR module installed (which is part of the Bundle::CPANxxl), then all your distroprefs files are checked for syntactic correctness. .SS "Example Distroprefs Files" .IX Subsection "Example Distroprefs Files" \&\f(CW\*(C`CPAN.pm\*(C'\fR comes with a collection of example \s-1YAML\s0 files. Note that these are really just examples and should not be used without care because they cannot fit everybody's purpose. After all, the authors of the packages that ask questions had a need to ask, so you should watch their questions and adjust the examples to your environment and your needs. You have been warned:\-) .SH "PROGRAMMER'S INTERFACE" .IX Header "PROGRAMMER'S INTERFACE" If you do not enter the shell, shell commands are available both as methods (\f(CW\*(C`CPAN::Shell\->install(...)\*(C'\fR) and as functions in the calling package (\f(CW\*(C`install(...)\*(C'\fR). Before calling low-level commands, it makes sense to initialize components of \s-1CPAN\s0 you need, e.g.: .PP .Vb 3 \& CPAN::HandleConfig\->load; \& CPAN::Shell::setup_output; \& CPAN::Index\->reload; .Ve .PP High-level commands do such initializations automatically. .PP There's currently only one class that has a stable interface \- CPAN::Shell. All commands that are available in the \s-1CPAN\s0 shell are methods of the class CPAN::Shell. The arguments on the commandline are passed as arguments to the method. .PP So if you take for example the shell command .PP .Vb 1 \& notest install A B C .Ve .PP the actually executed command is .PP .Vb 1 \& CPAN::Shell\->notest("install","A","B","C"); .Ve .PP Each of the commands that produce listings of modules (\f(CW\*(C`r\*(C'\fR, \&\f(CW\*(C`autobundle\*(C'\fR, \f(CW\*(C`u\*(C'\fR) also return a list of the IDs of all modules within the list. .IP "expand($type,@things)" 2 .IX Item "expand($type,@things)" The IDs of all objects available within a program are strings that can be expanded to the corresponding real objects with the \&\f(CW\*(C`CPAN::Shell\->expand("Module",@things)\*(C'\fR method. Expand returns a list of CPAN::Module objects according to the \f(CW@things\fR arguments given. In scalar context, it returns only the first element of the list. .IP "expandany(@things)" 2 .IX Item "expandany(@things)" Like expand, but returns objects of the appropriate type, i.e. CPAN::Bundle objects for bundles, CPAN::Module objects for modules, and CPAN::Distribution objects for distributions. Note: it does not expand to CPAN::Author objects. .IP "Programming Examples" 2 .IX Item "Programming Examples" This enables the programmer to do operations that combine functionalities that are available in the shell. .Sp .Vb 2 \& # install everything that is outdated on my disk: \& perl \-MCPAN \-e \*(AqCPAN::Shell\->install(CPAN::Shell\->r)\*(Aq \& \& # install my favorite programs if necessary: \& for $mod (qw(Net::FTP Digest::SHA Data::Dumper)) { \& CPAN::Shell\->install($mod); \& } \& \& # list all modules on my disk that have no VERSION number \& for $mod (CPAN::Shell\->expand("Module","/./")) { \& next unless $mod\->inst_file; \& # MakeMaker convention for undefined $VERSION: \& next unless $mod\->inst_version eq "undef"; \& print "No VERSION in ", $mod\->id, "\en"; \& } \& \& # find out which distribution on CPAN contains a module: \& print CPAN::Shell\->expand("Module","Apache::Constants")\->cpan_file .Ve .Sp Or if you want to schedule a \fIcron\fR job to watch \s-1CPAN,\s0 you could list all modules that need updating. First a quick and dirty way: .Sp .Vb 1 \& perl \-e \*(Aquse CPAN; CPAN::Shell\->r;\*(Aq .Ve .Sp If you don't want any output should all modules be up to date, parse the output of above command for the regular expression \f(CW\*(C`/modules are up to date/\*(C'\fR and decide to mail the output only if it doesn't match. .Sp If you prefer to do it more in a programmerish style in one single process, something like this may better suit you: .Sp .Vb 7 \& # list all modules on my disk that have newer versions on CPAN \& for $mod (CPAN::Shell\->expand("Module","/./")) { \& next unless $mod\->inst_file; \& next if $mod\->uptodate; \& printf "Module %s is installed as %s, could be updated to %s from CPAN\en", \& $mod\->id, $mod\->inst_version, $mod\->cpan_version; \& } .Ve .Sp If that gives too much output every day, you may want to watch only for three modules. You can write .Sp .Vb 1 \& for $mod (CPAN::Shell\->expand("Module","/Apache|LWP|CGI/")) { .Ve .Sp as the first line instead. Or you can combine some of the above tricks: .Sp .Vb 5 \& # watch only for a new mod_perl module \& $mod = CPAN::Shell\->expand("Module","mod_perl"); \& exit if $mod\->uptodate; \& # new mod_perl arrived, let me know all update recommendations \& CPAN::Shell\->r; .Ve .SS "Methods in the other Classes" .IX Subsection "Methods in the other Classes" .IP "\fBCPAN::Author::as_glimpse()\fR" 4 .IX Item "CPAN::Author::as_glimpse()" Returns a one-line description of the author .IP "\fBCPAN::Author::as_string()\fR" 4 .IX Item "CPAN::Author::as_string()" Returns a multi-line description of the author .IP "\fBCPAN::Author::email()\fR" 4 .IX Item "CPAN::Author::email()" Returns the author's email address .IP "\fBCPAN::Author::fullname()\fR" 4 .IX Item "CPAN::Author::fullname()" Returns the author's name .IP "\fBCPAN::Author::name()\fR" 4 .IX Item "CPAN::Author::name()" An alias for fullname .IP "\fBCPAN::Bundle::as_glimpse()\fR" 4 .IX Item "CPAN::Bundle::as_glimpse()" Returns a one-line description of the bundle .IP "\fBCPAN::Bundle::as_string()\fR" 4 .IX Item "CPAN::Bundle::as_string()" Returns a multi-line description of the bundle .IP "\fBCPAN::Bundle::clean()\fR" 4 .IX Item "CPAN::Bundle::clean()" Recursively runs the \f(CW\*(C`clean\*(C'\fR method on all items contained in the bundle. .IP "\fBCPAN::Bundle::contains()\fR" 4 .IX Item "CPAN::Bundle::contains()" Returns a list of objects' IDs contained in a bundle. The associated objects may be bundles, modules or distributions. .IP "CPAN::Bundle::force($method,@args)" 4 .IX Item "CPAN::Bundle::force($method,@args)" Forces \s-1CPAN\s0 to perform a task that it normally would have refused to do. Force takes as arguments a method name to be called and any number of additional arguments that should be passed to the called method. The internals of the object get the needed changes so that \s-1CPAN\s0.pm does not refuse to take the action. The \f(CW\*(C`force\*(C'\fR is passed recursively to all contained objects. See also the section above on the \f(CW\*(C`force\*(C'\fR and the \f(CW\*(C`fforce\*(C'\fR pragma. .IP "\fBCPAN::Bundle::get()\fR" 4 .IX Item "CPAN::Bundle::get()" Recursively runs the \f(CW\*(C`get\*(C'\fR method on all items contained in the bundle .IP "\fBCPAN::Bundle::inst_file()\fR" 4 .IX Item "CPAN::Bundle::inst_file()" Returns the highest installed version of the bundle in either \f(CW@INC\fR or \&\f(CW\*(C`$CPAN::Config\->{cpan_home}\*(C'\fR. Note that this is different from CPAN::Module::inst_file. .IP "\fBCPAN::Bundle::inst_version()\fR" 4 .IX Item "CPAN::Bundle::inst_version()" Like CPAN::Bundle::inst_file, but returns the \f(CW$VERSION\fR .IP "\fBCPAN::Bundle::uptodate()\fR" 4 .IX Item "CPAN::Bundle::uptodate()" Returns 1 if the bundle itself and all its members are up-to-date. .IP "\fBCPAN::Bundle::install()\fR" 4 .IX Item "CPAN::Bundle::install()" Recursively runs the \f(CW\*(C`install\*(C'\fR method on all items contained in the bundle .IP "\fBCPAN::Bundle::make()\fR" 4 .IX Item "CPAN::Bundle::make()" Recursively runs the \f(CW\*(C`make\*(C'\fR method on all items contained in the bundle .IP "\fBCPAN::Bundle::readme()\fR" 4 .IX Item "CPAN::Bundle::readme()" Recursively runs the \f(CW\*(C`readme\*(C'\fR method on all items contained in the bundle .IP "\fBCPAN::Bundle::test()\fR" 4 .IX Item "CPAN::Bundle::test()" Recursively runs the \f(CW\*(C`test\*(C'\fR method on all items contained in the bundle .IP "\fBCPAN::Distribution::as_glimpse()\fR" 4 .IX Item "CPAN::Distribution::as_glimpse()" Returns a one-line description of the distribution .IP "\fBCPAN::Distribution::as_string()\fR" 4 .IX Item "CPAN::Distribution::as_string()" Returns a multi-line description of the distribution .IP "CPAN::Distribution::author" 4 .IX Item "CPAN::Distribution::author" Returns the CPAN::Author object of the maintainer who uploaded this distribution .IP "\fBCPAN::Distribution::pretty_id()\fR" 4 .IX Item "CPAN::Distribution::pretty_id()" Returns a string of the form \*(L"\s-1AUTHORID/TARBALL\*(R",\s0 where \s-1AUTHORID\s0 is the author's \s-1PAUSE ID\s0 and \s-1TARBALL\s0 is the distribution filename. .IP "\fBCPAN::Distribution::base_id()\fR" 4 .IX Item "CPAN::Distribution::base_id()" Returns the distribution filename without any archive suffix. E.g \&\*(L"Foo\-Bar\-0.01\*(R" .IP "\fBCPAN::Distribution::clean()\fR" 4 .IX Item "CPAN::Distribution::clean()" Changes to the directory where the distribution has been unpacked and runs \f(CW\*(C`make clean\*(C'\fR there. .IP "\fBCPAN::Distribution::containsmods()\fR" 4 .IX Item "CPAN::Distribution::containsmods()" Returns a list of IDs of modules contained in a distribution file. Works only for distributions listed in the 02packages.details.txt.gz file. This typically means that just most recent version of a distribution is covered. .IP "\fBCPAN::Distribution::cvs_import()\fR" 4 .IX Item "CPAN::Distribution::cvs_import()" Changes to the directory where the distribution has been unpacked and runs something like .Sp .Vb 1 \& cvs \-d $cvs_root import \-m $cvs_log $cvs_dir $userid v$version .Ve .Sp there. .IP "\fBCPAN::Distribution::dir()\fR" 4 .IX Item "CPAN::Distribution::dir()" Returns the directory into which this distribution has been unpacked. .IP "CPAN::Distribution::force($method,@args)" 4 .IX Item "CPAN::Distribution::force($method,@args)" Forces \s-1CPAN\s0 to perform a task that it normally would have refused to do. Force takes as arguments a method name to be called and any number of additional arguments that should be passed to the called method. The internals of the object get the needed changes so that \s-1CPAN\s0.pm does not refuse to take the action. See also the section above on the \&\f(CW\*(C`force\*(C'\fR and the \f(CW\*(C`fforce\*(C'\fR pragma. .IP "\fBCPAN::Distribution::get()\fR" 4 .IX Item "CPAN::Distribution::get()" Downloads the distribution from \s-1CPAN\s0 and unpacks it. Does nothing if the distribution has already been downloaded and unpacked within the current session. .IP "\fBCPAN::Distribution::install()\fR" 4 .IX Item "CPAN::Distribution::install()" Changes to the directory where the distribution has been unpacked and runs the external command \f(CW\*(C`make install\*(C'\fR there. If \f(CW\*(C`make\*(C'\fR has not yet been run, it will be run first. A \f(CW\*(C`make test\*(C'\fR is issued in any case and if this fails, the install is cancelled. The cancellation can be avoided by letting \f(CW\*(C`force\*(C'\fR run the \f(CW\*(C`install\*(C'\fR for you. .Sp This install method only has the power to install the distribution if there are no dependencies in the way. To install an object along with all its dependencies, use CPAN::Shell\->install. .Sp Note that \fBinstall()\fR gives no meaningful return value. See \fBuptodate()\fR. .IP "\fBCPAN::Distribution::isa_perl()\fR" 4 .IX Item "CPAN::Distribution::isa_perl()" Returns 1 if this distribution file seems to be a perl distribution. Normally this is derived from the file name only, but the index from \&\s-1CPAN\s0 can contain a hint to achieve a return value of true for other filenames too. .IP "\fBCPAN::Distribution::look()\fR" 4 .IX Item "CPAN::Distribution::look()" Changes to the directory where the distribution has been unpacked and opens a subshell there. Exiting the subshell returns. .IP "\fBCPAN::Distribution::make()\fR" 4 .IX Item "CPAN::Distribution::make()" First runs the \f(CW\*(C`get\*(C'\fR method to make sure the distribution is downloaded and unpacked. Changes to the directory where the distribution has been unpacked and runs the external commands \f(CW\*(C`perl Makefile.PL\*(C'\fR or \f(CW\*(C`perl Build.PL\*(C'\fR and \f(CW\*(C`make\*(C'\fR there. .IP "\fBCPAN::Distribution::perldoc()\fR" 4 .IX Item "CPAN::Distribution::perldoc()" Downloads the pod documentation of the file associated with a distribution (in \s-1HTML\s0 format) and runs it through the external command \fIlynx\fR specified in \f(CW\*(C`$CPAN::Config\->{lynx}\*(C'\fR. If \fIlynx\fR isn't available, it converts it to plain text with the external command \fIhtml2text\fR and runs it through the pager specified in \f(CW\*(C`$CPAN::Config\->{pager}\*(C'\fR. .IP "\fBCPAN::Distribution::prefs()\fR" 4 .IX Item "CPAN::Distribution::prefs()" Returns the hash reference from the first matching \s-1YAML\s0 file that the user has deposited in the \f(CW\*(C`prefs_dir/\*(C'\fR directory. The first succeeding match wins. The files in the \f(CW\*(C`prefs_dir/\*(C'\fR are processed alphabetically, and the canonical distro name (e.g. AUTHOR/Foo\-Bar\-3.14.tar.gz) is matched against the regular expressions stored in the \f(CW$root\fR\->{match}{distribution} attribute value. Additionally all module names contained in a distribution are matched against the regular expressions in the \f(CW$root\fR\->{match}{module} attribute value. The two match values are ANDed together. Each of the two attributes are optional. .IP "\fBCPAN::Distribution::prereq_pm()\fR" 4 .IX Item "CPAN::Distribution::prereq_pm()" Returns the hash reference that has been announced by a distribution as the \f(CW\*(C`requires\*(C'\fR and \f(CW\*(C`build_requires\*(C'\fR elements. These can be declared either by the \f(CW\*(C`META.yml\*(C'\fR (if authoritative) or can be deposited after the run of \f(CW\*(C`Build.PL\*(C'\fR in the file \f(CW\*(C`./_build/prereqs\*(C'\fR or after the run of \f(CW\*(C`Makfile.PL\*(C'\fR written as the \f(CW\*(C`PREREQ_PM\*(C'\fR hash in a comment in the produced \f(CW\*(C`Makefile\*(C'\fR. \fINote\fR: this method only works after an attempt has been made to \f(CW\*(C`make\*(C'\fR the distribution. Returns undef otherwise. .IP "\fBCPAN::Distribution::readme()\fR" 4 .IX Item "CPAN::Distribution::readme()" Downloads the \s-1README\s0 file associated with a distribution and runs it through the pager specified in \f(CW\*(C`$CPAN::Config\->{pager}\*(C'\fR. .IP "\fBCPAN::Distribution::reports()\fR" 4 .IX Item "CPAN::Distribution::reports()" Downloads report data for this distribution from www.cpantesters.org and displays a subset of them. .IP "\fBCPAN::Distribution::read_yaml()\fR" 4 .IX Item "CPAN::Distribution::read_yaml()" Returns the content of the \s-1META\s0.yml of this distro as a hashref. Note: works only after an attempt has been made to \f(CW\*(C`make\*(C'\fR the distribution. Returns undef otherwise. Also returns undef if the content of \s-1META\s0.yml is not authoritative. (The rules about what exactly makes the content authoritative are still in flux.) .IP "\fBCPAN::Distribution::test()\fR" 4 .IX Item "CPAN::Distribution::test()" Changes to the directory where the distribution has been unpacked and runs \f(CW\*(C`make test\*(C'\fR there. .IP "\fBCPAN::Distribution::uptodate()\fR" 4 .IX Item "CPAN::Distribution::uptodate()" Returns 1 if all the modules contained in the distribution are up-to-date. Relies on containsmods. .IP "\fBCPAN::Index::force_reload()\fR" 4 .IX Item "CPAN::Index::force_reload()" Forces a reload of all indices. .IP "\fBCPAN::Index::reload()\fR" 4 .IX Item "CPAN::Index::reload()" Reloads all indices if they have not been read for more than \&\f(CW\*(C`$CPAN::Config\->{index_expire}\*(C'\fR days. .IP "\fBCPAN::InfoObj::dump()\fR" 4 .IX Item "CPAN::InfoObj::dump()" CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution inherit this method. It prints the data structure associated with an object. Useful for debugging. Note: the data structure is considered internal and thus subject to change without notice. .IP "\fBCPAN::Module::as_glimpse()\fR" 4 .IX Item "CPAN::Module::as_glimpse()" Returns a one-line description of the module in four columns: The first column contains the word \f(CW\*(C`Module\*(C'\fR, the second column consists of one character: an equals sign if this module is already installed and up-to-date, a less-than sign if this module is installed but can be upgraded, and a space if the module is not installed. The third column is the name of the module and the fourth column gives maintainer or distribution information. .IP "\fBCPAN::Module::as_string()\fR" 4 .IX Item "CPAN::Module::as_string()" Returns a multi-line description of the module .IP "\fBCPAN::Module::clean()\fR" 4 .IX Item "CPAN::Module::clean()" Runs a clean on the distribution associated with this module. .IP "\fBCPAN::Module::cpan_file()\fR" 4 .IX Item "CPAN::Module::cpan_file()" Returns the filename on \s-1CPAN\s0 that is associated with the module. .IP "\fBCPAN::Module::cpan_version()\fR" 4 .IX Item "CPAN::Module::cpan_version()" Returns the latest version of this module available on \s-1CPAN.\s0 .IP "\fBCPAN::Module::cvs_import()\fR" 4 .IX Item "CPAN::Module::cvs_import()" Runs a cvs_import on the distribution associated with this module. .IP "\fBCPAN::Module::description()\fR" 4 .IX Item "CPAN::Module::description()" Returns a 44 character description of this module. Only available for modules listed in The Module List (CPAN/modules/00modlist.long.html or 00modlist.long.txt.gz) .IP "\fBCPAN::Module::distribution()\fR" 4 .IX Item "CPAN::Module::distribution()" Returns the CPAN::Distribution object that contains the current version of this module. .IP "\fBCPAN::Module::dslip_status()\fR" 4 .IX Item "CPAN::Module::dslip_status()" Returns a hash reference. The keys of the hash are the letters \f(CW\*(C`D\*(C'\fR, \&\f(CW\*(C`S\*(C'\fR, \f(CW\*(C`L\*(C'\fR, \f(CW\*(C`I\*(C'\fR, and <P>, for development status, support level, language, interface and public licence respectively. The data for the \&\s-1DSLIP\s0 status are collected by pause.perl.org when authors register their namespaces. The values of the 5 hash elements are one-character words whose meaning is described in the table below. There are also 5 hash elements \f(CW\*(C`DV\*(C'\fR, \f(CW\*(C`SV\*(C'\fR, \f(CW\*(C`LV\*(C'\fR, \f(CW\*(C`IV\*(C'\fR, and <\s-1PV\s0> that carry a more verbose value of the 5 status variables. .Sp Where the '\s-1DSLIP\s0' characters have the following meanings: .Sp .Vb 7 \& D \- Development Stage (Note: *NO IMPLIED TIMESCALES*): \& i \- Idea, listed to gain consensus or as a placeholder \& c \- under construction but pre\-alpha (not yet released) \& a/b \- Alpha/Beta testing \& R \- Released \& M \- Mature (no rigorous definition) \& S \- Standard, supplied with Perl 5 \& \& S \- Support Level: \& m \- Mailing\-list \& d \- Developer \& u \- Usenet newsgroup comp.lang.perl.modules \& n \- None known, try comp.lang.perl.modules \& a \- abandoned; volunteers welcome to take over maintenance \& \& L \- Language Used: \& p \- Perl\-only, no compiler needed, should be platform independent \& c \- C and perl, a C compiler will be needed \& h \- Hybrid, written in perl with optional C code, no compiler needed \& + \- C++ and perl, a C++ compiler will be needed \& o \- perl and another language other than C or C++ \& \& I \- Interface Style \& f \- plain Functions, no references used \& h \- hybrid, object and function interfaces available \& n \- no interface at all (huh?) \& r \- some use of unblessed References or ties \& O \- Object oriented using blessed references and/or inheritance \& \& P \- Public License \& p \- Standard\-Perl: user may choose between GPL and Artistic \& g \- GPL: GNU General Public License \& l \- LGPL: "GNU Lesser General Public License" (previously known as \& "GNU Library General Public License") \& b \- BSD: The BSD License \& a \- Artistic license alone \& 2 \- Artistic license 2.0 or later \& o \- open source: approved by www.opensource.org \& d \- allows distribution without restrictions \& r \- restricted distribution \& n \- no license at all .Ve .IP "CPAN::Module::force($method,@args)" 4 .IX Item "CPAN::Module::force($method,@args)" Forces \s-1CPAN\s0 to perform a task it would normally refuse to do. Force takes as arguments a method name to be invoked and any number of additional arguments to pass that method. The internals of the object get the needed changes so that \s-1CPAN\s0.pm does not refuse to take the action. See also the section above on the \&\f(CW\*(C`force\*(C'\fR and the \f(CW\*(C`fforce\*(C'\fR pragma. .IP "\fBCPAN::Module::get()\fR" 4 .IX Item "CPAN::Module::get()" Runs a get on the distribution associated with this module. .IP "\fBCPAN::Module::inst_file()\fR" 4 .IX Item "CPAN::Module::inst_file()" Returns the filename of the module found in \f(CW@INC\fR. The first file found is reported, just as perl itself stops searching \f(CW@INC\fR once it finds a module. .IP "\fBCPAN::Module::available_file()\fR" 4 .IX Item "CPAN::Module::available_file()" Returns the filename of the module found in \s-1PERL5LIB\s0 or \f(CW@INC\fR. The first file found is reported. The advantage of this method over \&\f(CW\*(C`inst_file\*(C'\fR is that modules that have been tested but not yet installed are included because \s-1PERL5LIB\s0 keeps track of tested modules. .IP "\fBCPAN::Module::inst_version()\fR" 4 .IX Item "CPAN::Module::inst_version()" Returns the version number of the installed module in readable format. .IP "\fBCPAN::Module::available_version()\fR" 4 .IX Item "CPAN::Module::available_version()" Returns the version number of the available module in readable format. .IP "\fBCPAN::Module::install()\fR" 4 .IX Item "CPAN::Module::install()" Runs an \f(CW\*(C`install\*(C'\fR on the distribution associated with this module. .IP "\fBCPAN::Module::look()\fR" 4 .IX Item "CPAN::Module::look()" Changes to the directory where the distribution associated with this module has been unpacked and opens a subshell there. Exiting the subshell returns. .IP "\fBCPAN::Module::make()\fR" 4 .IX Item "CPAN::Module::make()" Runs a \f(CW\*(C`make\*(C'\fR on the distribution associated with this module. .IP "\fBCPAN::Module::manpage_headline()\fR" 4 .IX Item "CPAN::Module::manpage_headline()" If module is installed, peeks into the module's manpage, reads the headline, and returns it. Moreover, if the module has been downloaded within this session, does the equivalent on the downloaded module even if it hasn't been installed yet. .IP "\fBCPAN::Module::perldoc()\fR" 4 .IX Item "CPAN::Module::perldoc()" Runs a \f(CW\*(C`perldoc\*(C'\fR on this module. .IP "\fBCPAN::Module::readme()\fR" 4 .IX Item "CPAN::Module::readme()" Runs a \f(CW\*(C`readme\*(C'\fR on the distribution associated with this module. .IP "\fBCPAN::Module::reports()\fR" 4 .IX Item "CPAN::Module::reports()" Calls the \fBreports()\fR method on the associated distribution object. .IP "\fBCPAN::Module::test()\fR" 4 .IX Item "CPAN::Module::test()" Runs a \f(CW\*(C`test\*(C'\fR on the distribution associated with this module. .IP "\fBCPAN::Module::uptodate()\fR" 4 .IX Item "CPAN::Module::uptodate()" Returns 1 if the module is installed and up-to-date. .IP "\fBCPAN::Module::userid()\fR" 4 .IX Item "CPAN::Module::userid()" Returns the author's \s-1ID\s0 of the module. .SS "Cache Manager" .IX Subsection "Cache Manager" Currently the cache manager only keeps track of the build directory ($CPAN::Config\->{build_dir}). It is a simple \s-1FIFO\s0 mechanism that deletes complete directories below \f(CW\*(C`build_dir\*(C'\fR as soon as the size of all directories there gets bigger than \f(CW$CPAN::Config\fR\->{build_cache} (in \s-1MB\s0). The contents of this cache may be used for later re-installations that you intend to do manually, but will never be trusted by \s-1CPAN\s0 itself. This is due to the fact that the user might use these directories for building modules on different architectures. .PP There is another directory ($CPAN::Config\->{keep_source_where}) where the original distribution files are kept. This directory is not covered by the cache manager and must be controlled by the user. If you choose to have the same directory as build_dir and as keep_source_where directory, then your sources will be deleted with the same fifo mechanism. .SS "Bundles" .IX Subsection "Bundles" A bundle is just a perl module in the namespace Bundle:: that does not define any functions or methods. It usually only contains documentation. .PP It starts like a perl module with a package declaration and a \f(CW$VERSION\fR variable. After that the pod section looks like any other pod with the only difference being that \fIone special pod section\fR exists starting with (verbatim): .PP .Vb 1 \& =head1 CONTENTS .Ve .PP In this pod section each line obeys the format .PP .Vb 1 \& Module_Name [Version_String] [\- optional text] .Ve .PP The only required part is the first field, the name of a module (e.g. Foo::Bar, i.e. \fInot\fR the name of the distribution file). The rest of the line is optional. The comment part is delimited by a dash just as in the man page header. .PP The distribution of a bundle should follow the same convention as other distributions. .PP Bundles are treated specially in the \s-1CPAN\s0 package. If you say 'install Bundle::Tkkit' (assuming such a bundle exists), \s-1CPAN\s0 will install all the modules in the \s-1CONTENTS\s0 section of the pod. You can install your own Bundles locally by placing a conformant Bundle file somewhere into your \f(CW@INC\fR path. The \fBautobundle()\fR command which is available in the shell interface does that for you by including all currently installed modules in a snapshot bundle file. .SH "PREREQUISITES" .IX Header "PREREQUISITES" The \s-1CPAN\s0 program is trying to depend on as little as possible so the user can use it in hostile environment. It works better the more goodies the environment provides. For example if you try in the \s-1CPAN\s0 shell .PP .Vb 1 \& install Bundle::CPAN .Ve .PP or .PP .Vb 1 \& install Bundle::CPANxxl .Ve .PP you will find the shell more convenient than the bare shell before. .PP If you have a local mirror of \s-1CPAN\s0 and can access all files with \&\*(L"file:\*(R" URLs, then you only need a perl later than perl5.003 to run this module. Otherwise Net::FTP is strongly recommended. \s-1LWP\s0 may be required for non-UNIX systems, or if your nearest \s-1CPAN\s0 site is associated with a \s-1URL\s0 that is not \f(CW\*(C`ftp:\*(C'\fR. .PP If you have neither Net::FTP nor \s-1LWP,\s0 there is a fallback mechanism implemented for an external ftp command or for an external lynx command. .SH "UTILITIES" .IX Header "UTILITIES" .SS "Finding packages and \s-1VERSION\s0" .IX Subsection "Finding packages and VERSION" This module presumes that all packages on \s-1CPAN\s0 .IP "\(bu" 2 declare their \f(CW$VERSION\fR variable in an easy to parse manner. This prerequisite can hardly be relaxed because it consumes far too much memory to load all packages into the running program just to determine the \f(CW$VERSION\fR variable. Currently all programs that are dealing with version use something like this .Sp .Vb 2 \& perl \-MExtUtils::MakeMaker \-le \e \& \*(Aqprint MM\->parse_version(shift)\*(Aq filename .Ve .Sp If you are author of a package and wonder if your \f(CW$VERSION\fR can be parsed, please try the above method. .IP "\(bu" 2 come as compressed or gzipped tarfiles or as zip files and contain a \&\f(CW\*(C`Makefile.PL\*(C'\fR or \f(CW\*(C`Build.PL\*(C'\fR (well, we try to handle a bit more, but with little enthusiasm). .SS "Debugging" .IX Subsection "Debugging" Debugging this module is more than a bit complex due to interference from the software producing the indices on \s-1CPAN,\s0 the mirroring process on \s-1CPAN,\s0 packaging, configuration, synchronicity, and even (gasp!) due to bugs within the \s-1CPAN\s0.pm module itself. .PP For debugging the code of \s-1CPAN\s0.pm itself in interactive mode, some debugging aid can be turned on for most packages within \&\s-1CPAN\s0.pm with one of .IP "o debug package..." 2 .IX Item "o debug package..." sets debug mode for packages. .IP "o debug \-package..." 2 .IX Item "o debug -package..." unsets debug mode for packages. .IP "o debug all" 2 .IX Item "o debug all" turns debugging on for all packages. .IP "o debug number" 2 .IX Item "o debug number" .PP which sets the debugging packages directly. Note that \f(CW\*(C`o debug 0\*(C'\fR turns debugging off. .PP What seems a successful strategy is the combination of \f(CW\*(C`reload cpan\*(C'\fR and the debugging switches. Add a new debug statement while running in the shell and then issue a \f(CW\*(C`reload cpan\*(C'\fR and see the new debugging messages immediately without losing the current context. .PP \&\f(CW\*(C`o debug\*(C'\fR without an argument lists the valid package names and the current set of packages in debugging mode. \f(CW\*(C`o debug\*(C'\fR has built-in completion support. .PP For debugging of \s-1CPAN\s0 data there is the \f(CW\*(C`dump\*(C'\fR command which takes the same arguments as make/test/install and outputs each object's Data::Dumper dump. If an argument looks like a perl variable and contains one of \f(CW\*(C`$\*(C'\fR, \f(CW\*(C`@\*(C'\fR or \f(CW\*(C`%\*(C'\fR, it is \fBeval()\fRed and fed to Data::Dumper directly. .SS "Floppy, Zip, Offline Mode" .IX Subsection "Floppy, Zip, Offline Mode" \&\s-1CPAN\s0.pm works nicely without network access, too. If you maintain machines that are not networked at all, you should consider working with \f(CW\*(C`file:\*(C'\fR URLs. You'll have to collect your modules somewhere first. So you might use \s-1CPAN\s0.pm to put together all you need on a networked machine. Then copy the \f(CW$CPAN::Config\fR\->{keep_source_where} (but not \&\f(CW$CPAN::Config\fR\->{build_dir}) directory on a floppy. This floppy is kind of a personal \s-1CPAN. CPAN\s0.pm on the non-networked machines works nicely with this floppy. See also below the paragraph about CD-ROM support. .SS "Basic Utilities for Programmers" .IX Subsection "Basic Utilities for Programmers" .IP "has_inst($module)" 2 .IX Item "has_inst($module)" Returns true if the module is installed. Used to load all modules into the running \s-1CPAN\s0.pm that are considered optional. The config variable \&\f(CW\*(C`dontload_list\*(C'\fR intercepts the \f(CW\*(C`has_inst()\*(C'\fR call such that an optional module is not loaded despite being available. For example, the following command will prevent \f(CW\*(C`YAML.pm\*(C'\fR from being loaded: .Sp .Vb 1 \& cpan> o conf dontload_list push YAML .Ve .Sp See the source for details. .IP "use_inst($module)" 2 .IX Item "use_inst($module)" Similary to \fBhas_inst()\fR tries to load optional library but also dies if library is not available .IP "has_usable($module)" 2 .IX Item "has_usable($module)" Returns true if the module is installed and in a usable state. Only useful for a handful of modules that are used internally. See the source for details. .IP "instance($module)" 2 .IX Item "instance($module)" The constructor for all the singletons used to represent modules, distributions, authors, and bundles. If the object already exists, this method returns the object; otherwise, it calls the constructor. .IP "\fBfrontend()\fR" 2 .IX Item "frontend()" .PD 0 .IP "frontend($new_frontend)" 2 .IX Item "frontend($new_frontend)" .PD Getter/setter for frontend object. Method just allows to subclass \s-1CPAN\s0.pm. .SH "SECURITY" .IX Header "SECURITY" There's no strong security layer in \s-1CPAN\s0.pm. \s-1CPAN\s0.pm helps you to install foreign, unmasked, unsigned code on your machine. We compare to a checksum that comes from the net just as the distribution file itself. But we try to make it easy to add security on demand: .SS "Cryptographically signed modules" .IX Subsection "Cryptographically signed modules" Since release 1.77, \s-1CPAN\s0.pm has been able to verify cryptographically signed module distributions using Module::Signature. The \s-1CPAN\s0 modules can be signed by their authors, thus giving more security. The simple unsigned \s-1MD5\s0 checksums that were used before by \s-1CPAN\s0 protect mainly against accidental file corruption. .PP You will need to have Module::Signature installed, which in turn requires that you have at least one of Crypt::OpenPGP module or the command-line \fIgpg\fR tool installed. .PP You will also need to be able to connect over the Internet to the public key servers, like pgp.mit.edu, and their port 11731 (the \s-1HKP\s0 protocol). .PP The configuration parameter check_sigs is there to turn signature checking on or off. .SH "EXPORT" .IX Header "EXPORT" Most functions in package \s-1CPAN\s0 are exported by default. The reason for this is that the primary use is intended for the cpan shell or for one-liners. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" When the \s-1CPAN\s0 shell enters a subshell via the look command, it sets the environment \s-1CPAN_SHELL_LEVEL\s0 to 1, or increments that variable if it is already set. .PP When \s-1CPAN\s0 runs, it sets the environment variable \s-1PERL5_CPAN_IS_RUNNING\s0 to the \s-1ID\s0 of the running process. It also sets \&\s-1PERL5_CPANPLUS_IS_RUNNING\s0 to prevent runaway processes which could happen with older versions of Module::Install. .PP When running \f(CW\*(C`perl Makefile.PL\*(C'\fR, the environment variable \&\f(CW\*(C`PERL5_CPAN_IS_EXECUTING\*(C'\fR is set to the full path of the \&\f(CW\*(C`Makefile.PL\*(C'\fR that is being executed. This prevents runaway processes with newer versions of Module::Install. .PP When the config variable ftp_passive is set, all downloads will be run with the environment variable \s-1FTP_PASSIVE\s0 set to this value. This is in general a good idea as it influences both Net::FTP and \s-1LWP\s0 based connections. The same effect can be achieved by starting the cpan shell with this environment variable set. For Net::FTP alone, one can also always set passive mode by running libnetcfg. .SH "POPULATE AN INSTALLATION WITH LOTS OF MODULES" .IX Header "POPULATE AN INSTALLATION WITH LOTS OF MODULES" Populating a freshly installed perl with one's favorite modules is pretty easy if you maintain a private bundle definition file. To get a useful blueprint of a bundle definition file, the command autobundle can be used on the \s-1CPAN\s0 shell command line. This command writes a bundle definition file for all modules installed for the current perl interpreter. It's recommended to run this command once only, and from then on maintain the file manually under a private name, say Bundle/my_bundle.pm. With a clever bundle file you can then simply say .PP .Vb 1 \& cpan> install Bundle::my_bundle .Ve .PP then answer a few questions and go out for coffee (possibly even in a different city). .PP Maintaining a bundle definition file means keeping track of two things: dependencies and interactivity. \s-1CPAN\s0.pm sometimes fails on calculating dependencies because not all modules define all MakeMaker attributes correctly, so a bundle definition file should specify prerequisites as early as possible. On the other hand, it's annoying that so many distributions need some interactive configuring. So what you can try to accomplish in your private bundle file is to have the packages that need to be configured early in the file and the gentle ones later, so you can go out for coffee after a few minutes and leave \s-1CPAN\s0.pm to churn away unattended. .SH "WORKING WITH CPAN.pm BEHIND FIREWALLS" .IX Header "WORKING WITH CPAN.pm BEHIND FIREWALLS" Thanks to Graham Barr for contributing the following paragraphs about the interaction between perl, and various firewall configurations. For further information on firewalls, it is recommended to consult the documentation that comes with the \fIncftp\fR program. If you are unable to go through the firewall with a simple Perl setup, it is likely that you can configure \fIncftp\fR so that it works through your firewall. .SS "Three basic types of firewalls" .IX Subsection "Three basic types of firewalls" Firewalls can be categorized into three basic types. .IP "http firewall" 4 .IX Item "http firewall" This is when the firewall machine runs a web server, and to access the outside world, you must do so via that web server. If you set environment variables like http_proxy or ftp_proxy to values beginning with http://, or in your web browser you've proxy information set, then you know you are running behind an http firewall. .Sp To access servers outside these types of firewalls with perl (even for ftp), you need \s-1LWP\s0 or HTTP::Tiny. .IP "ftp firewall" 4 .IX Item "ftp firewall" This where the firewall machine runs an ftp server. This kind of firewall will only let you access ftp servers outside the firewall. This is usually done by connecting to the firewall with ftp, then entering a username like \*(L"user@outside.host.com\*(R". .Sp To access servers outside these type of firewalls with perl, you need Net::FTP. .IP "One-way visibility" 4 .IX Item "One-way visibility" One-way visibility means these firewalls try to make themselves invisible to users inside the firewall. An \s-1FTP\s0 data connection is normally created by sending your \s-1IP\s0 address to the remote server and then listening for the return connection. But the remote server will not be able to connect to you because of the firewall. For these types of firewall, \&\s-1FTP\s0 connections need to be done in a passive mode. .Sp There are two that I can think off. .RS 4 .IP "\s-1SOCKS\s0" 4 .IX Item "SOCKS" If you are using a \s-1SOCKS\s0 firewall, you will need to compile perl and link it with the \s-1SOCKS\s0 library. This is what is normally called a 'socksified' perl. With this executable you will be able to connect to servers outside the firewall as if it were not there. .IP "\s-1IP\s0 Masquerade" 4 .IX Item "IP Masquerade" This is when the firewall implemented in the kernel (via \s-1NAT,\s0 or networking address translation), it allows you to hide a complete network behind one \&\s-1IP\s0 address. With this firewall no special compiling is needed as you can access hosts directly. .Sp For accessing ftp servers behind such firewalls you usually need to set the environment variable \f(CW\*(C`FTP_PASSIVE\*(C'\fR or the config variable ftp_passive to a true value. .RE .RS 4 .RE .SS "Configuring lynx or ncftp for going through a firewall" .IX Subsection "Configuring lynx or ncftp for going through a firewall" If you can go through your firewall with e.g. lynx, presumably with a command such as .PP .Vb 1 \& /usr/local/bin/lynx \-pscott:tiger .Ve .PP then you would configure \s-1CPAN\s0.pm with the command .PP .Vb 1 \& o conf lynx "/usr/local/bin/lynx \-pscott:tiger" .Ve .PP That's all. Similarly for ncftp or ftp, you would configure something like .PP .Vb 1 \& o conf ncftp "/usr/bin/ncftp \-f /home/scott/ncftplogin.cfg" .Ve .PP Your mileage may vary... .SH "FAQ" .IX Header "FAQ" .IP "1)" 4 .IX Item "1)" I installed a new version of module X but \s-1CPAN\s0 keeps saying, I have the old version installed .Sp Probably you \fBdo\fR have the old version installed. This can happen if a module installs itself into a different directory in the \&\f(CW@INC\fR path than it was previously installed. This is not really a \&\s-1CPAN\s0.pm problem, you would have the same problem when installing the module manually. The easiest way to prevent this behaviour is to add the argument \f(CW\*(C`UNINST=1\*(C'\fR to the \f(CW\*(C`make install\*(C'\fR call, and that is why many people add this argument permanently by configuring .Sp .Vb 1 \& o conf make_install_arg UNINST=1 .Ve .IP "2)" 4 .IX Item "2)" So why is UNINST=1 not the default? .Sp Because there are people who have their precise expectations about who may install where in the \f(CW@INC\fR path and who uses which \f(CW@INC\fR array. In fine tuned environments \f(CW\*(C`UNINST=1\*(C'\fR can cause damage. .IP "3)" 4 .IX Item "3)" I want to clean up my mess, and install a new perl along with all modules I have. How do I go about it? .Sp Run the autobundle command for your old perl and optionally rename the resulting bundle file (e.g. Bundle/mybundle.pm), install the new perl with the Configure option prefix, e.g. .Sp .Vb 1 \& ./Configure \-Dprefix=/usr/local/perl\-5.6.78.9 .Ve .Sp Install the bundle file you produced in the first step with something like .Sp .Vb 1 \& cpan> install Bundle::mybundle .Ve .Sp and you're done. .IP "4)" 4 .IX Item "4)" When I install bundles or multiple modules with one command there is too much output to keep track of. .Sp You may want to configure something like .Sp .Vb 2 \& o conf make_arg "| tee \-ai /root/.cpan/logs/make.out" \& o conf make_install_arg "| tee \-ai /root/.cpan/logs/make_install.out" .Ve .Sp so that \s-1STDOUT\s0 is captured in a file for later inspection. .IP "5)" 4 .IX Item "5)" I am not root, how can I install a module in a personal directory? .Sp As of \s-1CPAN 1.9463,\s0 if you do not have permission to write the default perl library directories, \s-1CPAN\s0's configuration process will ask you whether you want to bootstrap <local::lib>, which makes keeping a personal perl library directory easy. .Sp Another thing you should bear in mind is that the \s-1UNINST\s0 parameter can be dangerous when you are installing into a private area because you might accidentally remove modules that other people depend on that are not using the private area. .IP "6)" 4 .IX Item "6)" How to get a package, unwrap it, and make a change before building it? .Sp Have a look at the \f(CW\*(C`look\*(C'\fR (!) command. .IP "7)" 4 .IX Item "7)" I installed a Bundle and had a couple of fails. When I retried, everything resolved nicely. Can this be fixed to work on first try? .Sp The reason for this is that \s-1CPAN\s0 does not know the dependencies of all modules when it starts out. To decide about the additional items to install, it just uses data found in the \s-1META\s0.yml file or the generated Makefile. An undetected missing piece breaks the process. But it may well be that your Bundle installs some prerequisite later than some depending item and thus your second try is able to resolve everything. Please note, \s-1CPAN\s0.pm does not know the dependency tree in advance and cannot sort the queue of things to install in a topologically correct order. It resolves perfectly well \fBif\fR all modules declare the prerequisites correctly with the \s-1PREREQ_PM\s0 attribute to MakeMaker or the \f(CW\*(C`requires\*(C'\fR stanza of Module::Build. For bundles which fail and you need to install often, it is recommended to sort the Bundle definition file manually. .IP "8)" 4 .IX Item "8)" In our intranet, we have many modules for internal use. How can I integrate these modules with \s-1CPAN\s0.pm but without uploading the modules to \s-1CPAN\s0? .Sp Have a look at the CPAN::Site module. .IP "9)" 4 .IX Item "9)" When I run \s-1CPAN\s0's shell, I get an error message about things in my \&\f(CW\*(C`/etc/inputrc\*(C'\fR (or \f(CW\*(C`~/.inputrc\*(C'\fR) file. .Sp These are readline issues and can only be fixed by studying readline configuration on your architecture and adjusting the referenced file accordingly. Please make a backup of the \f(CW\*(C`/etc/inputrc\*(C'\fR or \f(CW\*(C`~/.inputrc\*(C'\fR and edit them. Quite often harmless changes like uppercasing or lowercasing some arguments solves the problem. .IP "10)" 4 .IX Item "10)" Some authors have strange characters in their names. .Sp Internally \s-1CPAN\s0.pm uses the \s-1UTF\-8\s0 charset. If your terminal is expecting \s-1ISO\-8859\-1\s0 charset, a converter can be activated by setting term_is_latin to a true value in your config file. One way of doing so would be .Sp .Vb 1 \& cpan> o conf term_is_latin 1 .Ve .Sp If other charset support is needed, please file a bug report against \&\s-1CPAN\s0.pm at rt.cpan.org and describe your needs. Maybe we can extend the support or maybe \s-1UTF\-8\s0 terminals become widely available. .Sp Note: this config variable is deprecated and will be removed in a future version of \s-1CPAN\s0.pm. It will be replaced with the conventions around the family of \f(CW$LANG\fR and \f(CW$LC_\fR* environment variables. .IP "11)" 4 .IX Item "11)" When an install fails for some reason and then I correct the error condition and retry, \s-1CPAN\s0.pm refuses to install the module, saying \&\f(CW\*(C`Already tried without success\*(C'\fR. .Sp Use the force pragma like so .Sp .Vb 1 \& force install Foo::Bar .Ve .Sp Or you can use .Sp .Vb 1 \& look Foo::Bar .Ve .Sp and then \f(CW\*(C`make install\*(C'\fR directly in the subshell. .IP "12)" 4 .IX Item "12)" How do I install a \*(L"\s-1DEVELOPER RELEASE\*(R"\s0 of a module? .Sp By default, \s-1CPAN\s0 will install the latest non-developer release of a module. If you want to install a dev release, you have to specify the partial path starting with the author id to the tarball you wish to install, like so: .Sp .Vb 1 \& cpan> install KWILLIAMS/Module\-Build\-0.27_07.tar.gz .Ve .Sp Note that you can use the \f(CW\*(C`ls\*(C'\fR command to get this path listed. .IP "13)" 4 .IX Item "13)" How do I install a module and all its dependencies from the commandline, without being prompted for anything, despite my \s-1CPAN\s0 configuration (or lack thereof)? .Sp \&\s-1CPAN\s0 uses ExtUtils::MakeMaker's \fBprompt()\fR function to ask its questions, so if you set the \s-1PERL_MM_USE_DEFAULT\s0 environment variable, you shouldn't be asked any questions at all (assuming the modules you are installing are nice about obeying that variable as well): .Sp .Vb 1 \& % PERL_MM_USE_DEFAULT=1 perl \-MCPAN \-e \*(Aqinstall My::Module\*(Aq .Ve .IP "14)" 4 .IX Item "14)" How do I create a Module::Build based Build.PL derived from an ExtUtils::MakeMaker focused Makefile.PL? .Sp http://search.cpan.org/dist/Module\-Build\-Convert/ .IP "15)" 4 .IX Item "15)" I'm frequently irritated with the \s-1CPAN\s0 shell's inability to help me select a good mirror. .Sp \&\s-1CPAN\s0 can now help you select a \*(L"good\*(R" mirror, based on which ones have the lowest 'ping' round-trip times. From the shell, use the command 'o conf init urllist' and allow \s-1CPAN\s0 to automatically select mirrors for you. .Sp Beyond that help, the urllist config parameter is yours. You can add and remove sites at will. You should find out which sites have the best up-to-dateness, bandwidth, reliability, etc. and are topologically close to you. Some people prefer fast downloads, others up-to-dateness, others reliability. You decide which to try in which order. .Sp Henk P. Penning maintains a site that collects data about \s-1CPAN\s0 sites: .Sp .Vb 1 \& http://mirrors.cpan.org/ .Ve .Sp Also, feel free to play with experimental features. Run .Sp .Vb 1 \& o conf init randomize_urllist ftpstats_period ftpstats_size .Ve .Sp and choose your favorite parameters. After a few downloads running the \&\f(CW\*(C`hosts\*(C'\fR command will probably assist you in choosing the best mirror sites. .IP "16)" 4 .IX Item "16)" Why do I get asked the same questions every time I start the shell? .Sp You can make your configuration changes permanent by calling the command \f(CW\*(C`o conf commit\*(C'\fR. Alternatively set the \f(CW\*(C`auto_commit\*(C'\fR variable to true by running \f(CW\*(C`o conf init auto_commit\*(C'\fR and answering the following question with yes. .IP "17)" 4 .IX Item "17)" Older versions of \s-1CPAN\s0.pm had the original root directory of all tarballs in the build directory. Now there are always random characters appended to these directory names. Why was this done? .Sp The random characters are provided by File::Temp and ensure that each module's individual build directory is unique. This makes running \&\s-1CPAN\s0.pm in concurrent processes simultaneously safe. .IP "18)" 4 .IX Item "18)" Speaking of the build directory. Do I have to clean it up myself? .Sp You have the choice to set the config variable \f(CW\*(C`scan_cache\*(C'\fR to \&\f(CW\*(C`never\*(C'\fR. Then you must clean it up yourself. The other possible values, \f(CW\*(C`atstart\*(C'\fR and \f(CW\*(C`atexit\*(C'\fR clean up the build directory when you start (or more precisely, after the first extraction into the build directory) or exit the \s-1CPAN\s0 shell, respectively. If you never start up the \s-1CPAN\s0 shell, you probably also have to clean up the build directory yourself. .IP "19)" 4 .IX Item "19)" How can I switch to sudo instead of local::lib? .Sp The following 5 environment veriables need to be reset to the previous values: \s-1PATH, PERL5LIB, PERL_LOCAL_LIB_ROOT, PERL_MB_OPT, PERL_MM_OPT\s0; and these two \s-1CPAN\s0.pm config variables must be reconfigured: make_install_make_command and mbuild_install_build_command. The five env variables have probably been overwritten in your \f(CW$HOME\fR/.bashrc or some equivalent. You either find them there and delete their traces and logout/login or you override them temporarily, depending on your exact desire. The two cpanpm config variables can be set with: .Sp .Vb 1 \& o conf init /install_.*_command/ .Ve .Sp probably followed by .Sp .Vb 1 \& o conf commit .Ve .SH "COMPATIBILITY" .IX Header "COMPATIBILITY" .SS "\s-1OLD PERL VERSIONS\s0" .IX Subsection "OLD PERL VERSIONS" \&\s-1CPAN\s0.pm is regularly tested to run under 5.005 and assorted newer versions. It is getting more and more difficult to get the minimal prerequisites working on older perls. It is close to impossible to get the whole Bundle::CPAN working there. If you're in the position to have only these old versions, be advised that \s-1CPAN\s0 is designed to work fine without the Bundle::CPAN installed. .PP To get things going, note that GBARR/Scalar\-List\-Utils\-1.18.tar.gz is compatible with ancient perls and that File::Temp is listed as a prerequisite but \s-1CPAN\s0 has reasonable workarounds if it is missing. .SS "\s-1CPANPLUS\s0" .IX Subsection "CPANPLUS" This module and its competitor, the \s-1CPANPLUS\s0 module, are both much cooler than the other. \s-1CPAN\s0.pm is older. \s-1CPANPLUS\s0 was designed to be more modular, but it was never intended to be compatible with \s-1CPAN\s0.pm. .SS "\s-1CPANMINUS\s0" .IX Subsection "CPANMINUS" In the year 2010 App::cpanminus was launched as a new approach to a cpan shell with a considerably smaller footprint. Very cool stuff. .SH "SECURITY ADVICE" .IX Header "SECURITY ADVICE" This software enables you to upgrade software on your computer and so is inherently dangerous because the newly installed software may contain bugs and may alter the way your computer works or even make it unusable. Please consider backing up your data before every upgrade. .SH "BUGS" .IX Header "BUGS" Please report bugs via <http://rt.cpan.org/> .PP Before submitting a bug, please make sure that the traditional method of building a Perl module package from a shell by following the installation instructions of that package still works in your environment. .SH "AUTHOR" .IX Header "AUTHOR" Andreas Koenig \f(CW\*(C`<andk@cpan.org>\*(C'\fR .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP See <http://www.perl.com/perl/misc/Artistic.html> .SH "TRANSLATIONS" .IX Header "TRANSLATIONS" Kawai,Takanori provides a Japanese translation of a very old version of this manpage at <http://homepage3.nifty.com/hippo2000/perltips/CPAN.htm> .SH "SEE ALSO" .IX Header "SEE ALSO" Many people enter the \s-1CPAN\s0 shell by running the cpan utility program which is installed in the same directory as perl itself. So if you have this directory in your \s-1PATH\s0 variable (or some equivalent in your operating system) then typing \f(CW\*(C`cpan\*(C'\fR in a console window will work for you as well. Above that the utility provides several commandline shortcuts. .PP melezhik (Alexey) sent me a link where he published a chef recipe to work with \s-1CPAN\s0.pm: http://community.opscode.com/cookbooks/cpan. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/JSON::Syck.3pm�����������������������������������������������������������������������������0000444�����������������00000017632�15253012307�0010372 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 (<http://redhanded.hobix.com/inspect/yamlIsJson.html>), 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 <http://idisk.mac.com/christian.hansen/Public/perl/serialize.pl> .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 <cpan@audreyt.org> .PP Tatsuhiko Miyagawa <miyagawa@gmail.com> .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright 2005\-2009 by Audrey Tang <cpan@audreyt.org>. .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/JSON::XS.3pm�������������������������������������������������������������������������������0000444�����������������00000255675�15253012307�0010026 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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", \& "Hello<TAB>World", # literal <TAB> 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<allow_nonref>. .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_\|_" => <id> }\*(C'\fR into the corresponding \f(CW$WIDGET{<id>}\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, "<bigfile.json" \& or die "bigfile: $!"; \& \& # first parse the initial "[" \& for (;;) { \& sysread $fh, my $buf, 65536 \& or die "read error: $!"; \& $json\->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 <http://dist.schmorp.de/misc/json/short.json>). .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 (<http://dist.schmorp.de/misc/json/long.json>). .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 <http://blog.archive.jpsykes.com/47/practical\-csrf\-and\-json\-security/> 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 <schmorp@schmorp.de> \& http://home.schmorp.de/ .Ve �������������������������������������������������������������������man/man3/IO::Tty::Constant.3pm����������������������������������������������������������������������0000444�����������������00000022756�15253012307�0011700 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2024-03-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" 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 <termio.h> or <termios.h> (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/CPAN::HandleConfig.3pm���������������������������������������������������������������������0000444�����������������00000006367�15253012307�0011755 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::HandleConfig 3" .TH CPAN::HandleConfig 3 "2022-04-03" "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" CPAN::HandleConfig \- internal configuration handling for CPAN.pm .ie n .SS """CLASS\->safe_quote ITEM""" .el .SS "\f(CWCLASS\->safe_quote ITEM\fP" .IX Subsection "CLASS->safe_quote ITEM" Quotes an item to become safe against spaces in shell interpolation. An item is enclosed in double quotes if: .PP .Vb 2 \& \- the item contains spaces in the middle \& \- the item does not start with a quote .Ve .PP This happens to avoid shell interpolation problems when whitespace is present in directory names. .PP This method uses \f(CW\*(C`commands_quote\*(C'\fR to determine the correct quote. If \f(CW\*(C`commands_quote\*(C'\fR is a space, no quoting will take place. .PP if it starts and ends with the same quote character: leave it as it is .PP if it contains no whitespace: leave it as it is .PP if it contains whitespace, then .PP if it contains quotes: better leave it as it is .PP else: quote it with the correct quote type for the box we're on .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/Expect.3pm���������������������������������������������������������������������������������0000444�����������������00000166514�15253012307�0010037 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2024-03-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" 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 <http://code-maven.com/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 <space><backspace> 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, use a regexp object (\f(CW\*(C`qr//\*(C'\fR) or prefix the pattern with '\-re'. .Sp .Vb 2 \& $object\->expect(15, \*(Aqmatch me exactly\*(Aq, qr/match\es+me\es+exactly/); \& $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. If you don't want to explicitly put the timeout on all calls to \f(CW\*(C`expect\*(C'\fR, you can set it via the \f(CW\*(C`timeout\*(C'\fR method . If the first argument of \f(CW\*(C`expect\*(C'\fR doesn't look like a number, that value will be used. .Sp .Vb 2 \& $object\->timeout(15); \& $object\->expect(\*(Aqmatch me exactly\*(Aq,\*(Aq\-re\*(Aq,\*(Aqmatch\es+me\es+exactly\*(Aq); .Ve .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 <leakin@japh.itg.ti.com> has ported the kibitz script from Tcl/Expect to Perl/Expect. .PP Jeff Carr <jcarr@linuxmachines.com> 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 <Eric.Arnold@Sun.com> and Randal 'Nuke your \s-1NT\s0 box with one line of perl code' Schwartz<merlyn@stonehenge.com> 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 <rogaski@att.com> 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" <http://sourceforge.net/projects/expectperl/> though the source code is now in GitHub: <https://github.com/jacoby/expect.pm> .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/IO::Pty.3pm��������������������������������������������������������������������������������0000444�����������������00000020577�15253012307�0007775 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2023-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" IO::Pty \- Pseudo TTY object class .SH "VERSION" .IX Header "VERSION" 1.20 .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 <ylo@cs.hut.fi>, Markus Friedl and Todd C. Miller <Todd.Miller@courtesan.com>. .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/App::Cpan.3pm������������������������������������������������������������������������������0000444�����������������00000031307�15253012307�0010304 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "App::Cpan 3" .TH App::Cpan 3 "2022-04-03" "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" App::Cpan \- easily interact with CPAN from the command line .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # with arguments and no switches, installs specified modules \& cpan module_name [ module_name ... ] \& \& # with switches, installs modules with extra behavior \& cpan [\-cfFimtTw] module_name [ module_name ... ] \& \& # use local::lib \& cpan \-I module_name [ module_name ... ] \& \& # one time mirror override for faster mirrors \& cpan \-p ... \& \& # with just the dot, install from the distribution in the \& # current directory \& cpan . \& \& # without arguments, starts CPAN.pm shell \& cpan \& \& # without arguments, but some switches \& cpan [\-ahpruvACDLOPX] .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This script provides a command interface (not a shell) to \s-1CPAN.\s0 At the moment it uses \s-1CPAN\s0.pm to do the work, but it is not a one-shot command runner for \s-1CPAN\s0.pm. .SS "Options" .IX Subsection "Options" .IP "\-a" 4 .IX Item "-a" Creates a \s-1CPAN\s0.pm autobundle with CPAN::Shell\->autobundle. .IP "\-A module [ module ... ]" 4 .IX Item "-A module [ module ... ]" Shows the primary maintainers for the specified modules. .IP "\-c module" 4 .IX Item "-c module" Runs a `make clean` in the specified module's directories. .IP "\-C module [ module ... ]" 4 .IX Item "-C module [ module ... ]" Show the \fIChanges\fR files for the specified modules .IP "\-D module [ module ... ]" 4 .IX Item "-D module [ module ... ]" Show the module details. This prints one line for each out-of-date module (meaning, modules locally installed but have newer versions on \s-1CPAN\s0). Each line has three columns: module name, local version, and \s-1CPAN\s0 version. .IP "\-f" 4 .IX Item "-f" Force the specified action, when it normally would have failed. Use this to install a module even if its tests fail. When you use this option, \&\-i is not optional for installing a module when you need to force it: .Sp .Vb 1 \& % cpan \-f \-i Module::Foo .Ve .IP "\-F" 4 .IX Item "-F" Turn off \s-1CPAN\s0.pm's attempts to lock anything. You should be careful with this since you might end up with multiple scripts trying to muck in the same directory. This isn't so much of a concern if you're loading a special config with \f(CW\*(C`\-j\*(C'\fR, and that config sets up its own work directories. .IP "\-g module [ module ... ]" 4 .IX Item "-g module [ module ... ]" Downloads to the current directory the latest distribution of the module. .IP "\-G module [ module ... ]" 4 .IX Item "-G module [ module ... ]" \&\s-1UNIMPLEMENTED\s0 .Sp Download to the current directory the latest distribution of the modules, unpack each distribution, and create a git repository for each distribution. .Sp If you want this feature, check out Yanick Champoux's \f(CW\*(C`Git::CPAN::Patch\*(C'\fR distribution. .IP "\-h" 4 .IX Item "-h" Print a help message and exit. When you specify \f(CW\*(C`\-h\*(C'\fR, it ignores all of the other options and arguments. .IP "\-i module [ module ... ]" 4 .IX Item "-i module [ module ... ]" Install the specified modules. With no other switches, this switch is implied. .IP "\-I" 4 .IX Item "-I" Load \f(CW\*(C`local::lib\*(C'\fR (think like \f(CW\*(C`\-I\*(C'\fR for loading lib paths). Too bad \&\f(CW\*(C`\-l\*(C'\fR was already taken. .IP "\-j Config.pm" 4 .IX Item "-j Config.pm" Load the file that has the \s-1CPAN\s0 configuration data. This should have the same format as the standard \fICPAN/Config.pm\fR file, which defines \&\f(CW$CPAN::Config\fR as an anonymous hash. .Sp If the file does not exist, \f(CW\*(C`cpan\*(C'\fR dies. .IP "\-J" 4 .IX Item "-J" Dump the configuration in the same format that \s-1CPAN\s0.pm uses. This is useful for checking the configuration as well as using the dump as a starting point for a new, custom configuration. .IP "\-l" 4 .IX Item "-l" List all installed modules with their versions .IP "\-L author [ author ... ]" 4 .IX Item "-L author [ author ... ]" List the modules by the specified authors. .IP "\-m" 4 .IX Item "-m" Make the specified modules. .IP "\-M mirror1,mirror2,..." 4 .IX Item "-M mirror1,mirror2,..." A comma-separated list of mirrors to use for just this run. The \f(CW\*(C`\-P\*(C'\fR option can find them for you automatically. .IP "\-n" 4 .IX Item "-n" Do a dry run, but don't actually install anything. (unimplemented) .IP "\-O" 4 .IX Item "-O" Show the out-of-date modules. .IP "\-p" 4 .IX Item "-p" Ping the configured mirrors and print a report .IP "\-P" 4 .IX Item "-P" Find the best mirrors you could be using and use them for the current session. .IP "\-r" 4 .IX Item "-r" Recompiles dynamically loaded modules with CPAN::Shell\->recompile. .IP "\-s" 4 .IX Item "-s" Drop in the \s-1CPAN\s0.pm shell. This command does this automatically if you don't specify any arguments. .IP "\-t module [ module ... ]" 4 .IX Item "-t module [ module ... ]" Run a `make test` on the specified modules. .IP "\-T" 4 .IX Item "-T" Do not test modules. Simply install them. .IP "\-u" 4 .IX Item "-u" Upgrade all installed modules. Blindly doing this can really break things, so keep a backup. .IP "\-v" 4 .IX Item "-v" Print the script version and \s-1CPAN\s0.pm version then exit. .IP "\-V" 4 .IX Item "-V" Print detailed information about the cpan client. .IP "\-w" 4 .IX Item "-w" \&\s-1UNIMPLEMENTED\s0 .Sp Turn on cpan warnings. This checks various things, like directory permissions, and tells you about problems you might have. .IP "\-x module [ module ... ]" 4 .IX Item "-x module [ module ... ]" Find close matches to the named modules that you think you might have mistyped. This requires the optional installation of Text::Levenshtein or Text::Levenshtein::Damerau. .IP "\-X" 4 .IX Item "-X" Dump all the namespaces to standard output. .SS "Examples" .IX Subsection "Examples" .Vb 2 \& # print a help message \& cpan \-h \& \& # print the version numbers \& cpan \-v \& \& # create an autobundle \& cpan \-a \& \& # recompile modules \& cpan \-r \& \& # upgrade all installed modules \& cpan \-u \& \& # install modules ( sole \-i is optional ) \& cpan \-i Netscape::Booksmarks Business::ISBN \& \& # force install modules ( must use \-i ) \& cpan \-fi CGI::Minimal URI \& \& # install modules but without testing them \& cpan \-Ti CGI::Minimal URI .Ve .SS "Environment variables" .IX Subsection "Environment variables" There are several components in \s-1CPAN\s0.pm that use environment variables. The build tools, ExtUtils::MakeMaker and Module::Build use some, while others matter to the levels above them. Some of these are specified by the Perl Toolchain Gang: .PP Lancaster Consensus: <https://github.com/Perl\-Toolchain\-Gang/toolchain\-site/blob/master/lancaster\-consensus.md> .PP Oslo Consensus: <https://github.com/Perl\-Toolchain\-Gang/toolchain\-site/blob/master/oslo\-consensus.md> .IP "\s-1NONINTERACTIVE_TESTING\s0" 4 .IX Item "NONINTERACTIVE_TESTING" Assume no one is paying attention and skips prompts for distributions that do that correctly. \f(CWcpan(1)\fR sets this to \f(CW1\fR unless it already has a value (even if that value is false). .IP "\s-1PERL_MM_USE_DEFAULT\s0" 4 .IX Item "PERL_MM_USE_DEFAULT" Use the default answer for a prompted questions. \f(CWcpan(1)\fR sets this to \f(CW1\fR unless it already has a value (even if that value is false). .IP "\s-1CPAN_OPTS\s0" 4 .IX Item "CPAN_OPTS" As with \f(CW\*(C`PERL5OPT\*(C'\fR, a string of additional \f(CWcpan(1)\fR options to add to those you specify on the command line. .IP "\s-1CPANSCRIPT_LOGLEVEL\s0" 4 .IX Item "CPANSCRIPT_LOGLEVEL" The log level to use, with either the embedded, minimal logger or Log::Log4perl if it is installed. Possible values are the same as the \f(CW\*(C`Log::Log4perl\*(C'\fR levels: \f(CW\*(C`TRACE\*(C'\fR, \f(CW\*(C`DEBUG\*(C'\fR, \f(CW\*(C`INFO\*(C'\fR, \f(CW\*(C`WARN\*(C'\fR, \&\f(CW\*(C`ERROR\*(C'\fR, and \f(CW\*(C`FATAL\*(C'\fR. The default is \f(CW\*(C`INFO\*(C'\fR. .IP "\s-1GIT_COMMAND\s0" 4 .IX Item "GIT_COMMAND" The path to the \f(CW\*(C`git\*(C'\fR binary to use for the Git features. The default is \f(CW\*(C`/usr/local/bin/git\*(C'\fR. .SS "Methods" .IX Subsection "Methods" .IP "run( \s-1ARGS\s0 )" 4 .IX Item "run( ARGS )" Just do it. .Sp The \f(CW\*(C`run\*(C'\fR method returns 0 on success and a positive number on failure. See the section on \s-1EXIT CODES\s0 for details on the values. .Sp \&\s-1CPAN\s0.pm sends all the good stuff either to \s-1STDOUT,\s0 or to a temp file if \f(CW$CPAN::Be_Silent\fR is set. I have to intercept that output so I can find out what happened. .Sp Stolen from File::Path::Expand .SH "EXIT VALUES" .IX Header "EXIT VALUES" The script exits with zero if it thinks that everything worked, or a positive number if it thinks that something failed. Note, however, that in some cases it has to divine a failure by the output of things it does not control. For now, the exit codes are vague: .PP .Vb 1 \& 1 An unknown error \& \& 2 The was an external problem \& \& 4 There was an internal problem with the script \& \& 8 A module failed to install .Ve .SH "TO DO" .IX Header "TO DO" * There is initial support for Log4perl if it is available, but I haven't gone through everything to make the NullLogger work out correctly if Log4perl is not installed. .PP * When I capture \s-1CPAN\s0.pm output, I need to check for errors and report them to the user. .PP * Warnings switch .PP * Check then exit .SH "BUGS" .IX Header "BUGS" * none noted .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1CPAN\s0, App::cpanminus .SH "SOURCE AVAILABILITY" .IX Header "SOURCE AVAILABILITY" This code is in Github in the \s-1CPAN\s0.pm repository: .PP .Vb 1 \& https://github.com/andk/cpanpm .Ve .PP The source used to be tracked separately in another GitHub repo, but the canonical source is now in the above repo. .SH "CREDITS" .IX Header "CREDITS" Japheth Cleaver added the bits to allow a forced install (\f(CW\*(C`\-f\*(C'\fR). .PP Jim Brandt suggested and provided the initial implementation for the up-to-date and Changes features. .PP Adam Kennedy pointed out that \f(CW\*(C`exit()\*(C'\fR causes problems on Windows where this script ends up with a .bat extension .PP David Golden helps integrate this into the \f(CW\*(C`CPAN.pm\*(C'\fR repos. .PP Jim Keenan fixed up various issues with _download .SH "AUTHOR" .IX Header "AUTHOR" brian d foy, \f(CW\*(C`<bdfoy@cpan.org>\*(C'\fR .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2001\-2021, brian d foy, All Rights Reserved. .PP You may redistribute this under the same terms as Perl itself. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::API::HOWTO.3pm�����������������������������������������������������������������������0000444�����������������00000006776�15253012307�0011056 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::API::HOWTO 3" .TH CPAN::API::HOWTO 3 "2012-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" CPAN::API::HOWTO \- a recipe book for programming with CPAN.pm .SH "RECIPES" .IX Header "RECIPES" All of these recipes assume that you have put \*(L"use \s-1CPAN\*(R"\s0 at the top of your program. .SS "What distribution contains a particular module?" .IX Subsection "What distribution contains a particular module?" .Vb 3 \& my $distribution = CPAN::Shell\->expand( \& "Module", "Data::UUID" \& )\->distribution()\->pretty_id(); .Ve .PP This returns a string of the form \*(L"\s-1AUTHORID/TARBALL\*(R".\s0 If you want the full path and filename to this distribution on a \s-1CPAN\s0 mirror, then it is \&\f(CW\*(C`.../authors/id/A/AU/AUTHORID/TARBALL\*(C'\fR. .SS "What modules does a particular distribution contain?" .IX Subsection "What modules does a particular distribution contain?" .Vb 4 \& CPAN::Index\->reload(); \& my @modules = CPAN::Shell\->expand( \& "Distribution", "JHI/Graph\-0.83.tar.gz" \& )\->containsmods(); .Ve .PP You may also refer to a distribution in the form A/AU/AUTHORID/TARBALL. .SH "SEE ALSO" .IX Header "SEE ALSO" the main \s-1CPAN\s0.pm documentation .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP See <http://www.perl.com/perl/misc/Artistic.html> .SH "AUTHOR" .IX Header "AUTHOR" David Cantrell ��man/man3/POD2::PT_BR::local::lib.3pm����������������������������������������������������������������0000444�����������������00000054232�15253012307�0012371 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "POD2::PT_BR::local::lib 3" .TH POD2::PT_BR::local::lib 3 "2019-11-14" "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" local::lib~[pt_br] \- crie e use um diretório lib/ local para módulos perl com PERL5LIB .SH "SINOPSE" .IX Header "SINOPSE" No código \- .PP .Vb 1 \& use local::lib; # configura um lib local em ~/perl5 \& \& use local::lib \*(Aq~/foo\*(Aq; # idem, mas ~/foo \& \& # Ou... \& use FindBin; \& use local::lib "$FindBin::Bin/../suporte"; # bibliotecas de suporte locais à aplicação .Ve .PP Pela linha de comando (shell) \- .PP .Vb 2 \& # Instala o LWP e suas dependências não encontradas no diretório \*(Aq~/perl5\*(Aq \& perl \-MCPAN \-Mlocal::lib \-e \*(AqCPAN::install(LWP)\*(Aq \& \& # Apenas exibe alguns comandos úteis para a shell \& $ perl \-Mlocal::lib \& export PERL_MB_OPT=\*(Aq\-\-install_base /home/username/perl5\*(Aq \& export PERL_MM_OPT=\*(AqINSTALL_BASE=/home/username/perl5\*(Aq \& export PERL5LIB=\*(Aq/home/username/perl5/lib/perl5/i386\-linux:/home/username/perl5/lib/perl5\*(Aq \& export PATH="/home/username/perl5/bin:$PATH" .Ve .SS "A técnica de 'bootstrapping'" .IX Subsection "A técnica de 'bootstrapping'" Uma forma comum de instalar o local::lib é usando o que é conhecido como técnica de \*(L"bootstrapping\*(R". É uma boa abordagem caso seu administrador de sistemas não tenha instalado o local::lib. Nesse caso, você precisará instalar o local::lib em seu diretório de usuário. .PP Caso você tenha privilégios de administrador, ainda assim deverá configurar suas variáveis de ambiente, como discutido no passo 4, abaixo. Sem elas, você ainda instalará módulos no \s-1CPAN\s0 do sistema e seus scripts Perl não utilizarão o caminho para o lib/ que você definiu com o local::lib. .PP Por padrão, o local::lib instala os módulos do \s-1CPAN\s0 e a si próprio em ~/perl5. .PP Usuários do Windows devem ler \*(L"Diferenças ao usar esse módulo em Win32\*(R". .PP 1. Baixe e descompacte o local::lib do \s-1CPAN\s0 (procure por \*(L"Download\*(R" na página do \s-1CPAN\s0 sobre o local::lib). Faça isso como um usuário comum, não como root ou administrador. Descompacte o arquivo em seu diretório de usuário ou em qualquer outro local conveniente. .PP 2. Execute isso: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap .Ve .PP Caso o sistema pergunte se deve configurar tudo que puder automaticamente, você provavelmente deve responder que sim (yes). .PP Para instalar o local::lib em um diretório que não o padrão, você precisará especificá\-lo ao chamar o bootstrap, da seguinte forma: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap=~/foo .Ve .PP 3. Execute isso: (local::lib assume que você possui o comando 'make' instalado em seu sistema) .PP .Vb 1 \& make test && make install .Ve .PP 4. Agora precisamos configurar as variáveis de ambiente apropriadas para que o Perl use nosso recém\-criado diretório lib/. Caso esteja usando bash ou outra shell Bourne, você pode fazer isso adicionando a seguinte linha em seu script de inicialização da shell: .PP .Vb 1 \& echo \*(Aqeval $(perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib)\*(Aq >>~/.bashrc .Ve .PP Caso esteja usando a shell C, pode fazer da seguinte forma: .PP .Vb 4 \& /bin/csh \& echo $SHELL \& /bin/csh \& perl \-I$HOME/perl5/lib/perl5 \-Mlocal::lib >> ~/.cshrc .Ve .PP Caso tenha passado para o bootstrap um diretório que não o padrão, você precisará indicá\-lo na chamada ao local::lib, dessa forma: .PP .Vb 1 \& echo \*(Aqeval $(perl \-I$HOME/foo/lib/perl5 \-Mlocal::lib=$HOME/foo)\*(Aq >>~/.bashrc .Ve .PP Após atualizar seu arquivo de configuração da shell, certifique-se de processá\-lo novamente para obter as modificações em sua shell atual. Shells Bourne usam \f(CW\*(C`. ~/.bashrc\*(C'\fR para isso, enquanto shells C usam \f(CW\*(C`source ~/.cshrc\*(C'\fR. .PP Se estiver em uma máquina lenta ou operando com grandes limitações de espaço em disco, você pode desativar a geração automática de manpages a partir do \s-1POD\s0 ao instalar módulos. Para isso, basta passar o argumento \&\f(CW\*(C`\-\-no\-manpages\*(C'\fR durante o bootstrap: .PP .Vb 1 \& perl Makefile.PL \-\-bootstrap \-\-no\-manpages .Ve .PP Para evitar ter que fazer vários bootstraps para vários ambientes de módulos Perl na mesma conta de usuário \- por exemplo se você usa o local::lib para desenvolver diferentes aplicativos independentes \- você pode utilizar uma única instalação bootstrap do local::lib para instalar módulos em diretórios diferentes da seguinte forma: .PP .Vb 7 \& cd ~/meudir1 \& perl \-Mlocal::lib=./ \& eval $(perl \-Mlocal::lib=./) ### Para configurar o ambiente apenas nessa shell \& printenv ### Veja que o ~/meudir1 está na PERL5LIB \& perl \-MCPAN \-e install ... ### Os módulos que quiser \& cd ../meudir2 \& ... REPITA ... .Ve .PP Para múltiplos ambientes destinados a múltiplos aplicativos, você pode precisar incluir uma versão modificada das instruções de \f(CW\*(C`use FindBin\*(C'\fR no exemplo \*(L"No código\*(R" acima. Caso tenha feito algo como o que foi descrito acima, terá um conjunto de módulos Perl em \f(CW\*(C`~/meudir1/lib\*(C'\fR. Caso tenha um script em \f(CW\*(C`~/meudir1/scripts/meuscript.pl\*(C'\fR, você precisará indicar a ele onde encontrar os módulos que instalou para ele em \f(CW\*(C`~/meudir1/lib\*(C'\fR. .PP Em \f(CW\*(C`~/meudir1/scripts/meuscript.pl\*(C'\fR: .PP .Vb 4 \& use strict; \& use warnings; \& use local::lib "$FindBin::Bin/.."; ### aponta para ~/meudir1 e o local::lib acha o lib/ \& use lib "$FindBin::Bin/../lib"; ### aponta para ~/meudir1/lib .Ve .PP Coloque isso antes de qualquer bloco \s-1BEGIN\s0 { ... } que precise dos módulos instalados. .SS "Diferenças ao usar esse módulo em Win32" .IX Subsection "Diferenças ao usar esse módulo em Win32" Para configurar as variáveis de ambiente apropriadas para sua sessão atual do \f(CW\*(C`CMD.exe\*(C'\fR, você pode fazer assim: .PP .Vb 5 \& C:\e>perl \-Mlocal::lib \& set PERL_MB_OPT=\-\-install_base C:\eDOCUME~1\eADMINI~1\eperl5 \& set PERL_MM_OPT=INSTALL_BASE=C:\eDOCUME~1\eADMINI~1\eperl5 \& set PERL5LIB=C:\eDOCUME~1\eADMINI~1\eperl5\elib\eperl5;C:\eDOCUME~1\eADMINI~1\eperl5\elib\eperl5\eMSWin32\-x86\-multi\-thread \& set PATH=C:\eDOCUME~1\eADMINI~1\eperl5\ebin;%PATH% \& \& ### Para configurar o ambiente apenas dessa shell \& C:\e>perl \-Mlocal::lib > %TEMP%\etmp.bat && %TEMP%\etmp.bat && del %TEMP%\etemp.bat \& ### em vez de $(perl \-Mlocal::lib=./) .Ve .PP Caso queira que as configurações do ambiente persistam, você precisará adicioná\-las em Painel de Controle \-> Sistema, ou usar o App::local::lib::Win32Helper. .PP O \*(L"~\*(R" é transformado no diretório do perfil do usuário (o diretório com o nome do usuário dentro de \*(L"Documents and Settings\*(R" (Windows \s-1XP\s0 ou anterior) ou \*(L"Usuários\*(R" (Windows Vista e mais recentes)) a menos que \f(CW$ENV\fR{\s-1HOME\s0} exista. Após isso, o nome do diretório é encurtado e os subdiretórios são criados (o que significa que o diretório deve existir). .SH "MOTIVAÇÃO" .IX Header "MOTIVAÇÃO" A versão de um pacote Perl na sua máquina nem sempre é a que você precisa. Obviamente, a melhor coisa a fazer seria atualizá\-la para a versão desejada. No entanto, você pode estar em uma situação que o impede de fazer isso. Talvez você não tenha privilégios de administrador do sistema; ou talvez esteja usando um sistema de gerenciamento de pacotes como o do Debian, e ainda não exista um pacote disponível na versão desejada. .PP local::lib resolve esse problema possibilitando a criação de seu próprio diretório de pacotes Perl obtidos do \s-1CPAN\s0 (em sistemas multi\-usuário, isso normalmente fica dentro do diretório de seu usuário). A instalação do Perl no sistema permanece inalterada; você simplesmente chama o Perl com opções especiais para que ele use os pacotes em seu diretório local em vez dos pacotes do sistema. O local::lib organiza as coisas para que versões dos pacotes Perl instalados localmente tenham precedência sobre as do sistema. .PP Caso esteja usando um sistema de gerenciamento de pacote (como em sistemas Debian), não precisará se preocupar com conflitos entre o Debian e o \s-1CPAN.\s0 Sua versão local dos pacotes será instalada em um diretório completamente diferente das versões instaladas pelo gerenciador de pacotes do sistema. .SH "DESCRIÇÃO" .IX Header "DESCRIÇÃO" Este módulo oferece uma forma rápida e conveniente para criar um repositório de módulos locais ao usuário, dentro do diretório do mesmo. Ele também monta e exibe para o usuário uma lista de variáveis de ambiente utilizando a sintaxe da shell atual do usuário (conforme especificado pela variável de ambiente \f(CW\*(C`SHELL\*(C'\fR), pronta para ser adicionada diretamente no arquivo de configuração da shell. .PP Generalizando, o local::lib permite a criação e uso de um diretório contendo módulos Perl fora do \f(CW@INC\fR do Perl. Isso facilita a produção de aplicações com uma versão específica de determinado módulo, ou coleção de módulos. Também é útil quando o mantenedor de um módulo não aplicou determinado patch que você precisa para seu aplicativo. .PP Durante o \f(CW\*(C`import\*(C'\fR, o local::lib define valores apropriados para as seguintes variáveis de ambiente: .IP "\s-1PERL_MB_OPT\s0" 4 .IX Item "PERL_MB_OPT" .PD 0 .IP "\s-1PERL_MM_OPT\s0" 4 .IX Item "PERL_MM_OPT" .IP "\s-1PERL5LIB\s0" 4 .IX Item "PERL5LIB" .IP "\s-1PATH\s0" 4 .IX Item "PATH" .PD valores serão anexados ao \s-1PATH,\s0 em vez de substituí\-lo. .PP Esses valores são então disponibilizados para referência por qualquer outro código após o \f(CW\*(C`import\*(C'\fR. .SH "CRIANDO UM CONJUNTO AUTO-CONTIDO DE MÓDULOS" .IX Header "CRIANDO UM CONJUNTO AUTO-CONTIDO DE MÓDULOS" Veja lib::core::only para uma maneira de fazer isso \- mas note que há uma série de ressalvas na abordagem, e a melhor forma é sempre fazer o 'build' contra uma versão limpa do perl (i.e. com 'site' e 'vendor' o mais vazios possível). .SH "MÉTODOS" .IX Header "MÉTODOS" .SS "ensure_dir_structure_for" .IX Subsection "ensure_dir_structure_for" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .IP "Valor de Retorno: Nenhum" 4 .IX Item "Valor de Retorno: Nenhum" .PD .PP Tenta criar o caminho fornecido, e todos os diretórios superiores necessários. Gera uma exceção em caso de falha. .SS "print_environment_vars_for" .IX Subsection "print_environment_vars_for" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .IP "Valor de Retorno: Nenhum" 4 .IX Item "Valor de Retorno: Nenhum" .PD .PP Exibe na saída padrão as variáveis listadas acima, devidamente ajustadas para utilizar o caminho fornecido como diretório base. .SS "build_environment_vars_for" .IX Subsection "build_environment_vars_for" .ie n .IP "Argumentos: $caminho_do_diretorio, $interpolar" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR, \f(CW$interpolar\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio, $interpolar" .PD 0 .ie n .IP "Valor de Retorno: %variaveis_de_ambiente" 4 .el .IP "Valor de Retorno: \f(CW%variaveis_de_ambiente\fR" 4 .IX Item "Valor de Retorno: %variaveis_de_ambiente" .PD .PP Retorna hash contendo as variáveis de ambiente listadas acima, devidamente ajustadas para utilizar o caminho fornecido como diretório base. .SS "setup_env_hash_for" .IX Subsection "setup_env_hash_for" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .IP "Valor de Retorno: Nenhum" 4 .IX Item "Valor de Retorno: Nenhum" .PD .PP Constrói as chaves no \f(CW%ENV\fR para o caminho fornecido, chamando \&\f(CW\*(C`build_environment_vars_for\*(C'\fR. .SS "install_base_perl_path" .IX Subsection "install_base_perl_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_base_de_instalacao" 4 .el .IP "Valor de Retorno: \f(CW$caminho_base_de_instalacao\fR" 4 .IX Item "Valor de Retorno: $caminho_base_de_instalacao" .PD .PP Retorna um caminho de diretório indicando onde instalar os módulos Perl para essa instalação local de bibliotecas. Adiciona os diretórios \f(CW\*(C`lib\*(C'\fR e \f(CW\*(C`perl5\*(C'\fR ao final do caminho fornecido. .SS "install_base_arch_path" .IX Subsection "install_base_arch_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_base_de_instalacao_arch" 4 .el .IP "Valor de Retorno: \f(CW$caminho_base_de_instalacao_arch\fR" 4 .IX Item "Valor de Retorno: $caminho_base_de_instalacao_arch" .PD .PP Retorna um caminho de diretório indicando onde instalar os módulos Perl de arquiteturas específicas para essa instalação local de bibliotecas. Baseia-se no valor de retorno do método \*(L"install_base_perl_path\*(R", adicionando o valor de \f(CW$Config{archname}\fR. .SS "install_base_bin_path" .IX Subsection "install_base_bin_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_base_de_instalacao_bin" 4 .el .IP "Valor de Retorno: \f(CW$caminho_base_de_instalacao_bin\fR" 4 .IX Item "Valor de Retorno: $caminho_base_de_instalacao_bin" .PD .PP Retorna um caminho de diretório indicando onde instalar programas executáveis para essa instalação local de bibliotecas. Baseia-se no valor de retorno do método \*(L"install_base_perl_path\*(R", adicionando o diretório \f(CW\*(C`bin\*(C'\fR. .SS "resolve_empty_path" .IX Subsection "resolve_empty_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_base_de_instalacao" 4 .el .IP "Valor de Retorno: \f(CW$caminho_base_de_instalacao\fR" 4 .IX Item "Valor de Retorno: $caminho_base_de_instalacao" .PD .PP Cria e retorna o caminho de diretório raiz em que a instalação local de módulos deve ser feita. O padrão é \f(CW\*(C`~/perl5\*(C'\fR. .SS "resolve_home_path" .IX Subsection "resolve_home_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_para_home" 4 .el .IP "Valor de Retorno: \f(CW$caminho_para_home\fR" 4 .IX Item "Valor de Retorno: $caminho_para_home" .PD .PP Procura pelo diretório padrão (home) do usuário. Gera uma exceção caso não encontre resultado definitivo. .SS "resolve_relative_path" .IX Subsection "resolve_relative_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_absoluto" 4 .el .IP "Valor de Retorno: \f(CW$caminho_absoluto\fR" 4 .IX Item "Valor de Retorno: $caminho_absoluto" .PD .PP Transforma o caminho fornecido em um caminho absoluto. .SS "resolve_path" .IX Subsection "resolve_path" .ie n .IP "Argumentos: $caminho_do_diretorio" 4 .el .IP "Argumentos: \f(CW$caminho_do_diretorio\fR" 4 .IX Item "Argumentos: $caminho_do_diretorio" .PD 0 .ie n .IP "Valor de Retorno: $caminho_absoluto" 4 .el .IP "Valor de Retorno: \f(CW$caminho_absoluto\fR" 4 .IX Item "Valor de Retorno: $caminho_absoluto" .PD .PP Invoca os seguintes métodos em sequência, passando o resultado do método anterior para o seguinte, na tentativa de descobrir onde configurar o ambiente para a instalação local de bibliotecas: \*(L"resolve_empty_path\*(R", \&\*(L"resolve_home_path\*(R", \*(L"resolve_relative_path\*(R". Passa o caminho de diretório fornecido para \*(L"resolve_empty_path\*(R" que retorna um resultado que é passado para \*(L"resolve_home_path\*(R", que então tem seu resultado passado para \*(L"resolve_relative_path\*(R". O resultado dessa chamada final é então retornado pelo \*(L"resolve_path\*(R". .SH "UM AVISO SOBRE UNINST=1" .IX Header "UM AVISO SOBRE UNINST=1" Tenha cuidado ao usar o local::lib em conjunto com \*(L"make install UNINST=1\*(R". A idéia dessa opção é desinstalar a versão anterior de um módulo antes de instalar a mais recente. No entanto ela não possui uma verificação de segurança de que a versão antiga e a nova referem-se ao mesmo diretório. Usada em combinação com o local::lib, você pode potencialmente apagar uma versão globalmente acessível de um módulo e instalar a versão mais nova no diretório local. Apenas utilize \*(L"make install UNINST=1\*(R" junto com o local::lib se você entende essas possíveis consequências. .SH "LIMITAÇÕES" .IX Header "LIMITAÇÕES" As ferramentas auxiliares do perl não conseguem lidar com nomes de diretórios contendo espaços, então não é possível fazer seu bootstrap do local::lib em um diretório com espaços. O que você pode fazer é mover seu local::lib para um diretório com espaços \fBapós\fR ter instalado todos os módulos dentro dele. Mas esteja ciente que você não poderá atualizar ou instalar outros módulos do \s-1CPAN\s0 nesse diretório local após a mudança. .PP A detecção da shell é relativamente básica. Neste momento, qualquer coisa com csh no nome será tratada como a C shell ou compatível, e todo o resto será tratado como Bourne, exceto em sistemas Win32. Caso a variável de ambiente \f(CW\*(C`SHELL\*(C'\fR não esteja disponível, assumiremos tratar-se de uma shell compatível com a Bourne. .PP A técnica de bootstrap é um hack e usará o \s-1CPAN\s0.pm para o ExtUtils::MakeMaker mesmo que você tenha o \s-1CPANPLUS\s0 instalado. .PP Destrói qualquer valor pré\-existente nas variáveis de ambiente \s-1PERL5LIB, PERL_MM_OPT\s0 e \s-1PERL_MB_OPT.\s0 .PP Provavelmente deveria auto-configurar o \s-1CPAN\s0 caso isso ainda não tenha sido feito. .PP Correções (patches) são muito bem-vindos para quaisquer dos itens acima. .PP Em sistemas Win32, não há uma forma de escrever no registro as variáveis de ambiente criadas, para que elas persistam a uma reinicialização. .SH "SOLUÇÃO DE PROBLEMAS" .IX Header "SOLUÇÃO DE PROBLEMAS" Se você configurou o local::lib para instalar módulos do \s-1CPAN\s0 em algum lugar do seu 'home', e mais tarde tentou instalar um módulo fazendo \f(CW\*(C`cpan \-i Foo::Bar\*(C'\fR, mas ele falhou com um erro como: \f(CW\*(C`Warning: You do not have permissions to install into /usr/lib64/perl5/site_perl/5.8.8/x86_64\-linux at /usr/lib64/perl5/5.8.8/Foo/Bar.pm\*(C'\fR e em algum lugar no seu log de instalação houver um erro dizendo \f(CW\*(C`\*(AqINSTALL_BASE\*(Aq is not a known MakeMaker parameter name\*(C'\fR, então você de alguma forma perdeu seu ExtUtils::MakeMaker atualizado. .PP Para remediar a situação, execute novamente o procedimento de bootstrap descrito acima. .PP Então, execute \f(CW\*(C`rm \-r ~/.cpan/build/Foo\-Bar*\*(C'\fR .PP Finalmente, execute novamente o \f(CW\*(C`cpan \-i Foo::Bar\*(C'\fR e ele deve instalar sem problemas. .SH "AMBIENTE" .IX Header "AMBIENTE" .IP "\s-1SHELL\s0" 4 .IX Item "SHELL" .PD 0 .IP "\s-1COMSPEC\s0" 4 .IX Item "COMSPEC" .PD O local::lib procura pela variável de ambiente \f(CW\*(C`SHELL\*(C'\fR do usuário ao processar e exibir os comandos a serem adicionados no arquivo de configuração da shell. .Sp Em sistemas Win32, \f(CW\*(C`COMSPEC\*(C'\fR também será examinado. .SH "SUPORTE" .IX Header "SUPORTE" \&\s-1IRC:\s0 .PP .Vb 1 \& Acesse #local\-lib em irc.perl.org. .Ve .SH "AUTOR DA TRADUÇÃO" .IX Header "AUTOR DA TRADUÇÃO" Breno G. de Oliveira, \f(CW\*(C`<garu at cpan.org>\*(C'\fR, após ter perdido uma aposta para o Getty <http://search.cpan.org/~getty/> durante a Copa de 2010. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2007 \- 2010 \*(L"\s-1AUTHOR\*(R"\s0 in local::lib e \*(L"\s-1CONTRIBUTORS\*(R"\s0 in local::lib do local::lib como listados em local::lib. .SH "LICENÇA" .IX Header "LICENÇA" Esta biblioteca é software livre e pode ser distribuída sob os mesmo termos do perl. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/Switch.3pm���������������������������������������������������������������������������������0000444�����������������00000045102�15253012307�0010035 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "Switch 3" .TH Switch 3 "2014-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" Switch \- A switch statement for Perl, do not use if you can use given/when .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Switch; \& \& switch ($val) { \& case 1 { print "number 1" } \& case "a" { print "string a" } \& case [1..10,42] { print "number in list" } \& case (\e@array) { print "number in list" } \& case /\ew+/ { print "pattern" } \& case qr/\ew+/ { print "pattern" } \& case (\e%hash) { print "entry in hash" } \& case (\e&sub) { print "arg to subroutine" } \& else { print "previous case not true" } \& } .Ve .SH "BACKGROUND" .IX Header "BACKGROUND" [Skip ahead to \*(L"\s-1DESCRIPTION\*(R"\s0 if you don't care about the whys and wherefores of this control structure] .PP In seeking to devise a \*(L"Swiss Army\*(R" case mechanism suitable for Perl, it is useful to generalize this notion of distributed conditional testing as far as possible. Specifically, the concept of \*(L"matching\*(R" between the switch value and the various case values need not be restricted to numeric (or string or referential) equality, as it is in other languages. Indeed, as Table 1 illustrates, Perl offers at least eighteen different ways in which two values could generate a match. .PP .Vb 1 \& Table 1: Matching a switch value ($s) with a case value ($c) \& \& Switch Case Type of Match Implied Matching Code \& Value Value \& ====== ===== ===================== ============= \& \& number same numeric or referential match if $s == $c; \& or ref equality \& \& object method result of method call match if $s\->$c(); \& ref name match if defined $s\->$c(); \& or ref \& \& other other string equality match if $s eq $c; \& non\-ref non\-ref \& scalar scalar \& \& string regexp pattern match match if $s =~ /$c/; \& \& array scalar array entry existence match if 0<=$c && $c<@$s; \& ref array entry definition match if defined $s\->[$c]; \& array entry truth match if $s\->[$c]; \& \& array array array intersection match if intersects(@$s, @$c); \& ref ref (apply this table to \& all pairs of elements \& $s\->[$i] and \& $c\->[$j]) \& \& array regexp array grep match if grep /$c/, @$s; \& ref \& \& hash scalar hash entry existence match if exists $s\->{$c}; \& ref hash entry definition match if defined $s\->{$c}; \& hash entry truth match if $s\->{$c}; \& \& hash regexp hash grep match if grep /$c/, keys %$s; \& ref \& \& sub scalar return value defn match if defined $s\->($c); \& ref return value truth match if $s\->($c); \& \& sub array return value defn match if defined $s\->(@$c); \& ref ref return value truth match if $s\->(@$c); .Ve .PP In reality, Table 1 covers 31 alternatives, because only the equality and intersection tests are commutative; in all other cases, the roles of the \f(CW$s\fR and \f(CW$c\fR variables could be reversed to produce a different test. For example, instead of testing a single hash for the existence of a series of keys (\f(CW\*(C`match if exists $s\->{$c}\*(C'\fR), one could test for the existence of a single key in a series of hashes (\f(CW\*(C`match if exists $c\->{$s}\*(C'\fR). .SH "DESCRIPTION" .IX Header "DESCRIPTION" The Switch.pm module implements a generalized case mechanism that covers most (but not all) of the numerous possible combinations of switch and case values described above. .PP The module augments the standard Perl syntax with two new control statements: \f(CW\*(C`switch\*(C'\fR and \f(CW\*(C`case\*(C'\fR. The \f(CW\*(C`switch\*(C'\fR statement takes a single scalar argument of any type, specified in parentheses. \&\f(CW\*(C`switch\*(C'\fR stores this value as the current switch value in a (localized) control variable. The value is followed by a block which may contain one or more Perl statements (including the \f(CW\*(C`case\*(C'\fR statement described below). The block is unconditionally executed once the switch value has been cached. .PP A \f(CW\*(C`case\*(C'\fR statement takes a single scalar argument (in mandatory parentheses if it's a variable; otherwise the parens are optional) and selects the appropriate type of matching between that argument and the current switch value. The type of matching used is determined by the respective types of the switch value and the \f(CW\*(C`case\*(C'\fR argument, as specified in Table 1. If the match is successful, the mandatory block associated with the \f(CW\*(C`case\*(C'\fR statement is executed. .PP In most other respects, the \f(CW\*(C`case\*(C'\fR statement is semantically identical to an \f(CW\*(C`if\*(C'\fR statement. For example, it can be followed by an \f(CW\*(C`else\*(C'\fR clause, and can be used as a postfix statement qualifier. .PP However, when a \f(CW\*(C`case\*(C'\fR block has been executed control is automatically transferred to the statement after the immediately enclosing \f(CW\*(C`switch\*(C'\fR block, rather than to the next statement within the block. In other words, the success of any \f(CW\*(C`case\*(C'\fR statement prevents other cases in the same scope from executing. But see \*(L"Allowing fall-through\*(R" below. .PP Together these two new statements provide a fully generalized case mechanism: .PP .Vb 1 \& use Switch; \& \& # AND LATER... \& \& %special = ( woohoo => 1, d\*(Aqoh => 1 ); \& \& while (<>) { \& chomp; \& switch ($_) { \& case (%special) { print "homer\en"; } # if $special{$_} \& case /[a\-z]/i { print "alpha\en"; } # if $_ =~ /a\-z/i \& case [1..9] { print "small num\en"; } # if $_ in [1..9] \& case { $_[0] >= 10 } { print "big num\en"; } # if $_ >= 10 \& print "must be punctuation\en" case /\eW/; # if $_ ~= /\eW/ \& } \& } .Ve .PP Note that \f(CW\*(C`switch\*(C'\fRes can be nested within \f(CW\*(C`case\*(C'\fR (or any other) blocks, and a series of \f(CW\*(C`case\*(C'\fR statements can try different types of matches \&\*(-- hash membership, pattern match, array intersection, simple equality, etc. \*(-- against the same switch value. .PP The use of intersection tests against an array reference is particularly useful for aggregating integral cases: .PP .Vb 8 \& sub classify_digit \& { \& switch ($_[0]) { case 0 { return \*(Aqzero\*(Aq } \& case [2,4,6,8] { return \*(Aqeven\*(Aq } \& case [1,3,5,7,9] { return \*(Aqodd\*(Aq } \& case /[A\-F]/i { return \*(Aqhex\*(Aq } \& } \& } .Ve .SS "Allowing fall-through" .IX Subsection "Allowing fall-through" Fall-though (trying another case after one has already succeeded) is usually a Bad Idea in a switch statement. However, this is Perl, not a police state, so there \fIis\fR a way to do it, if you must. .PP If a \f(CW\*(C`case\*(C'\fR block executes an untargeted \f(CW\*(C`next\*(C'\fR, control is immediately transferred to the statement \fIafter\fR the \f(CW\*(C`case\*(C'\fR statement (i.e. usually another case), rather than out of the surrounding \&\f(CW\*(C`switch\*(C'\fR block. .PP For example: .PP .Vb 7 \& switch ($val) { \& case 1 { handle_num_1(); next } # and try next case... \& case "1" { handle_str_1(); next } # and try next case... \& case [0..9] { handle_num_any(); } # and we\*(Aqre done \& case /\ed/ { handle_dig_any(); next } # and try next case... \& case /.*/ { handle_str_any(); next } # and try next case... \& } .Ve .PP If \f(CW$val\fR held the number \f(CW1\fR, the above \f(CW\*(C`switch\*(C'\fR block would call the first three \f(CW\*(C`handle_...\*(C'\fR subroutines, jumping to the next case test each time it encountered a \f(CW\*(C`next\*(C'\fR. After the third \f(CW\*(C`case\*(C'\fR block was executed, control would jump to the end of the enclosing \&\f(CW\*(C`switch\*(C'\fR block. .PP On the other hand, if \f(CW$val\fR held \f(CW10\fR, then only the last two \f(CW\*(C`handle_...\*(C'\fR subroutines would be called. .PP Note that this mechanism allows the notion of \fIconditional fall-through\fR. For example: .PP .Vb 4 \& switch ($val) { \& case [0..9] { handle_num_any(); next if $val < 7; } \& case /\ed/ { handle_dig_any(); } \& } .Ve .PP If an untargeted \f(CW\*(C`last\*(C'\fR statement is executed in a case block, this immediately transfers control out of the enclosing \f(CW\*(C`switch\*(C'\fR block (in other words, there is an implicit \f(CW\*(C`last\*(C'\fR at the end of each normal \f(CW\*(C`case\*(C'\fR block). Thus the previous example could also have been written: .PP .Vb 4 \& switch ($val) { \& case [0..9] { handle_num_any(); last if $val >= 7; next; } \& case /\ed/ { handle_dig_any(); } \& } .Ve .SS "Automating fall-through" .IX Subsection "Automating fall-through" In situations where case fall-through should be the norm, rather than an exception, an endless succession of terminal \f(CW\*(C`next\*(C'\fRs is tedious and ugly. Hence, it is possible to reverse the default behaviour by specifying the string \*(L"fallthrough\*(R" when importing the module. For example, the following code is equivalent to the first example in \*(L"Allowing fall-through\*(R": .PP .Vb 1 \& use Switch \*(Aqfallthrough\*(Aq; \& \& switch ($val) { \& case 1 { handle_num_1(); } \& case "1" { handle_str_1(); } \& case [0..9] { handle_num_any(); last } \& case /\ed/ { handle_dig_any(); } \& case /.*/ { handle_str_any(); } \& } .Ve .PP Note the explicit use of a \f(CW\*(C`last\*(C'\fR to preserve the non-fall-through behaviour of the third case. .SS "Alternative syntax" .IX Subsection "Alternative syntax" Perl 6 will provide a built-in switch statement with essentially the same semantics as those offered by Switch.pm, but with a different pair of keywords. In Perl 6 \f(CW\*(C`switch\*(C'\fR will be spelled \f(CW\*(C`given\*(C'\fR, and \&\f(CW\*(C`case\*(C'\fR will be pronounced \f(CW\*(C`when\*(C'\fR. In addition, the \f(CW\*(C`when\*(C'\fR statement will not require switch or case values to be parenthesized. .PP This future syntax is also (largely) available via the Switch.pm module, by importing it with the argument \f(CW"Perl6"\fR. For example: .PP .Vb 1 \& use Switch \*(AqPerl6\*(Aq; \& \& given ($val) { \& when 1 { handle_num_1(); } \& when ($str1) { handle_str_1(); } \& when [0..9] { handle_num_any(); last } \& when /\ed/ { handle_dig_any(); } \& when /.*/ { handle_str_any(); } \& default { handle anything else; } \& } .Ve .PP Note that scalars still need to be parenthesized, since they would be ambiguous in Perl 5. .PP Note too that you can mix and match both syntaxes by importing the module with: .PP .Vb 1 \& use Switch \*(AqPerl5\*(Aq, \*(AqPerl6\*(Aq; .Ve .SS "Higher-order Operations" .IX Subsection "Higher-order Operations" One situation in which \f(CW\*(C`switch\*(C'\fR and \f(CW\*(C`case\*(C'\fR do not provide a good substitute for a cascaded \f(CW\*(C`if\*(C'\fR, is where a switch value needs to be tested against a series of conditions. For example: .PP .Vb 11 \& sub beverage { \& switch (shift) { \& case { $_[0] < 10 } { return \*(Aqmilk\*(Aq } \& case { $_[0] < 20 } { return \*(Aqcoke\*(Aq } \& case { $_[0] < 30 } { return \*(Aqbeer\*(Aq } \& case { $_[0] < 40 } { return \*(Aqwine\*(Aq } \& case { $_[0] < 50 } { return \*(Aqmalt\*(Aq } \& case { $_[0] < 60 } { return \*(AqMoet\*(Aq } \& else { return \*(Aqmilk\*(Aq } \& } \& } .Ve .PP (This is equivalent to writing \f(CW\*(C`case (sub { $_[0] < 10 })\*(C'\fR, etc.; \f(CW$_[0]\fR is the argument to the anonymous subroutine.) .PP The need to specify each condition as a subroutine block is tiresome. To overcome this, when importing Switch.pm, a special \*(L"placeholder\*(R" subroutine named \f(CW\*(C`_\|_\*(C'\fR [sic] may also be imported. This subroutine converts (almost) any expression in which it appears to a reference to a higher-order function. That is, the expression: .PP .Vb 1 \& use Switch \*(Aq_\|_\*(Aq; \& \& _\|_ < 2 .Ve .PP is equivalent to: .PP .Vb 1 \& sub { $_[0] < 2 } .Ve .PP With \f(CW\*(C`_\|_\*(C'\fR, the previous ugly case statements can be rewritten: .PP .Vb 7 \& case _\|_ < 10 { return \*(Aqmilk\*(Aq } \& case _\|_ < 20 { return \*(Aqcoke\*(Aq } \& case _\|_ < 30 { return \*(Aqbeer\*(Aq } \& case _\|_ < 40 { return \*(Aqwine\*(Aq } \& case _\|_ < 50 { return \*(Aqmalt\*(Aq } \& case _\|_ < 60 { return \*(AqMoet\*(Aq } \& else { return \*(Aqmilk\*(Aq } .Ve .PP The \f(CW\*(C`_\|_\*(C'\fR subroutine makes extensive use of operator overloading to perform its magic. All operations involving _\|_ are overloaded to produce an anonymous subroutine that implements a lazy version of the original operation. .PP The only problem is that operator overloading does not allow the boolean operators \f(CW\*(C`&&\*(C'\fR and \f(CW\*(C`||\*(C'\fR to be overloaded. So a case statement like this: .PP .Vb 1 \& case 0 <= _\|_ && _\|_ < 10 { return \*(Aqdigit\*(Aq } .Ve .PP doesn't act as expected, because when it is executed, it constructs two higher order subroutines and then treats the two resulting references as arguments to \f(CW\*(C`&&\*(C'\fR: .PP .Vb 1 \& sub { 0 <= $_[0] } && sub { $_[0] < 10 } .Ve .PP This boolean expression is inevitably true, since both references are non-false. Fortunately, the overloaded \f(CW\*(Aqbool\*(Aq\fR operator catches this situation and flags it as an error. .SH "DEPENDENCIES" .IX Header "DEPENDENCIES" The module is implemented using Filter::Util::Call and Text::Balanced and requires both these modules to be installed. .SH "AUTHOR" .IX Header "AUTHOR" Damian Conway (damian@conway.org). This module is now maintained by Alexandr Ciornii (alexchorny@gmail.com). Previously was maintained by Rafael Garcia-Suarez and perl5 porters. .SH "BUGS" .IX Header "BUGS" There are undoubtedly serious bugs lurking somewhere in code this funky :\-) Bug reports and other feedback are most welcome. .PP May create syntax errors in other parts of code. .PP On perl 5.10.x may cause syntax error if \*(L"case\*(R" is present inside heredoc. .PP In general, use given/when instead. It were introduced in perl 5.10.0. Perl 5.10.0 was released in 2007. .SH "LIMITATIONS" .IX Header "LIMITATIONS" Due to the heuristic nature of Switch.pm's source parsing, the presence of regexes with embedded newlines that are specified with raw \f(CW\*(C`/.../\*(C'\fR delimiters and don't have a modifier \f(CW\*(C`//x\*(C'\fR are indistinguishable from code chunks beginning with the division operator \f(CW\*(C`/\*(C'\fR. As a workaround you must use \f(CW\*(C`m/.../\*(C'\fR or \f(CW\*(C`m?...?\*(C'\fR for such patterns. Also, the presence of regexes specified with raw \f(CW\*(C`?...?\*(C'\fR delimiters may cause mysterious errors. The workaround is to use \f(CW\*(C`m?...?\*(C'\fR instead. .PP Due to the way source filters work in Perl, you can't use Switch inside an string \f(CW\*(C`eval\*(C'\fR. .PP May not work if sub prototypes are used (RT#33988). .PP Regex captures in when are not available to code. .PP If your source file is longer then 1 million characters and you have a switch statement that crosses the 1 million (or 2 million, etc.) character boundary you will get mysterious errors. The workaround is to use smaller source files. .SH "COPYRIGHT" .IX Header "COPYRIGHT" .Vb 3 \& Copyright (c) 1997\-2008, Damian Conway. All Rights Reserved. \& This module is free software. It may be used, redistributed \& and/or modified under the same terms as Perl itself. .Ve ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/HTTP::Tiny.3pm�����������������������������������������������������������������������������0000444�����������������00000067221�15253012307�0010411 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "2023-07-11" "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.088 .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-1TLS/SSL\s0 certificate of an \f(CW\*(C`https\*(C'\fR — connection (default is true). Changed from false to true in version 0.083. .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 .IP "\(bu" 4 \&\f(CW$ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT}\fR \- Changes the default certificate verification behavior to not check server identity if set to 1. Only effective if \f(CW\*(C`verify_SSL\*(C'\fR is not set. Added in version 0.083. .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 Content data in the request/response is handled as \*(L"raw bytes\*(R". Any encoding/decoding (with associated headers) are the responsibility of the caller. .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 "TLS/SSL SUPPORT" .IX Header "TLS/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-1TLS\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-1TLS/SSL\s0 provides two distinct capabilities: .IP "\(bu" 4 Encrypted communication channel .IP "\(bu" 4 Verification of server identity .PP \&\fBBy default, HTTP::Tiny verifies server identity\fR. .PP This was changed in version 0.083 due to security concerns. The previous default behavior can be enabled by setting \f(CW$ENV{PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT}\fR to 1. .PP Verification is done by checking that that the \s-1TLS/SSL\s0 connection has a valid certificate corresponding to the host name of the connection and that the certificate has been verified by a \s-1CA.\s0 Assuming you trust the \s-1CA,\s0 this will protect against machine-in-the-middle attacks <http://en.wikipedia.org/wiki/Machine-in-the-middle_attack>. .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. .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 .IP "\(bu" 4 /etc/openssl/certs/ca\-certificates.crt .IP "\(bu" 4 /etc/ssl/cert.pem .IP "\(bu" 4 /usr/local/share/certs/ca\-root\-nss.crt .IP "\(bu" 4 /etc/pki/tls/cacert.pem .IP "\(bu" 4 /etc/certs/ca\-certificates.crt .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-1TLS/SSL\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-1TLS/SSL\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 <http://www.w3.org/Protocols/>: .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 <https://github.com/Perl\-Toolchain\-Gang/HTTP\-Tiny/issues>. 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 <https://github.com/Perl\-Toolchain\-Gang/HTTP\-Tiny> .PP .Vb 1 \& git clone https://github.com/Perl\-Toolchain\-Gang/HTTP\-Tiny.git .Ve .SH "AUTHORS" .IX Header "AUTHORS" .IP "\(bu" 4 Christian Hansen <chansen@cpan.org> .IP "\(bu" 4 David Golden <dagolden@cpan.org> .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" .IP "\(bu" 4 Alan Gardner <gardner@pythian.com> .IP "\(bu" 4 Alessandro Ghedini <al3xbio@gmail.com> .IP "\(bu" 4 A. Sinan Unur <nanis@cpan.org> .IP "\(bu" 4 Brad Gilbert <bgills@cpan.org> .IP "\(bu" 4 brian m. carlson <sandals@crustytoothpaste.net> .IP "\(bu" 4 Chris Nehren <apeiron@cpan.org> .IP "\(bu" 4 Chris Weyl <cweyl@alumni.drew.edu> .IP "\(bu" 4 Claes Jakobsson <claes@surfar.nu> .IP "\(bu" 4 Clinton Gormley <clint@traveljury.com> .IP "\(bu" 4 Craig A. Berry <craigberry@mac.com> .IP "\(bu" 4 Craig Berry <cberry@cpan.org> .IP "\(bu" 4 David Golden <xdg@xdg.me> .IP "\(bu" 4 David Mitchell <davem@iabyn.com> .IP "\(bu" 4 Dean Pearce <pearce@pythian.com> .IP "\(bu" 4 Edward Zborowski <ed@rubensteintech.com> .IP "\(bu" 4 Felipe Gasper <felipe@felipegasper.com> .IP "\(bu" 4 Graham Knop <haarg@haarg.org> .IP "\(bu" 4 Greg Kennedy <kennedy.greg@gmail.com> .IP "\(bu" 4 James E Keenan <jkeenan@cpan.org> .IP "\(bu" 4 James Raspass <jraspass@gmail.com> .IP "\(bu" 4 Jeremy Mates <jmates@cpan.org> .IP "\(bu" 4 Jess Robinson <castaway@desert\-island.me.uk> .IP "\(bu" 4 Karen Etheridge <ether@cpan.org> .IP "\(bu" 4 Lukas Eklund <leklund@gmail.com> .IP "\(bu" 4 Martin J. Evans <mjegh@ntlworld.com> .IP "\(bu" 4 Martin-Louis Bright <mlbright@gmail.com> .IP "\(bu" 4 Matthew Horsfall <wolfsage@gmail.com> .IP "\(bu" 4 Michael R. Davis <mrdvt92@users.noreply.github.com> .IP "\(bu" 4 Mike Doherty <doherty@cpan.org> .IP "\(bu" 4 Nicolas Rochelemagne <rochelemagne@cpanel.net> .IP "\(bu" 4 Olaf Alders <olaf@wundersolutions.com> .IP "\(bu" 4 Olivier Mengué <dolmen@cpan.org> .IP "\(bu" 4 Petr Písař <ppisar@redhat.com> .IP "\(bu" 4 sanjay-cpu <snjkmr32@gmail.com> .IP "\(bu" 4 Serguei Trouchelle <stro@cpan.org> .IP "\(bu" 4 Shoichi Kaji <skaji@cpan.org> .IP "\(bu" 4 SkyMarshal <skymarshal1729@gmail.com> .IP "\(bu" 4 Sören Kornetzki <soeren.kornetzki@delti.com> .IP "\(bu" 4 Steve Grazzini <steve.grazzini@grantstreet.com> .IP "\(bu" 4 Stig Palmquist <git@stig.io> .IP "\(bu" 4 Syohei \s-1YOSHIDA\s0 <syohex@gmail.com> .IP "\(bu" 4 Tatsuhiko Miyagawa <miyagawa@bulknews.net> .IP "\(bu" 4 Tom Hukins <tom@eborcom.com> .IP "\(bu" 4 Tony Cook <tony@develop\-help.com> .IP "\(bu" 4 Xavier Guimard <yadd@debian.org> .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2023 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/Types::Serialiser.3pm����������������������������������������������������������������������0000444�����������������00000027311�15253012307�0012111 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 <schmorp@schmorp.de> \& http://home.schmorp.de/ .Ve �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/JSON::XS::Boolean.3pm����������������������������������������������������������������������0000444�����������������00000005445�15253012307�0011476 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 <schmorp@schmorp.de> \& http://home.schmorp.de/ .Ve ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/common::sense.3pm��������������������������������������������������������������������������0000444�����������������00000000000�15253012307�0011272 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Tarzip.3pm���������������������������������������������������������������������������0000444�����������������00000004564�15253012307�0010702 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Tarzip 3" .TH CPAN::Tarzip 3 "2020-05-19" "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" CPAN::Tarzip \- internal handling of tar archives for CPAN.pm .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ��������������������������������������������������������������������������������������������������������������������������������������������man/man3/CPAN::Plugin.3pm���������������������������������������������������������������������������0000444�����������������00000006747�15253012307�0010674 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Plugin 3" .TH CPAN::Plugin 3 "2020-05-19" "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" CPAN::Plugin \- Base class for CPAN shell extensions .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& package CPAN::Plugin::Flurb; \& use parent \*(AqCPAN::Plugin\*(Aq; \& \& sub post_test { \& my ($self, $distribution_object) = @_; \& $self = $self\->new (distribution_object => $distribution_object); \& ...; \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" .SS "Alpha Status" .IX Subsection "Alpha Status" The plugin system in the \s-1CPAN\s0 shell was introduced in version 2.07 and is still considered experimental. .SS "How Plugins work?" .IX Subsection "How Plugins work?" See \*(L"Plugin support\*(R" in \s-1CPAN\s0. .SH "METHODS" .IX Header "METHODS" .SS "plugin_requires" .IX Subsection "plugin_requires" returns list of packages given plugin requires for functionality. This list is evaluated using \f(CW\*(C`CPAN\->use_inst\*(C'\fR method. .SS "distribution_object" .IX Subsection "distribution_object" Get current distribution object. .SS "distribution" .IX Subsection "distribution" .SS "distribution_info" .IX Subsection "distribution_info" .SS "build_dir" .IX Subsection "build_dir" Simple delegatees for misc parameters derived from distribution .SS "is_xs" .IX Subsection "is_xs" Predicate to detect whether package contains \s-1XS.\s0 .SH "AUTHOR" .IX Header "AUTHOR" Branislav Zahradnik <barney@cpan.org> �������������������������man/man3/CPAN::Distroprefs.3pm����������������������������������������������������������������������0000444�����������������00000013710�15253012307�0011726 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Distroprefs 3" .TH CPAN::Distroprefs 3 "2020-03-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" CPAN::Distroprefs \-\- read and match distroprefs .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use CPAN::Distroprefs; \& \& my %info = (... distribution/environment info ...); \& \& my $finder = CPAN::Distroprefs\->find($prefs_dir, \e%ext_map); \& \& while (my $result = $finder\->next) { \& \& die $result\->as_string if $result\->is_fatal; \& \& warn($result\->as_string), next if $result\->is_warning; \& \& for my $pref (@{ $result\->prefs }) { \& if ($pref\->matches(\e%info)) { \& return $pref; \& } \& } \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module encapsulates reading Distroprefs and matching them against \s-1CPAN\s0 distributions. .SH "INTERFACE" .IX Header "INTERFACE" .Vb 1 \& my $finder = CPAN::Distroprefs\->find($dir, \e%ext_map); \& \& while (my $result = $finder\->next) { ... } .Ve .PP Build an iterator which finds distroprefs files in the tree below the given directory. Within the tree directories matching \f(CW\*(C`m/^[._]/\*(C'\fR are pruned. .PP \&\f(CW%ext_map\fR is a hashref whose keys are file extensions and whose values are modules used to load matching files: .PP .Vb 5 \& { \& \*(Aqyml\*(Aq => \*(AqYAML::Syck\*(Aq, \& \*(Aqdd\*(Aq => \*(AqData::Dumper\*(Aq, \& ... \& } .Ve .PP Each time \f(CW\*(C`$finder\->next\*(C'\fR is called, the iterator returns one of two possible values: .IP "\(bu" 4 a CPAN::Distroprefs::Result object .IP "\(bu" 4 \&\f(CW\*(C`undef\*(C'\fR, indicating that no prefs files remain to be found .SH "RESULTS" .IX Header "RESULTS" \&\f(CW\*(C`find()\*(C'\fR returns CPAN::Distroprefs::Result objects to indicate success or failure when reading a prefs file. .SS "Common" .IX Subsection "Common" All results share some common attributes: .PP \fItype\fR .IX Subsection "type" .PP \&\f(CW\*(C`success\*(C'\fR, \f(CW\*(C`warning\*(C'\fR, or \f(CW\*(C`fatal\*(C'\fR .PP \fIfile\fR .IX Subsection "file" .PP the file from which these prefs were read, or to which this error refers (relative filename) .PP \fIext\fR .IX Subsection "ext" .PP the file's extension, which determines how to load it .PP \fIdir\fR .IX Subsection "dir" .PP the directory the file was read from .PP \fIabs\fR .IX Subsection "abs" .PP the absolute path to the file .SS "Errors" .IX Subsection "Errors" Error results (warning and fatal) contain: .PP \fImsg\fR .IX Subsection "msg" .PP the error message (usually either \f(CW$!\fR or a \s-1YAML\s0 error) .SS "Successes" .IX Subsection "Successes" Success results contain: .PP \fIprefs\fR .IX Subsection "prefs" .PP an arrayref of CPAN::Distroprefs::Pref objects .SH "PREFS" .IX Header "PREFS" CPAN::Distroprefs::Pref objects represent individual distroprefs documents. They are constructed automatically as part of \f(CW\*(C`success\*(C'\fR results from \f(CW\*(C`find()\*(C'\fR. .PP \fIdata\fR .IX Subsection "data" .PP the pref information as a hashref, suitable for e.g. passing to Kwalify .PP \fImatch_attributes\fR .IX Subsection "match_attributes" .PP returns a list of the valid match attributes (see the Distroprefs section in \s-1CPAN\s0) .PP currently: \f(CW\*(C`env perl perlconfig distribution module\*(C'\fR .PP \fIhas_any_match\fR .IX Subsection "has_any_match" .PP true if this pref has a 'match' attribute at all .PP \fIhas_valid_subkeys\fR .IX Subsection "has_valid_subkeys" .PP true if this pref has a 'match' attribute and at least one valid match attribute .PP \fImatches\fR .IX Subsection "matches" .PP .Vb 1 \& if ($pref\->matches(\e%arg)) { ... } .Ve .PP true if this pref matches the passed-in hashref, which must have a value for each of the \f(CW\*(C`match_attributes\*(C'\fR (above) .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ��������������������������������������������������������man/man3/CPAN::Plugin::Specfile.3pm�����������������������������������������������������������������0000444�����������������00000007264�15253012307�0012526 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN::Plugin::Specfile 3" .TH CPAN::Plugin::Specfile 3 "2020-05-19" "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" CPAN::Plugin::Specfile \- Proof of concept implementation of a trivial CPAN::Plugin .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # once in the cpan shell \& o conf plugin_list push CPAN::Plugin::Specfile \& \& # make permanent \& o conf commit \& \& # any time in the cpan shell to write a spec file \& test Acme::Meta \& \& # disable \& # if it is the last in plugin_list: \& o conf plugin_list pop \& # otherwise, determine the index to splice: \& o conf plugin_list \& # and then use splice, e.g. to splice position 3: \& o conf plugin_list splice 3 1 .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Implemented as a post-test hook, this plugin writes a specfile after every successful test run. The content is also written to the terminal. .PP As a side effect, the timestamps of the written specfiles reflect the linear order of all dependencies. .PP \&\fB\s-1WARNING:\s0\fR This code is just a small demo how to use the plugin system of the \s-1CPAN\s0 shell, not a full fledged spec file writer. Do not expect new features in this plugin. .SS "\s-1OPTIONS\s0" .IX Subsection "OPTIONS" The target directory to store the spec files in can be set using \f(CW\*(C`dir\*(C'\fR as in .PP .Vb 1 \& o conf plugin_list push CPAN::Plugin::Specfile=dir,/tmp/specfiles\-000042 .Ve .PP The default directory for this is the \&\f(CW\*(C`plugins/CPAN::Plugin::Specfile\*(C'\fR directory in the \fIcpan_home\fR directory. .SH "AUTHOR" .IX Header "AUTHOR" Andreas Koenig <andk@cpan.org>, Branislav Zahradnik <barney@cpan.org> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man3/lib::core::only.3pm������������������������������������������������������������������������0000444�����������������00000013011�15253012307�0011457 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "lib::core::only 3" .TH lib::core::only 3 "2017-11-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" lib::core::only \- Remove all non\-core paths from @INC to avoid site/vendor dirs .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use lib::core::only; # now @INC contains only the two core directories .Ve .PP To get only the core directories plus the ones for the local::lib in scope: .PP .Vb 1 \& $ perl \-mlocal::lib \-Mlib::core::only \-Mlocal::lib=~/perl5 myscript.pl .Ve .PP To attempt to do a self-contained build (but note this will not reliably propagate into subprocesses, see the \s-1CAVEATS\s0 below): .PP .Vb 1 \& $ PERL5OPT=\*(Aq\-mlocal::lib \-Mlib::core::only \-Mlocal::lib=~/perl5\*(Aq cpan .Ve .PP Please note that it is necessary to use \f(CW\*(C`local::lib\*(C'\fR twice for this to work. First so that \f(CW\*(C`lib::core::only\*(C'\fR doesn't prevent \f(CW\*(C`local::lib\*(C'\fR from loading (it's not currently in core) and then again after \f(CW\*(C`lib::core::only\*(C'\fR so that the local paths are not removed. .SH "DESCRIPTION" .IX Header "DESCRIPTION" lib::core::only is simply a shortcut to say \*(L"please reduce my \f(CW@INC\fR to only the core lib and archlib (architecture-specific lib) directories of this perl\*(R". .PP You might want to do this to ensure a local::lib contains only the code you need, or to test an App::FatPacker tree, or to avoid known bad vendor packages. .PP You might want to use this to try and install a self-contained tree of perl modules. Be warned that that probably won't work (see \*(L"\s-1CAVEATS\*(R"\s0). .PP This module was extracted from local::lib's \-\-self\-contained feature, and contains the only part that ever worked. I apologise to anybody who thought anything else did. .SH "CAVEATS" .IX Header "CAVEATS" This does \fBnot\fR propagate properly across perl invocations like local::lib's stuff does. It can't. It's only a module import, so it \fBonly affects the specific perl \s-1VM\s0 instance in which you load and \fBimport()\fB it\fR. .PP If you want to cascade it across invocations, you can set the \s-1PERL5OPT\s0 environment variable to '\-Mlib::core::only' and it'll sort of work. But be aware that taint mode ignores this, so some modules' build and test code probably will as well. .PP You also need to be aware that perl's command line options are not processed in order \- \-I options take effect before \-M options, so .PP .Vb 1 \& perl \-Mlib::core::only \-Ilib .Ve .PP is unlike to do what you want \- it's exactly equivalent to: .PP .Vb 1 \& perl \-Mlib::core::only .Ve .PP If you want to combine a core-only \f(CW@INC\fR with additional paths, you need to add the additional paths using \-M options and the lib module: .PP .Vb 1 \& perl \-Mlib::core::only \-Mlib=lib \& \& # or if you\*(Aqre trying to test compiled code: \& \& perl \-Mlib::core::only \-Mblib .Ve .PP For more information on the impossibility of sanely propagating this across module builds without help from the build program, see <http://www.shadowcat.co.uk/blog/matt\-s\-trout/tainted\-love> \- and for ways to achieve the old \-\-self\-contained feature's results, look at App::FatPacker's tree function, and at App::cpanminus's \-\-local\-lib\-contained feature. .SH "AUTHOR" .IX Header "AUTHOR" Matt S. Trout <mst@shadowcat.co.uk> .SH "LICENSE" .IX Header "LICENSE" This library is free software under the same terms as perl itself. .SH "COPYRIGHT" .IX Header "COPYRIGHT" (c) 2010 the lib::core::only \*(L"\s-1AUTHOR\*(R"\s0 as specified above. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man1/cpan.1�������������������������������������������������������������������������������������0000444�����������������00000027470�15253012307�0007164 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN 1" .TH CPAN 1 "2022-04-03" "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" cpan \- easily interact with CPAN from the command line .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # with arguments and no switches, installs specified modules \& cpan module_name [ module_name ... ] \& \& # with switches, installs modules with extra behavior \& cpan [\-cfFimtTw] module_name [ module_name ... ] \& \& # use local::lib \& cpan \-I module_name [ module_name ... ] \& \& # one time mirror override for faster mirrors \& cpan \-p ... \& \& # with just the dot, install from the distribution in the \& # current directory \& cpan . \& \& # without arguments, starts CPAN.pm shell \& cpan \& \& # without arguments, but some switches \& cpan [\-ahpruvACDLOPX] .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This script provides a command interface (not a shell) to \s-1CPAN.\s0 At the moment it uses \s-1CPAN\s0.pm to do the work, but it is not a one-shot command runner for \s-1CPAN\s0.pm. .SS "Options" .IX Subsection "Options" .IP "\-a" 4 .IX Item "-a" Creates a \s-1CPAN\s0.pm autobundle with CPAN::Shell\->autobundle. .IP "\-A module [ module ... ]" 4 .IX Item "-A module [ module ... ]" Shows the primary maintainers for the specified modules. .IP "\-c module" 4 .IX Item "-c module" Runs a `make clean` in the specified module's directories. .IP "\-C module [ module ... ]" 4 .IX Item "-C module [ module ... ]" Show the \fIChanges\fR files for the specified modules .IP "\-D module [ module ... ]" 4 .IX Item "-D module [ module ... ]" Show the module details. This prints one line for each out-of-date module (meaning, modules locally installed but have newer versions on \s-1CPAN\s0). Each line has three columns: module name, local version, and \s-1CPAN\s0 version. .IP "\-f" 4 .IX Item "-f" Force the specified action, when it normally would have failed. Use this to install a module even if its tests fail. When you use this option, \&\-i is not optional for installing a module when you need to force it: .Sp .Vb 1 \& % cpan \-f \-i Module::Foo .Ve .IP "\-F" 4 .IX Item "-F" Turn off \s-1CPAN\s0.pm's attempts to lock anything. You should be careful with this since you might end up with multiple scripts trying to muck in the same directory. This isn't so much of a concern if you're loading a special config with \f(CW\*(C`\-j\*(C'\fR, and that config sets up its own work directories. .IP "\-g module [ module ... ]" 4 .IX Item "-g module [ module ... ]" Downloads to the current directory the latest distribution of the module. .IP "\-G module [ module ... ]" 4 .IX Item "-G module [ module ... ]" \&\s-1UNIMPLEMENTED\s0 .Sp Download to the current directory the latest distribution of the modules, unpack each distribution, and create a git repository for each distribution. .Sp If you want this feature, check out Yanick Champoux's \f(CW\*(C`Git::CPAN::Patch\*(C'\fR distribution. .IP "\-h" 4 .IX Item "-h" Print a help message and exit. When you specify \f(CW\*(C`\-h\*(C'\fR, it ignores all of the other options and arguments. .IP "\-i module [ module ... ]" 4 .IX Item "-i module [ module ... ]" Install the specified modules. With no other switches, this switch is implied. .IP "\-I" 4 .IX Item "-I" Load \f(CW\*(C`local::lib\*(C'\fR (think like \f(CW\*(C`\-I\*(C'\fR for loading lib paths). Too bad \&\f(CW\*(C`\-l\*(C'\fR was already taken. .IP "\-j Config.pm" 4 .IX Item "-j Config.pm" Load the file that has the \s-1CPAN\s0 configuration data. This should have the same format as the standard \fICPAN/Config.pm\fR file, which defines \&\f(CW$CPAN::Config\fR as an anonymous hash. .IP "\-J" 4 .IX Item "-J" Dump the configuration in the same format that \s-1CPAN\s0.pm uses. This is useful for checking the configuration as well as using the dump as a starting point for a new, custom configuration. .IP "\-l" 4 .IX Item "-l" List all installed modules with their versions .IP "\-L author [ author ... ]" 4 .IX Item "-L author [ author ... ]" List the modules by the specified authors. .IP "\-m" 4 .IX Item "-m" Make the specified modules. .IP "\-M mirror1,mirror2,..." 4 .IX Item "-M mirror1,mirror2,..." A comma-separated list of mirrors to use for just this run. The \f(CW\*(C`\-P\*(C'\fR option can find them for you automatically. .IP "\-n" 4 .IX Item "-n" Do a dry run, but don't actually install anything. (unimplemented) .IP "\-O" 4 .IX Item "-O" Show the out-of-date modules. .IP "\-p" 4 .IX Item "-p" Ping the configured mirrors and print a report .IP "\-P" 4 .IX Item "-P" Find the best mirrors you could be using and use them for the current session. .IP "\-r" 4 .IX Item "-r" Recompiles dynamically loaded modules with CPAN::Shell\->recompile. .IP "\-s" 4 .IX Item "-s" Drop in the \s-1CPAN\s0.pm shell. This command does this automatically if you don't specify any arguments. .IP "\-t module [ module ... ]" 4 .IX Item "-t module [ module ... ]" Run a `make test` on the specified modules. .IP "\-T" 4 .IX Item "-T" Do not test modules. Simply install them. .IP "\-u" 4 .IX Item "-u" Upgrade all installed modules. Blindly doing this can really break things, so keep a backup. .IP "\-v" 4 .IX Item "-v" Print the script version and \s-1CPAN\s0.pm version then exit. .IP "\-V" 4 .IX Item "-V" Print detailed information about the cpan client. .IP "\-w" 4 .IX Item "-w" \&\s-1UNIMPLEMENTED\s0 .Sp Turn on cpan warnings. This checks various things, like directory permissions, and tells you about problems you might have. .IP "\-x module [ module ... ]" 4 .IX Item "-x module [ module ... ]" Find close matches to the named modules that you think you might have mistyped. This requires the optional installation of Text::Levenshtein or Text::Levenshtein::Damerau. .IP "\-X" 4 .IX Item "-X" Dump all the namespaces to standard output. .SS "Examples" .IX Subsection "Examples" .Vb 2 \& # print a help message \& cpan \-h \& \& # print the version numbers \& cpan \-v \& \& # create an autobundle \& cpan \-a \& \& # recompile modules \& cpan \-r \& \& # upgrade all installed modules \& cpan \-u \& \& # install modules ( sole \-i is optional ) \& cpan \-i Netscape::Booksmarks Business::ISBN \& \& # force install modules ( must use \-i ) \& cpan \-fi CGI::Minimal URI \& \& # install modules but without testing them \& cpan \-Ti CGI::Minimal URI .Ve .SS "Environment variables" .IX Subsection "Environment variables" There are several components in \s-1CPAN\s0.pm that use environment variables. The build tools, ExtUtils::MakeMaker and Module::Build use some, while others matter to the levels above them. Some of these are specified by the Perl Toolchain Gang: .PP Lancaster Consensus: <https://github.com/Perl\-Toolchain\-Gang/toolchain\-site/blob/master/lancaster\-consensus.md> .PP Oslo Consensus: <https://github.com/Perl\-Toolchain\-Gang/toolchain\-site/blob/master/oslo\-consensus.md> .IP "\s-1NONINTERACTIVE_TESTING\s0" 4 .IX Item "NONINTERACTIVE_TESTING" Assume no one is paying attention and skips prompts for distributions that do that correctly. \f(CWcpan(1)\fR sets this to \f(CW1\fR unless it already has a value (even if that value is false). .IP "\s-1PERL_MM_USE_DEFAULT\s0" 4 .IX Item "PERL_MM_USE_DEFAULT" Use the default answer for a prompted questions. \f(CWcpan(1)\fR sets this to \f(CW1\fR unless it already has a value (even if that value is false). .IP "\s-1CPAN_OPTS\s0" 4 .IX Item "CPAN_OPTS" As with \f(CW\*(C`PERL5OPT\*(C'\fR, a string of additional \f(CWcpan(1)\fR options to add to those you specify on the command line. .IP "\s-1CPANSCRIPT_LOGLEVEL\s0" 4 .IX Item "CPANSCRIPT_LOGLEVEL" The log level to use, with either the embedded, minimal logger or Log::Log4perl if it is installed. Possible values are the same as the \f(CW\*(C`Log::Log4perl\*(C'\fR levels: \f(CW\*(C`TRACE\*(C'\fR, \f(CW\*(C`DEBUG\*(C'\fR, \f(CW\*(C`INFO\*(C'\fR, \f(CW\*(C`WARN\*(C'\fR, \&\f(CW\*(C`ERROR\*(C'\fR, and \f(CW\*(C`FATAL\*(C'\fR. The default is \f(CW\*(C`INFO\*(C'\fR. .IP "\s-1GIT_COMMAND\s0" 4 .IX Item "GIT_COMMAND" The path to the \f(CW\*(C`git\*(C'\fR binary to use for the Git features. The default is \f(CW\*(C`/usr/local/bin/git\*(C'\fR. .SH "EXIT VALUES" .IX Header "EXIT VALUES" The script exits with zero if it thinks that everything worked, or a positive number if it thinks that something failed. Note, however, that in some cases it has to divine a failure by the output of things it does not control. For now, the exit codes are vague: .PP .Vb 1 \& 1 An unknown error \& \& 2 The was an external problem \& \& 4 There was an internal problem with the script \& \& 8 A module failed to install .Ve .SH "TO DO" .IX Header "TO DO" * one shot configuration values from the command line .SH "BUGS" .IX Header "BUGS" * none noted .SH "SEE ALSO" .IX Header "SEE ALSO" Most behaviour, including environment variables and configuration, comes directly from \s-1CPAN\s0.pm. .SH "SOURCE AVAILABILITY" .IX Header "SOURCE AVAILABILITY" This code is in Github in the \s-1CPAN\s0.pm repository: .PP .Vb 1 \& https://github.com/andk/cpanpm .Ve .PP The source used to be tracked separately in another GitHub repo, but the canonical source is now in the above repo. .SH "CREDITS" .IX Header "CREDITS" Japheth Cleaver added the bits to allow a forced install (\-f). .PP Jim Brandt suggest and provided the initial implementation for the up-to-date and Changes features. .PP Adam Kennedy pointed out that \fBexit()\fR causes problems on Windows where this script ends up with a .bat extension .SH "AUTHOR" .IX Header "AUTHOR" brian d foy, \f(CW\*(C`<bdfoy@cpan.org>\*(C'\fR .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2001\-2015, brian d foy, All Rights Reserved. .PP You may redistribute this under the same terms as Perl itself. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������man/man1/cpan-mirrors.1�����������������������������������������������������������������������������0000444�����������������00000014770�15253012307�0010656 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 "CPAN-MIRRORS 1" .TH CPAN-MIRRORS 1 "2018-09-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" cpan\-mirrors \- Find the fatest CPAN mirrors nearby .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& % cpan\-mirrors \& \& Testing Africa \& is.co.za \-> 733.72 ms \& wa.co.za \-> 601.56 ms \& ucu.ac.ug \-> 407.99 ms \& mirror.ac.za \-> 614.05 ms \& zol.co.zw \-> 612.57 ms \& \-\->median time: 612.57 ms \& Testing Oceania \& serversaustralia.com.au \-> 38.62 ms \& cpan.inspire.net.nz \-> 67.81 ms \& digitalpacific.com.au \-> 37.89 ms \& uber.com.au \-> 44.47 ms \& lagoon.nc \-> 67.49 ms \& \-\->median time: 44.47 ms \& Testing North America \& httpupdate40.cpanel.net \-> 254.00 ms \& httpupdate35.cpanel.net \-> 409.75 ms \& mirrors.sonic.net \-> 368.56 ms \& httpupdate8.cpanel.net \-> 409.10 ms \& cpan.cs.utah.edu \-> 408.00 ms \& \-\->median time: 408.00 ms \& Testing Asia \& vinahost.vn \-> 146.10 ms \& yazd.ac.ir \-> 469.29 ms \& mirrors\-ru.go\-parts.com \-> 367.09 ms \& sohu.com \-> 399.76 ms \& neolabs.kz \-> 610.92 ms \& \-\->median time: 399.76 ms \& Testing South America \& mmgdesigns.com.ar \-> 407.96 ms \& nbtelecom.com.br \-> 401.96 ms \& sunsite.dcc.uchile.cl \-> 415.69 ms \& linorg.usp.br \-> 424.65 ms \& unal.edu.co \-> 407.60 ms \& \-\->median time: 407.96 ms \& Testing Europe \& uk2.net \-> 409.37 ms \& ambiweb.de \-> 710.65 ms \& bibleonline.ru \-> 471.49 ms \& rol.ru \-> 469.70 ms \& rub.de \-> 346.57 ms \& \-\->median time: 469.70 ms \& Median result by continent: \& 44 ms Oceania \& 400 ms Asia \& 408 ms South America \& 408 ms North America \& 470 ms Europe \& 613 ms Africa \& Best continent is Oceania \& cpan.catalyst.net.nz = 78.8369178771973 ms \& cpan.inspire.net.nz = 69.4258213043213 ms \& cpan.mirrors.ilisys.com.au = 50.2209663391113 ms \& digitalpacific.com.au = 40.1251316070557 ms \& lagoon.nc = 88.8760089874268 ms \& nautile.nc = 65.7081604003906 ms \& optusnet.com.au = 41.4729118347168 ms \& serversaustralia.com.au = 46.1521148681641 ms \& uber.com.au = 48.2730865478516 ms \& waia.asn.au = 86.2929821014404 ms \& webtastix.net = 70.5790519714355 ms \& Best mirrors are digitalpacific.com.au \& optusnet.com.au \& serversaustralia.com.au \& uber.com.au \& cpan.mirrors.ilisys.com.au \& \& Best urls are \& http://cpan.mirror.digitalpacific.com.au/ \& http://mirror.optusnet.com.au/CPAN/ \& http://cpan.mirror.serversaustralia.com.au/ \& http://cpan.mirror.uber.com.au/ \& http://cpan.mirrors.ilisys.com.au/ .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1CPAN\s0 Mirrors come and go, and maybe you do too. The mirror that was fast then might not be fast now, especially if you changed hemispheres. .PP This program goes through the \fI\s-1MIRRORED.BY\s0\fR file and pings a selection of mirrors on each continent to find the fastest mirrors. From the best continent, it samples several mirrors to find the \s-1URL\s0 you should add to your configuration. .PP If you don't have a \fI\s-1MIRRORED.BY\s0\fR file, this program will download one for you. It looks through your existing \f(CW\*(C`urllist\*(C'\fR configuration and then default locations. It stores it in \f(CW\*(C`~/.cpan\*(C'\fR (or your configured location to store files). .SH "TO DO" .IX Header "TO DO" .IP "\(bu" 4 Add an option to update the \s-1CPAN\s0 configuration .IP "\(bu" 4 Add an option to give \s-1JSON\s0 output .SH "AUTHOR" .IX Header "AUTHOR" brian d foy \f(CW\*(C`<bdfoy@cpan.org>\*(C'\fR .SH "LICENSE" .IX Header "LICENSE" This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP See <http://www.perl.com/perl/misc/Artistic.html> ��������man/man1/json_xs.1����������������������������������������������������������������������������������0000444�����������������00000020407�15253012307�0007717 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" 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 <isitreally.json .Ve .PP \&\*(L"\s-1JSON\s0 Lint\*(R" \- tries to parse the file \fIisitreally.json\fR as \s-1JSON\s0 \- if it is valid \s-1JSON,\s0 the command outputs nothing, otherwise it will print an error message and exit with non-zero exit status. .PP .Vb 1 \& <src.json json_xs >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 <file .Ve .PP Read the serialised Storable file \fIfile\fR and print a human-readable \s-1JSON\s0 version of it to \s-1STDOUT.\s0 .PP .Vb 1 \& json_xs \-f storable\-file \-t yaml <file .Ve .PP Same as above, but write \s-1YAML\s0 instead (not using \s-1JSON\s0 at all :) .PP .Vb 1 \& json_xs \-f none \-e \*(Aq$_ = [1, 2, 3]\*(Aq .Ve .PP Dump the perl array as \s-1UTF\-8\s0 encoded \s-1JSON\s0 text. .PP .Vb 1 \& <torrentfile json_xs \-f bencode \-e \*(Aq$_ = join "\en", map @$_, @{$_\->{"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 <json@schmorp.de> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/THANKS�������������������������������������������������������������������������������0000644�����������������00000126452�15253042577�0010267 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� This project has been alive for many years. Countless people have provided feedback that have improved curl. Here follows a list of people that have contributed (a-z order). If you have contributed but are missing here, please let us know! 0xee on github 0xflotus on github 12932 on github 1337vt on github 1ocalhost on github 3dyd on github 3eka on github 8U61ife on github a1346054 on github Aaro Koskinen Aaron Oneal Aaron Orenstein Aaron Scarisbrick aasivov on github Abhinav Singh Abram Pousada accountantM on github AceCrow on Github ad0p on github Adam Averay Adam Barclay Adam Brown Adam Coyne Adam D. Moss Adam Langley Adam Light Adam Marcionek Adam Piggott Adam Rosenfield Adam Sampson Adam Tkac Adnan Khan adnn on github Adrian Burcea Adrian Peniak Adrian Schuur Adriano Meirelles afrind on github Aftab Alam ahodesuka on github ajak in #curl Ajit Dhumale Akhil Kedia Aki Koskinen Akos Pasztory Akshay Vernekar Alain Danteny Alain Miniussi Alan Jenkins Alan Pinstein Albert Chin-A-Young Albert Choy Albin Vass Alejandro Alvarez Ayllon Alejandro Colomar Alejandro R. Sedeño Aleksandar Milivojevic Aleksander Mazur Aleksandr Krotov Aleksey Tulinov Ales Mlakar Ales Novak Alessandro Ghedini Alessandro Vesely Alex aka WindEagle Alex Baines Alex Bligh Alex Chan Alex Crichton Alex Fishman Alex Gaynor Alex Grebenschikov Alex Gruz Alex Kiernan Alex Konev Alex Malinovich Alex Mayorga Alex McLellan Alex Neblett Alex Nichols Alex Potapenko Alex Rousskov Alex Samorukov Alex Suykov Alex Vinnik Alex Xu Alexander Beedie Alexander Chuykov Alexander Dyagilev Alexander Elgert Alexander Kanavin Alexander Klauer Alexander Kourakos Alexander Krasnostavsky Alexander Lazic Alexander Pepper Alexander Peslyak Alexander Sinditskiy Alexander Traud Alexander V. Tikhonov Alexander Zhuravlev Alexandre Bury Alexandre Ferrieux Alexandre Pion Alexey Borzov Alexey Eremikhin Alexey Melnichuk Alexey Pesternikov Alexey Savchuk Alexey Simak Alexey Zakhlestin Alexis Carvalho Alexis La Goutte Alexis Vachette Alfonso Martone Alfred Gebert Ali Khodkar Ali Utku Selen ALittleDruid on github Allen Pulsifer Alois Klink Alona Rossen Amaury Denoyelle amishmm on github Amit Katyal Amol Pattekar Amr Shahin Anatol Belski Anatoli Tubman Anders Bakken Anders Berg Anders Gustafsson Anders Havn Anders Roxell Anderson Sasaki Anderson Toshiyuki Sasaki Andi Jahja Andre Guibert de Bruet Andre Heinecke Andrea Pappacoda Andreas Damm Andreas Falkenhahn Andreas Farber Andreas Fischer Andreas Huebner Andreas Kostyrka Andreas Malzahn Andreas Ntaflos Andreas Olsson Andreas Rieke Andreas Roth Andreas Schneider Andreas Schuldei Andreas Sommer Andreas Streichardt Andreas Wurf Andrei Benea Andrei Bica Andrei Cipu Andrei Karas Andrei Kurushin Andrei Neculau Andrei Rybak Andrei Sedoi Andrei Valeriu BICA Andrei Virtosu Andrej E Baranov Andrew Barnert Andrew Barnes Andrew Benham Andrew Biggs Andrew Bushnell Andrew de los Reyes Andrew Francis Andrew Fuller Andrew Ishchuk Andrew Krieger Andrew Kurushin Andrew Lambert Andrew Moise Andrew Potter Andrew Robbins Andrew Wansink Andrey Alifanov Andrey Gursky Andrey Labunets Andrii Moiseiev Andrius Merkys Andrés García Andy Alt Andy Cedilnik Andy Fiddaman Andy Serpa Andy Stamp Andy Tsouladze Angus Mackay anio on github anon00000000 on github anshnd on github Anssi Kolehmainen Antarpreet Singh Anthon Pang Anthony Avina Anthony Bryan Anthony G. Basile Anthony Hu Anthony Ramine Anthony Shaw Antoine Aubert Antoine Calando Antoine du Hamel Antoine Pietri Antoine Pitrou Anton Bychkov Anton Gerasimov Anton Kalmykov Anton Malov Anton Yabchinskiy Antoni Villalonga Antonio Larrosa Antony74 on github Antti Hätälä April King arainchik on github Archangel_SDY on github Arkadiusz Miskiewicz Armel Asselin Arnaud Compan Arnaud Ebalard Arnaud Rebillout Arne Soete Aron Bergman Aron Rotteveel Artak Galoyan Arthur Murray Artur Sinila Arve Knudsen Arvid Norberg arvids-kokins-bidstack on github asavah on github Ashish Shukla Ashwin Metpalli Ask Bjørn Hansen Askar Safin AtariDreams on github Ates Goral atjg on github Augustus Saunders Austin Green Avery Fay awesomenode on github Axel Chong Axel Morawietz Axel Tillequin Ayesh Karunaratne Ayoub Boudhar Ayushman Singh Chauhan b9a1 on github Bachue Zhou Baitinq on github Balaji Parasuram Balaji S Rao Balaji Salunke Balakrishnan Balasubramanian Balazs Kovacsics Balint Szilakszi Barry Abrahamson Barry Pollard Bart Whiteley Baruch Siach Bas Mevissen Bas van Schaik Bastian Krause Bastien Bouclet Basuke Suzuki baumanj on github bdry on github beckenc on github Ben Boeckel Ben Darnell Ben Fritz Ben Greear Ben Kohler Ben Madsen Ben Noordhuis Ben Van Hof Ben Voris Ben Winslow Benau on github Benbuck Nason Benjamin Gerard Benjamin Gilbert Benjamin Johnson Benjamin Kircher Benjamin Loison Benjamin Riefenstahl Benjamin Ritcey Benjamin Sergeant Benoit Neil Benoit Sigoure Bernard Leak Bernard Spil Bernat Mut Bernd Mueller Bernhard Iselborn Bernhard M. Wiedemann Bernhard Reutner-Fischer Bernhard Walle Bert Huijben Bertrand Demiddelaer Bertrand Simonnet beslick5 on github Bevan Weiss Bill Doyle Bill Egert Bill Hoffman Bill Middlecamp Bill Nagel Bill Pyne billionai on github Billyzou0741326 on github Bin Lan Bin Meng Biswapriyo Nath Bjarni Ingi Gislason Bjoern Franke Bjoern Sikora Bjorn Augustsson Bjorn Reese Björn Stenberg Blaise Potard Blake Burkhart bnfp on github Bo Anderson Bob Relyea Bob Richmond Bob Schader bobmitchell1956 on github Bodo Bergmann Bogdan Nicula Boris Kuschel Boris Okunskiy Boris Rasin Boris Verkhovskiy Brad Burdick Brad Fitzpatrick Brad Forschinger Brad Harder Brad Hards Brad King Brad Spencer Bradford Bruce bramus on github Brandon Casey Brandon Dong Brandon Wang BratSinot on github Brendan Jurd Brent Beardsley Brian Akins Brian Bergeron Brian Carpenter Brian Chaplin Brian Childs Brian Chrisman Brian Dessent Brian E. Gallew Brian Green Brian Inglis Brian J. Murrell Brian Lund Brian Nixon Brian Prodoehl Brian R Duffy Brian Ulm Brock Noland Bru Rom Bruce Mitchener Bruce Stephens BrumBrum on hackerone Bruno Baguette Bruno de Carvalho Bruno Grasselli Bruno Henrique Batista Cruz da Silva Bruno Thomsen Bryan Henderson Bryan Kemp bsammon on github bsergean on github Bubu on github buzo-ffm on github bxac on github Bylon2 on github Byrial Jensen Caleb Raitto Calvin Buckley Cameron Blomquist Cameron Cawley Cameron Kaiser Cameron MacMinn Cameron Will Camille Moncelier Cao ZhenXiang Caolan McNamara Captain Basil Carie Pointer Carl Zogheib Carlo Alberto Carlo Cannas Carlo Marcelo Arenas Belón Carlo Teubner Carlo Wood Carlos ORyan Carsten Lange Casey Bodley Casey O'Donnell Catalin Patulea causal-agent on github cbartl on github cclauss on github Cering on github Cesar Eduardo Barros Chad Monroe Chandrakant Bagul Charles Cazabon Charles Kerr Charles Romestant Chen Prog Cherish98 on github Chester Liu Chih-Chung Chang Chih-Hsuan Yen Chilledheart on github Chloe Kudryavtsev Chris "Bob Bob" Chris Araman Chris Carlmar Chris Combes Chris Conlon Chris Deidun Chris Faherty Chris Flerackers Chris Gaukroger Chris Maltby Chris Mumford Chris Paulson-Ellis Chris Roberts Chris Smowton Chris Talbot Chris Young Christian Fillion Christian Grothoff Christian Heimes Christian Hesse Christian Hägele Christian Krause Christian Kurz Christian Robottom Reis Christian Schmitz Christian Stewart Christian Vogt Christian Weisgerber Christoph Krey Christoph M. Becker Christoph Reiter Christophe Demory Christophe Dervieux Christophe Legry Christopher Conroy Christopher Degawa Christopher Head Christopher Palow Christopher R. Palmer Christopher Reid Christopher Sauer Christopher Stone Chungtsun Li Ciprian Badescu civodul on github Claes Jakobsson Clarence Gardner Claudio Neves clbr on github Clemens Gruber Cliff Crosland Clifford Wolf Clint Clayton Cloudogu Siebels Clément Notin cmfrolick on github codesniffer13 on github Cody Jones Cody Mack COFFEETALES on github coinhubs on github Colby Ranger Colin Blair Colin Cross Colin Hogben Colin Leroy Colin O'Dell Colin Watson Colm Buckley Colman Mbuya Constantine Sapuntzakis coralw on github correctmost on github Cory Benfield Cory Nelson Costya Shulyupin Craig A West Craig Andrews Craig Davison Craig de Stigter Craig Markwardt crazydef on github Cris Bailiff Cristian Greco Cristian Morales Vega Cristian Rodríguez Curt Bogmine Cynthia Coan Cyril B Cyrill Osterwalder Cédric Connes Cédric Deltheil D. Flinkmann d4d on hackerone d912e3 on github Da-Yoon Chung daboul on github Dag Ekengren Dagobert Michelsen Daiki Ueno Dair Grant Dambaev Alexander Damian Dixon Damien Adant Damien Vielpeau Damien Walsh Dan Becker Dan Cristian Dan Donahue Dan Fandrich Dan Frandrich Dan Johnson Dan Kenigsberg Dan Locks Dan McNulty Dan Nelson Dan Petitt Dan Torop Dan Zitter Daniel at touchtunes Daniel Bankhead Daniel Black Daniel Carpenter Daniel Cater Daniel Egger Daniel Faust Daniel Gustafsson Daniel Hallberg Daniel Hwang Daniel Jeliński Daniel Johnson Daniel Kahn Gillmor Daniel Katz Daniel Krügler Daniel Kurečka Daniel Lee Hwang Daniel Lublin Daniel Marjamäki Daniel Melani Daniel Mentz Daniel Romero Daniel Schauenberg Daniel Seither Daniel Shahaf Daniel Silverstone Daniel Steinberg Daniel Stenberg Daniel Theron Daniel Valenzuela Daniel Woelfel Daphne Luong Dario Nieuwenhuis Dario Weißer Darryl House Darshan Mody Darío Hereñú dasimx on github Dave Dribin Dave Halbakken Dave Hamilton Dave May Dave Reisner Dave Thompson Dave Vasilevsky Davey Shafik David Bau David Benjamin David Binderman David Blaikie David Bohman David Byron David Carlier David Cohen David Cook David Demelier David E. Narváez David Earl David Eriksson David Garske David Goerger David Houlder David Hu David Hull David J Meyer David James David Kalnischkies David Kierznowski David Kimdon David L. David Lang David LeBlanc David Lopes David Lord David McCreedy David McLaughlin David Odin David Phillips David Rosenstrauch David Ryskalczyk David Sanderson David Schweikert David Shaw David Strauss David Tarendash David Thiel David Walser David Woodhouse David Wright David Yan Davide Cassioli davidedec on github dbrowndan on github dEajL3kA on github Deal(一线灵) dekerser on github dengjfzh on github Dengminwen Denis Baručić Denis Chaplygin Denis Feklushkin Denis Goleshchikhin Denis Laxalde Denis Ollier Dennis Clarke Dennis Felsing Derek Higgins Derzsi Dániel Desmond O. Chang destman on github Detlef Schmier Dheeraj Sangamkar Didier Brisebourg Diego Bes Diego Casorran Dietmar Hauser Dilyan Palauzov Dima Barsky Dima Pasechnik Dima Tisnek Dimitar Boevski Dimitre Dimitrov Dimitrios Apostolou Dimitrios Siganos Dimitris Sarris Dinar Diogo Teles Sant'Anna Dion Williams Dirk Eddelbuettel Dirk Feytons Dirk Manske Dirk Rosenkranz Dirk Wetter Dirkjan Bussink Diven Qi divinity76 on github Divy Le Ray dkjjr89 on github dkwolfe4 on github Dmitri Shubin Dmitri Tikhonov Dmitriy Sergeyev dmitrmax on github Dmitry Atamanov Dmitry Bartsevich Dmitry Eremin-Solenikov Dmitry Falko Dmitry Karpov Dmitry Kostjuchenko Dmitry Kurochkin Dmitry Mikhirev Dmitry Popov Dmitry Rechkin Dmitry S. Baikov Dmitry Wagin dnivras on github Dolbneff A.V Domen Kožar Domenico Andreoli Dominick Meglio Dominik Hölzl Dominik Klemba Dominik Thalhammer Dominique Leuenberger Don J Olmstead Dongliang Mu Doron Behar Doug Kaufman Doug Porter Douglas Creager Douglas E. Wegscheid Douglas Kilpatrick Douglas Mencken Douglas R. Horner Douglas R. Reno Douglas Steinwand Dov Murik dpull on github Drake Arconis dtmsecurity on github Duane Cathey Duncan Mac-Vicar Prett Duncan Wilcox Dustin Boswell Dustin Howett Dusty Mabe Duy Phan Thanh Dwarakanath Yadavalli Dylan Anthony Dylan Ellicott Dylan Salisbury Dániel Bakai eaglegai on github Early Ehlinger Earnestly on github Eason-Yu on github Ebe Janchivdorj ebejan on github Ebenezer Ikonne Ed Morley Eddie Lumpkin Edgaras Janušauskas Edin Kadribasic Edmond Yu Edoardo Lolletti Eduard Bloch Edward Kimmel Edward Rudd Edward Sheldrake Edward Thomson Eelco Dolstra Eetu Ojanen Egon Eckert Egor Pugin Ehren Bendler Eldar Zaitov elelel on github elephoenix on github Eli Schwartz Elia Tufarolo Elliot Saba Ellis Pritchard Elmira A Semenova Elms Eloy Degen elsamuko on github emanruse on github Emanuele Bovisio Emanuele Torre Emil Engler Emil Lerner Emil Romanus Emil Österlund Emiliano Ida Emilio Cobos Álvarez Emilio López Emmanuel Tychon Enrico Scholz Enrik Berkhan Eramoto Masaya Eric Cooper Eric Curtin Eric Gallager Eric Hu Eric Landes Eric Lavigne Eric Lubin Eric Melville Eric Mertens Eric Musser Eric Rautman Eric Rescorla Eric Ridge Eric Rosenquist Eric S. Raymond Eric Sauvageau Eric Thelin Eric Vergnaud Eric Vigeant Eric Wong Eric Wu Eric Young Erick Nuwendam Erik Jacobsen Erik Janssen Erik Johansson Erik Minekus Erik Olsson Erik Stenlund Ernest Beinrohr Ernst Sjöstrand Erwan Legrand Erwin Authried Esdras de Morais da Silva Estanislau Augé-Pujadas Ethan Glasser Camp Etienne Simard Eugene Kotlyarov Evan Jordan Evangelos Foutras Even Rouault Evert Pot Evgeny Grin (Karlson2k) Evgeny Turnaev eXeC64 on github Eygene Ryabinkin Eylem Ugurel Fabian Fischer Fabian Frank Fabian Hiernaux Fabian Keil Fabian Ruff Fabian Yamaguchi Fabrice Fontaine Fabrizio Ammollo Fahim Chandurwala Faizur Rahman Farzin on github Fata Nugraha Fawad Mirza fds242 on github Federico Bianchi Federico Pellegrin Fedor Karpelevitch Fedor Korotkov FeignClaims on github Feist Josselin Felipe Gasper Felix Hädicke Felix Kaiser Felix von Leitner Felix Yan Feng Tu Fernando Muñoz Filip Lundgren Filip Salomonsson finkjsc on github Firefox OS Flameborn on github Flavio Medeiros Florian Kohnhäuser Florian Pritz Florian Schoppmann Florian Van Heghe Florian Weimer Florin Petriuc Forrest Cahoon Francisco Moraes Francisco Munoz Francisco Olarte Francisco Sedano Francois Petitjean Francois Rivard Frank Denis Frank Gevaerts Frank Hempel Frank Keeney Frank McGeough Frank Meier Frank Ticheler Frank Van Uffelen František Kučera François Charlier François Michel François Rigault Frazer Smith Fred Machado Fred New Fred Noz Fred Stluka Frederic Lepied Frederik B Frederik Wedel-Heinen Fredrik Thulin FuccDucc on github Fujii Hironori fullincome on github fundawang on github Gabriel Kuri Gabriel Simmer Gabriel Sjoberg Gambit Communications Ganesh Kamath gaoxingwang on github Garrett Holmstrom Garrett Squire Gary Maxwell Gaurav Malhotra Gautam Kachroo Gautam Mani Gavin Wong Gavrie Philipson Gaz Iqbal Gaël Portay gclinch on github Gealber Morales Geeknik Labs Geoff Beier Georeth Zhou Georg Horn Georg Huettenegger Georg Lippitsch Georg Wicherski George Liu Gerd v. Egidy Gergely Nagy Gerhard Herre Gerrit Bruchhäuser Gerrit Renker Ghennadi Procopciuc Giancarlo Formicuccia Giaslas Georgios Gil Weber Gilad Gilbert Ramirez Jr. Gilles Blanc Gilles Vollant Giorgos Oikonomou Gisle Vanem git-bruh on github GitYuanQu on github Giuseppe Attardi Giuseppe D'Ambrosio Giuseppe Persico Gleb Ivanovsky Glen A Johnson Jr. Glen Nakamura Glen Scott Glenn de boer Glenn Sheridan Glenn Strauss godmar on github Godwin Stewart Google Inc. Gordon Marler Gorilla Maguila Gou Lingfeng Graham Campbell Grant Erickson Grant Pannell Greg Hewgill Greg Morse Greg Onufer Greg Pratt Greg Rowe Greg Zavertnik Gregor Jasny Gregory Jefferis Gregory Muchka Gregory Nicholls Gregory Panakkal Gregory Szorc Griffin Downs Grigory Entin Grisha Levit Guenole Bescon Guido Berhoerster Guillaume Arluison guitared on github Gunamoi Software Gunter Knauf Gustaf Hui Gustavo Grieco Guy Poizat GwanYeong Kim Gwen Shapira Gwenole Beauchesne Gökhan Şengün Götz Babin-Ebell h1zzz on github H3RSKO on github Hagai Auro Haibo Huang Hamish Mackenzie hamstergene on github Han Han Han Qiao Hang Kin Lau Hang Su Hannah Schierling Hannes Magnusson Hanno Böck Hanno Kranzhoff Hans Steegers Hans-Christian Noren Egtvedt Hans-Jurgen May Hao Wu Hardeep Singh Haris Okanovic Harold Stuart Harry Sarson Harry Sintonen Harshal Pradhan Hauke Duden Hayden Roche He Qin Heikki Korpela Heinrich Ko Heinrich Schaefer Helge Klein Helmut K. C. Tessarek Helwing Lutz Hendrik Visage Henning Schild Henri Gomez Henrik Gaßmann Henrik Holst Henrik Storner Henry Ludemann Henry Roeland Herve Amblard HexTheDragon Hide Ishikawa Hidemoto Nakada highmtworks on github Himanshu Gupta Hind Montassif Hiroki Kurosawa Hirotaka Tagawa Ho-chi Chen Hoi-Ho Chan Hongli Lai Hongyi Zhao Howard Blaise Howard Chu hsiao yi htasta on github Hubert Kario Hugh Macdonald Hugo van Kemenade humbleacolyte Huzaifa Sidhpurwala huzunhao on github hydra3333 on github Hzhijun iammrtau on github Ian Blanes Ian D Allen Ian Fette Ian Ford Ian Gulliver Ian Lynagh Ian Spence Ian Turner Ian Wilkes Ignacio Vazquez-Abrams Igor Franchuk Igor Khristophorov Igor Makarov Igor Novoseltsev Igor Polyakov Igor Todorovski Ihor Karpenko ihsinme on github Iida Yosiaki Ikko Ashimine Ilguiz Latypov Ilja van Sprundel Illarion Taev illusory-dream on github Ilmari Lauhakangas Ilya Kosarev imilli on github Immanuel Gregoire ImpatientHippo on GitHub Inca R infinnovation-dev on github Ingmar Runge Ingo Ralf Blum Ingo Wilken Inho Oh Ionuț-Francisc Oancea Irfan Adilovic Ironbars13 on github Irving Wolfe Isaac Boukris Isaiah Norton Ishan SinghLevett Ithubg on github Ivan Avdeev Ivan Tsybulin IvanoG on github Ivo Bellin Salarin iz8mbw on github J. Bromley Jack Boos Yu Jack Zhang Jackarain on github JackBoosY on github Jacky Lam Jacob Barthelmeh Jacob Hoffman-Andrews Jacob Meuser Jacob Moshenko Jacob Tolar Jactry Zeng Jad Chamcham Jaime Fullaondo jakirkham on github Jakob Hirsch Jakub Bochenski Jakub Wilk Jakub Zakrzewski James Atwill James Brown James Bursa James Cheng James Clancy James Cone James Dury James Fuller James Gallagher James Griffiths James Housley James Keast James Knight James Le Cuirot James Lucas James MacMillan James Slaughter Jamie Lokier Jamie Newton Jamie Wilkinson Jan Alexander Steffens Jan Chren Jan Ehrhardt Jan Engelhardt Jan Koen Annot Jan Kunder Jan Macku Jan Mazur Jan Schaumann Jan Schmidt Jan Van Boghout Jan Venekamp Jan Verbeek Jan-Piet Mens JanB on github Janne Blomqvist Janne Johansson Jared Jennings Jared Lundell Jari Aalto Jari Sundell jasal82 on github Jason Baietto Jason Glasgow Jason Juang Jason Lee Jason Liu Jason McDonald Jason S. Priebe Javier Barroso Javier Blazquez Javier G. Sogo Javier Navarro Javier Sixto Jay Austin Jay Dommaschk Jayesh A Shah Jaz Fresh jbgoog on github Jean Fabrice Jean Gressmann Jean Jacques Drouin Jean-Claude Chauve Jean-Francois Bertrand Jean-Francois Durand Jean-Louis Lemaire Jean-Marc Ranger Jean-Noël Rouvignac Jean-Philippe Barrette-LaPierre Jean-Philippe Menil Jeff Connelly Jeff Hodges Jeff Johnson Jeff King Jeff Lawson Jeff Luszcz Jeff Mears Jeff Phillips Jeff Pohlmeyer Jeff Weber Jeffrey Tolar Jeffrey Walton jeffrson on github Jelle van der Waa Jenny Heino Jens Finkhaeuser Jens Rantil Jens Schleusener Jeremie Rapin Jeremy Falcon Jeremy Friesner Jeremy Huddleston Jeremy Lainé Jeremy Lin Jeremy Maitin-Shepard Jeremy Pearson Jeremy Tan Jeremy Thibault Jeroen Koekkoek Jeroen Ooms Jerome Mao Jerome Muffat-Meridol Jerome Robert Jerome St-Louis Jerome Vouillon Jerry Krinock Jerry Wu Jes Badwal Jesper Jensen Jesse Chisholm Jesse Noller Jesse Tan jethrogb on github jhoyla on github Jie He Jilayne Lovejoy Jim Beveridge Jim Drash Jim Freeman Jim Fuller Jim Hollinger Jim King Jim Meyering Jimmy Gaussen Jiri Dvorak Jiri Hruska Jiri Jaburek Jishan Shaikh Jiří Malák jmdavitt on github jnbr on github Jocelyn Jaubert Jochem Broekhoff Joe Halpin Joe Malicki Joe Mason Joel Chen Joel Depooter Joel Jakobsson Joel Teichroeb joey-l-us on github Jofell Gallardo Johan Anderson Johan Lantz Johan Nilsson Johan van Selst Johann150 on github Johannes Bauer Johannes Ernst Johannes G. Kristinsson Johannes Lesr Johannes Schindelin John A. Bristor John Bampton John Bradshaw John Butterfield John Coffey John Crow John David Anglin John DeHelian John Dennis John Dunn John E. Malmberg John Gardiner Myers John H. Ayad John Hascall John Haugabook John Janssen John Joseph Bachir John Kelly John Kohl John Lask John Levon John Lightsey John Marino John Marshall John McGowan John P. McCaskey John Porter John Schroeder John Sherrill John Simpson John Starks John Suprock John V. Chow John Wanghui John Weismiller John Wilkinson John-Mark Bell Johnny Luong Jojojov on github Jon DeVree Jon Grubbs Jon Johnson Jr Jon Nelson Jon Rumsey Jon Sargeant Jon Seymour Jon Spencer Jon Torrey Jon Travis Jon Turner Jon Wilkes Jonas Bülow Jonas Forsman Jonas Haag Jonas Minnberg Jonas Schnelli Jonas Vautherin Jonatan Lander Jonatan Vela Jonathan Cardoso Machado Jonathan Hseu Jonathan Moerman Jonathan Nieder Jonathan Watt Jonathan Wernberg Jongki Suwandi jonny112 on github Joombalaya on github Joonas Kuorilehto Jordan Brown Jose Alf Jose Kahan Josef Wolf Joseph Chen Josh Bialkowski Josh Brobst Josh Kapell Josh McCullough Josh Soref joshhe on github Joshua Kwan Joshua Root Joshua Swink Josie Huddleston Josip Medved Josue Andrade Gomes José Joaquín Atria Jozef Kralik Juan Barreto Juan Cruz Viotti Juan F. Codagnone Juan Ignacio Hervás Juan RP Judson Bishop Juergen Hoetzel Juergen Wilke Jukka Pihl Julian Montes Julian Noble Julian Ospald Julian Romero Nieto Julian Taylor Julian Z Julien Chaffraix Julien Nabet Julien Royer Jun Tseng Jun-ichiro itojun Hagino Jun-ya Kato jungle-boogie on github Junho Choi Jurij Smakov jurisuk on github Juro Bystricky JustAnotherArchivist on github justchen1369 on github Justin Clift Justin Ehlert Justin Fletcher Justin Karneges Justin Maggard jveazey on github jvreelanda on github jvvprasad78 on github jzinn on github János Fekete Jérémy Rabasco Jérémy Rocher Jörg Mueller-Tolk Jörn Hartroth Jürgen Gmach K. R. Walker ka7 on github Kael1117 on github Kai Engert Kai Noda Kai Pastor Kai Sommerfeld Kai-Uwe Rommel Kalle Vahlman Kamil Dudka Kane York Kang Lin Kang-Jin Lee Kantanat Wannapaka Kari Pahula Karl Chen Karl Moerder Karol Pietrzak Karthikdasari0423 Karthikdasari0423 on github Kartik Mahajan Kaspar Brand Katie Wang Katsuhiko YOSHIDA Kazuho Oku kchow-FTNT on github Kees Cook Kees Dekker Keitagit-kun on github Keith MacDonald Keith McGuigan Keith Mok Kelly Kaoudis Ken Brown Ken Hirsch Ken Rastatter Kenneth Davidson Kenneth Myhra Kenny To Kent Boortz Kerem Kat Keshav Krity Kev Jackson Kevin Adler Kevin Baughman Kevin Burke Kevin Fisk Kevin Ji Kevin Lussier Kevin R. Bulgrien Kevin Reed Kevin Roth Kevin Ryan Kevin Smith Kevin Ushey Kim Minjoong Kim Rinnewitz Kim Vandry Kimmo Kinnunen Kirill Efimov Kirill Marchuk Kjell Ericson Kjetil Jacobsen Klaus Crusius Klaus Stein Klevtsov Vadim Kobi Gurkan Koen Dergent Koichi Shiraishi kokke on github Konstantin Isakov Konstantin Kushnir KotlinIsland on github kotoriのねこ kouzhudong on github Kovalkov Dmitrii kreshano on github Kris Kennaway Krishnendu Majumdar Krister Johansen Kristian Gunstone Kristian Köhntopp Kristian Mide Kristiyan Tsaklev Kristoffer Gleditsch Kunal Chandarana Kunal Ekawde Kurt Fankhauser Kushal Das Kvarec Lezki kwind on github Kwon-Young Choi Kyle Abramowitz Kyle Edwards Kyle J. McKay Kyle L. Huff Kyle Sallee Kyohei Kadota Kyselgov E.N l00p3r on Hackerone Lachlan O'Dea Ladar Levison Lance Ware Laramie Leavitt Larry Campbell Larry Fahnoe Larry Lin Larry Stefani Larry Stone Lars Buitinck Lars Gustafsson Lars J. Aas Lars Johannesen Lars Nilsson Lars Torben Wilson Laurent Bonnans Laurent Dufresne Laurent Rabret Lauri Kasanen Laurie Clark-Michalek Lawrence Gripper Lawrence Matthews Lawrence Wagerfield Leah Neukirchen Leandro Coutinho Legoff Vincent Lehel Bernadt Leif W Leigh Purdie Leith Bade Len Krause Len Marinaccio Lenaic Lefever Lenny Rachitsky Leo Neat Leon Breedt Leon Winter Leonardo Rosati Leonardo Taccari Leszek Kubik Li Xinwei Liam Healy Liam Warfield LigH-de on github lijian996 on github Lijo Antony lilongyan-huawei on github Linas Vepstas Lindley French Ling Thio Linos Giannopoulos Linus Lewandowski Linus Nielsen Feltzing Linus Nordberg Lior Kaplan Lisa Xu Litter White Liviu Chircu Liza Alenchery lizhuang0630 on github lllaffer on github Lloyd Fournier Lluís Batlle i Rossell locpyl-tidnyd on github Loganaden Velvindron Loic Dachary Loren Kirkby Lorenzo Miniero Luan Cestari Luca Altea Luca Boccassi Luca Niccoli Lucas Adamski Lucas Clemente Vella Lucas Holt Lucas Pardue Lucas Servén Marín Lucas Severo Lucien Zürcher Ludek Finstrle Ludovico Cavedon Ludwig Nussel Lukas Ruzicka Lukasz Czekierda lukaszgn on github Luke Amery Luke Call Luke Dashjr Luke Granger-Brown luminixinc on github Luo Jinghua Luong Dinh Dung Luz Paz Luật Nguyễn lwthiker on github Lyman Epp Lyndon Hill M.R.T on github Maciej Domanski Maciej Karpiuk Maciej Puzio Maciej W. Rozycki madblobfish on github MaeIsBad on github Mahmoud Samir Fayed Maks Naumov Maksim Kuzevanov Maksim Stsepanenka Malik Idrees Hasan Khan Mamoru Tasaka Mamta Upadhyay Mandy Wu Manfred Schwarb Manuel Massing Manuj Bhatia Marc Aldorasi Marc Boucher Marc Deslauriers Marc Doughty Marc Hesse Marc Hörsken Marc Kleine-Budde Marc Renault Marc Schlatter Marc-Antoine Perennou marc-groundctl on github Marcel Hernandez Marcel Raad Marcel Roelofs Marcelo Echeverria Marcelo Juchem Marcin Adamski Marcin Gryszkalis Marcin Konicki Marco Deckel Marco G. Salvagno Marco Kamner Marco Maggi Marcos Diazr Marcus Hoffmann Marcus Klein Marcus Sundberg Marcus T Marcus Webster Margu Marian Klymov Mario Schroeder Mark Brand Mark Butler Mark Davies Mark Dodgson Mark Gaiser Mark Hamilton Mark Incley Mark Itzcovitz Mark Karpeles Mark Lentczner Mark Nottingham Mark Roszko Mark Salisbury Mark Seuffert Mark Snelling Mark Swaanenburg Mark Tully Mark W. Eichin Mark Wotton Markus Duft Markus Elfring Markus Koetter Markus Moeller Markus Oberhumer Markus Olsson Markus Westerlind Maros Priputen Marquis de Muesli marski on github Martijn Koster Martin Ankerl Martin Bašti Martin C. Martin Martin D'Aloia Martin Dorey Martin Drasar Martin Dreher Martin Frodl Martin Galvan Martin Gartner Martin Hager Martin Halle Martin Hedenfalk Martin Howarth Martin Jansen Martin Kammerhofer Martin Kepplinger Martin Lemke Martin Skinner Martin Staael Martin Storsjö Martin Strunz Martin V Martin Vejnár Martin Waleczek Martin Ågren Marty Kuhrt Maruko Masaya Suzuki masbug on github Massimiliano Fantuzzi Massimiliano Ziccardi Massimo Callegari Master Inspire MasterInQuestion on github Mateusz Loskot Mathias Axelsson Mathias Gumz Mathieu Carbonneaux Mathieu Legare Matias N. Goldberg Mats Lidell Mats Lindestam Matt Arsenault Matt Ford Matt Holt Matt Jolly Matt Kraai Matt McClure Matt Veenstra Matt Witherspoon Matt Wixson Matteo Baccan Matteo Bignotti Matteo Bignottignotti Matteo Rocco Matthew Blain Matthew Clarke Matthew Hall Matthew Kerwin Matthew Thompson Matthew Whitehead Matthias Bolte Matthias Gatto Matthias Naegler Mattias Fornander Matus Uzak Maurice Barnum Mauro Iorio Mauro Rappa Max Dymond Max Katsev Max Kellermann Max Khon Max Mehl Max Peal Max Savenkov Max Zettlmeißl Maxim Ivanov Maxim Perenesenko Maxim Prohorov Maxime Larocque Maxime Legros mbeifuss on github mccormickt12 on github Median Median Stride mehatzri on github Mehmet Bozkurt Mekonikum Melissa Mears Melroy van den Berg Mert Yazıcıoğlu Mettgut Jamalla Micah Snyder) Michael Afanasiev Michael Anti Michael Baentsch Michael Benedict Michael Brehm Michael Brown Michael Calmer Michael Cronenworth Michael Curtis Michael Day Michael Drake Michael Felt Michael Forney Michael Gmelin Michael Goffioul Michael Heimpold Michael Hordijk Michael Jahn Michael Jerris Michael Kalinin Michael Kaufmann Michael Kilburn Michael Kolechkin Michael Kujawa Michael König Michael Lee Michael Maltese Michael Mealling Michael Mueller Michael Musset Michael O'Farrell Michael Olbrich Michael Osipov Michael Schmid Michael Smith Michael Stapelberg Michael Steuer Michael Stillwell Michael Trebilcock Michael Vittiglio Michael Wallner Michal Bonino Michal Marek Michal Rus Michal Trybus Michal Čaplygin Michał Antoniak Michał Fita Michał Górny Michał Janiszewski Michał Kowalczyk Michał Petryka Michał Piechowski Michel Promonet Michele Bini Miguel Angel Miguel Diaz migueljcrum on github Mihai Ionescu Mikael Johansson Mikael Sennerholm Mikalai Ananenka Mike Bytnar Mike Crowe Mike Dobbs Mike Dowell Mike Duglas Mike Frysinger Mike Gelfand Mike Giancola Mike Hasselberg Mike Henshaw Mike Hommey Mike Mio Mike Norton Mike Power Mike Protts Mike Revi Mike Tzou Mikhail Kuznetsov Miklos Nemeth Miloš Ljumović Mingliang Zhu Mingtao Yang Miroslav Franc Miroslav Spousta Mischa Salle Mitz Wark mkzero on github modbw on github Mohamed Lrhazi Mohamed Osama Mohammad AlSaleh Mohammad Hasbini Mohammed Naser Mohun Biswas momala454 on github Momoka Yamamoto MonkeybreadSoftware on github moohoorama on github Morten Minde Neergaard Mostyn Bramley-Moore Moti Avrahami MrdUkk on github MrSorcus on github Muhammad Herdiansyah Muhammad Hussein Ammari Muhammed Yavuz Nuzumlalı Murugan Balraj musvaage on github Muz Dima Myk Taylor n0name321 on github Nach M. S. Nagai H Nao Yonashiro naost3rn on github Nate Prewitt Nathan Coulter Nathan Moinvaziri Nathan O'Sullivan Nathanael Nerode Nathaniel J. Smith Nathaniel R. Lewis Nathaniel Waisbrot Naveen Chandran Naveen Noel Neal McBurnett Neal Poole nedres on github neex on github Nehal J Wani neheb on github Neil Bowers Neil Dunbar Neil Kolban Neil Spring neutric on github nevv on HackerOne/curl Niall O'Reilly niallor on github nian6324 on github nianxuejie on github Nic Roets Nicholas Maniscalco Nick Banks Nick Coghlan Nick Draffen Nick Gimbrone Nick Humfrey Nick Miyake Nick Zitzmann nick-telia on github Nicklas Avén Nico Baggus nico-abram on github Nicolas Berloquin Nicolas Croiset Nicolas François Nicolas Grekas Nicolas Guillier Nicolas Morey-Chaisemartin Nicolas Sterchele Niels Martignène Niels van Tongeren Nikita Schmidt Nikitinskit Dmitriy Niklas Angebrand Niklas Hambüchen Nikolai Kondrashov Nikos Mavrogiannopoulos Nikos Tsipinakis nimaje on github niner on github Ning Dong Nir Soffer Niranjan Hasabnis Nis Jorgensen nk Noam Moshe nobedee on github NobodyXu on github Nobuhiro Ban Nodak Sodak nopjmp on github Norbert Frese Norbert Kett Norbert Novotny norbertmm on github nosajsnikta on github NTMan on Github Nuru on github Octavio Schroeder odek86 on github Ofer Okhin Vasilij Ola Mork Olaf Flebbe Olaf Hering Olaf Stüben Oleg Jukovec Oleg Pudeyev Oleguer Llopart Olen Andoni olesteban on github Oli Kingshott Oliver Chang Oliver Gondža Oliver Graute Oliver Kuckertz Oliver Roberts Oliver Schindler Oliver Urbann Olivier Berger Olivier Brunel Omar Ramadan omau on github Ondřej Koláček opensignature on github opensslonzos-github on github Orange Tsai Oren Souroujon Oren Tirosh Orgad Shaneh Ori Avtalion orycho on github osabc on github Osaila on github Osama Albahrani Oscar Koeroo Oscar Norlander Oskar Liljeblad Oskar Sigvardsson Oumph on github ovidiu-benea on github P R Schaffner Palo Markovic pandada8 on github Paolo Mossino Paolo Piacentini Paras Sethia parazyd on github Pascal Gaudette Pascal Terjan Pasha Kuznetsov Pasi Karkkainen Pat Ray patelvivekv1993 on github patnyb on github Patrice Guerin Patricia Muscalu Patrick Bihan-Faou Patrick Dawson Patrick McManus Patrick Monnerat Patrick Rapin Patrick Schlangen Patrick Scott Patrick Smith Patrick Watson Patrik Thunstrom Pau Garcia i Quiles Paul B. Omta Paul Donohue Paul Dreik Paul Groke Paul Harrington Paul Harris Paul Hoffman Paul Howarth Paul Johnson Paul Joyce Paul Marks Paul Marquis Paul Moore Paul Nolan Paul Oliver Paul Querna Paul Saab Paul Seligman Paul Vixie Paul Wise Paulo Roberto Tomasi Pavel Cenek Pavel Gushchin Pavel Kalyugin Pavel Löbl Pavel Mayorov Pavel Orehov Pavel Pavlov Pavel Raiskup Pavel Rochnyak Pavel Volgarev Pavol Markovic Pawel A. Gajda Pawel Kierski Paweł Kowalski Paweł Wegner Pedro Henrique Pedro Larroy Pedro Monreal Pedro Neves pendrek at hackerone Peng Li Peng-Yu Chen Per Jensen Per Lundberg Per Malmberg Per Nilsson Pete Lomax Peter Bray Peter Forret Peter Frühberger Peter Gal Peter Goodman Peter Heuchert Peter Hjalmarsson Peter Korsgaard Peter Körner Peter Lamare Peter Lamberg Peter Laser Peter O'Gorman Peter Pentchev Peter Piekarski Peter Silva Peter Simonyi Peter Su Peter Sumatra Peter Sylvester Peter Todd Peter Varga Peter Verhas Peter Wang Peter Wu Peter Wullinger Peteris Krumins Petr Bahula Petr Novak Petr Pisar Petr Voytsik Petr Štetiar Phil Blundell Phil Crump Phil E. Taylor Phil Karn Phil Lisiecki Phil Pellouchoud Philip Chan Philip Craig Philip Gladstone Philip Heiduck Philip Langdale Philip Prindeville Philip Sanetra Philipp Engel Philipp Klaus Krause Philipp Waehnert Philippe Hameau Philippe Marguinaud Philippe Raoult Philippe Vaucher Pierre Pierre Brico Pierre Chapuis Pierre Joye Pierre Yager Pierre Ynard Pierre-Yves Bigourdan Pierrick Charron Piotr Dobrogost Piotr Komborski Po-Chuan Hsieh Pontakorn Prasertsuk Pontus Lundkvist Pooyan McSporran Poul T Lomholt Pramod Sharma Prash Dush Praveen Pvs Prithvi MK privetryan on github Priyanka Shah ProceduralMan on github Pronyushkin Petr Przemysław Tomaszewski pszemus on github puckipedia on github Puneet Pawaia qiandu2006 on github Quagmire Quanah Gibson-Mount Quentin Balland Quinn Slack r-a-sattarov on github R. Dennis Steed Radek Brich Radek Zajic Radoslav Georgiev Radu Hociung Radu Simionescu Rafa Muyo Rafael Antonio Rafael Sagula Rafayel Mkrtchyan Rafaël Carré Rafał Mikrut Rainer Canavan Rainer Jung Rainer Koenig Rainer Müller Raito Bezarius Rajesh Naganathan Rajkumar Mandal Ralf S. Engelschall Ralph Beckmann Ralph Langendam Ralph Mitchell Ram Krushna Mishra ramsay-jones on github Ran Mozes RanBarLavie on github Randall S. Becker Randolf J Randy Armstrong Randy McMurchy Raphael Gozzo Rasmus Melchior Jacobsen Raul Onitza-Klugman Ravi Pratap Ray Dassen Ray Pekowski Ray Satiro Razvan Cojocaru rcombs on github Red Hat Product Security Reed Loden Reinhard Max Reinout van Schouwen RekGRpth on github Remco van Hooff Remi Gacogne Remo E Renato Botelho Renaud Allard Renaud Chaillat Renaud Duhaut Renaud Guillard Renaud Lehoux Rene Bernhardt Rene Rebe Reuven Wachtfogel Reza Arbab Rianov Viacheslav Ricardo Cadime Ricardo Gomes Ricardo M. Correia Ricardo Martins Rich Burridge Rich FitzJohn Rich Gray Rich Mirch Rich Rauenzahn Rich Salz Rich Turner Richard Adams Richard Alcock Richard Archer Richard Atterer Richard Bowker Richard Bramante Richard Clayton Richard Cooper Richard Gorton Richard Gray Richard Hosking Richard Hsu Richard Marion Richard Michael Richard Moore Richard Prescott Richard Silverman Richard van den Berg Richard Whitehouse Richy Kim Rici Lake Rick Deist Rick Jones Rick Lane Rick Richardson Rick Welykochy Rickard Hallerbäck Ricki Hirner Ricky Leverence Ricky-Tigg on github Rider Linden RiderALT on github Rikard Falkeborn rl1987 on github Rob Boeckermann Rob Cotrone Rob Crittenden Rob Davies Rob de Wit Rob Jones Rob Sanders Rob Stanzel Rob Ward RobBotic1 on github Robby Simpson Robert A. Monat Robert B. Harris Robert Brose Robert Charles Muir Robert D. Young Robert Dunaj Robert Foreman Robert Iakobashvili Robert Kolcun Robert Linden Robert Olson Robert Prag Robert Ronto Robert Schumann Robert Weaver Robert Wruck Robin A. Meade Robin Cornelius Robin Douine Robin Johnson Robin Kay Robin Marx Robson Braga Araujo Rod Widdowson Rodger Combs Rodney Simmons Rodric Glaser Rodrigo Silva Roger Leigh Roger Orr Roger Young Roland Blom Roland Hieber Roland Krikava Roland Zimmermann Rolf Eike Beer Rolland Dudemaine Romain Coltel Romain Fliedel Romain Geissler romamik om github Roman Koifman Roman Mamedov Romulo A. Ceccon Ron Eldor Ron Parker Ron Zapp Ronan Pigott Ronnie Mose Rosen Penev Rosimildo da Silva Ross Burton roughtex on github Roy Bellingan Roy Li Roy Shan Rui LIU Rui Pinheiro Rune Kleveland Ruslan Baratov Ruslan Gazizov Rutger Hofman Ruurd Beerstra RuurdBeerstra on github rwmjones on github Ryan Beck-Buysse Ryan Braud Ryan Chan Ryan Mast Ryan Nelson Ryan Schmidt Ryan Scott Ryan Sleevi Ryan Winograd ryancaicse on github Ryuichi KAWAMATA rzrymiak on github Rémy Léone S. Moonesamy Sai Ram Kunala Salah-Eddin Shaban Saleem Abdulrasool SaltyMilk Salvador Dávila Salvatore Sorrentino Sam Deane Sam Hurst Sam Roth Sam Schanken Samanta Navarro Sampo Kellomaki Samuel Díaz García Samuel Henrique Samuel Listopad Samuel Marks Samuel Surtees Samuel Thibault Samuel Tranchet SandakovMM on github Sander Gates Sandor Feldi Sandro Jaeckel Santhana Todatry Santino Keupp Saqib Ali Sara Golemon Saran Neti Sascha Swiercy Sascha Zengler Satadru Pramanik Saul good Saurav Babu sayrer on github SBKarr on github Scott Bailey Scott Barrett Scott Cantor Scott Davis Scott McCreary Sean Boudreau Sean Burford Sean MacLennan Sean McArthur Sean Miller Sean Molenaar Sebastiaan van Erk Sebastian Haglund Sebastian Mundry Sebastian Pohlschmidt Sebastian Rasmussen Sebastian Sterk selmelc on hackerone SendSonS on github Senthil Raja Velu Sergei Kuzmin Sergei Nikulov Sergey Alirzaev Sergey Bronnikov Sergey Fionov Sergey Markelov Sergey Ogryzkov Sergey Ryabinin Sergey Tatarincev Sergii Kavunenko Sergii Pylypenko Sergio Ballestrero Sergio Barresi Sergio Borghese Sergio Durigan Junior Sergio Mijatovic Sergio-IME on github sergio-nsk on github Serj Kalichev SerusDev on github Seshubabu Pasam Seth Mos Sevan Janiyan Sgharat on github Sh Diao Shachaf Ben-Kiki ShadowZzj on github Shailesh Kapse Shankar Jadhavar Shao Shuchao Sharad Gupta Shard Sharon Brizinov Shaun Jackman Shaun Mirani Shawn Landden Shawn Poulson Sheshadri.V Shikha Sharma Shine Fan Shiraz Kanga shithappens2016 on github Shlomi Fish Shmulik Regev Shohei Maeda Siddhartha Prakash Jain siddharthchhabrap on github Sidney San Martín Siegfried Gyuricsko silveja1 on github Simon Berger Simon Chalifoux Simon Dick Simon H. Simon Josefsson Simon Legner Simon Liu Simon Warta simplerobot on github Siva Sivaraman SLDiggie on github Smackd0wn on github smuellerDD on github sn on hackerone sofaboss on github Somnath Kundu Song Ma Sonia Subramanian Spacen Jasset Spezifant on github Spiridonoff A.V Spoon Man Spork Schivago ssdbest on github sspiri on github sstruchtrup on github Stadler Stephan Stan Hu Stan van de Burgt Stanislav Ivochkin Stanislav Zidek Stanley Wucw Stathis Kapnidis Stav Nir steelman on github Stefan Agner Stefan Bühler Stefan Eissing Stefan Esser Stefan Grether Stefan Huber Stefan Kanthak Stefan Karpinski Stefan Krause Stefan Neis Stefan Strogin Stefan Talpalaru Stefan Teleman Stefan Tomanek Stefan Ulrich Stefan Yohansson Stefano Simonelli Steinar H. Gunderson steini2000 on github Stepan Broz Stepan Efremov Stephan Bergmann Stephan Guilloux Stephan Lagerholm Stephan Mühlstrasser Stephan Szabo Stephane Pellegrino Stephen Boost Stephen Brokenshire Stephen Collyer Stephen Kick Stephen M. Coakley Stephen More Stephen Toub Sterling Hughes Steve Green Steve H Truong Steve Havelka Steve Herrell Steve Holme Steve Lhomme Steve Little Steve Marx Steve Oliphant Steve Roskowski Steve Walch Steven Bazyl Steven G. Johnson Steven Gu Steven M. Schweda Steven Parkes Steven Penny Stewart Gebbie Stian Soiland-Reyes Stoned Elipot stootill on github Stuart Henderson Sukanya Hanumanthu SumatraPeter on github Sune Ahlgren Sunny Bean Sunny Purushe SuperIlu on github Sven Anders Sven Blumenstein Sven Neuhaus Sven Wegener Svyatoslav Mishyn swalkaus at yahoo.com sylgal on github Sylvestre Ledru Symeon Paraschoudis Sébastien Helleu Sébastien Willemijns T. Bharath T. Yamada T200proX7 on github Tadej Vengust Tae Hyoung Ahn Taiyu Len Taneli Vähäkangas Tanguy Fautre Taras Kushnir tarek112 on github Tatsuhiro Tsujikawa tawmoto on github tbugfinder on github Ted Lyngmo Teemu Yli-Elsila Temprimus Terri Oda Terry Wu thanhchungbtc on github The Infinnovation team TheAssassin on github TheKnarf on github Theodore Dubois therealhirudo on github Thiago Suchorski tholin on github Thomas Bouzerar Thomas Braun Thomas Danielsson Thomas Gamper Thomas Glanzmann Thomas Guillem Thomas J. Moore Thomas Klausner Thomas L. Shinnick Thomas Lopatic Thomas M. DuBuisson Thomas Petazzoni Thomas Ruecker Thomas Schwinge Thomas Taylor Thomas Tonino Thomas van Hesteren Thomas Vegas Thomas Weißschuh Thomas1664 on github Thorsten Schöning Tiit Pikma Till Maas Tim Ansell Tim Baker Tim Bartley Tim Chen Tim Costello Tim Harder Tim Heckman Tim Mcdonough Tim Newsome Tim Rühsen Tim Sedlmeyer Tim Sneddon Tim Stack Tim Starling Tim Tassonis Tim Verhoeven Timmy Schierling Timo Lange Timo Sirainen Timotej Lazar Timothe Litt Timothy Gu Timothy Polich Timur Artikov Tinus van den Berg TJ Saunders Tk Xiong tlahn on github tmkk on github Tobias Blomberg Tobias Gabriel Tobias Hieta Tobias Hintze Tobias Lindgren Tobias Markus Tobias Nießen Tobias Nygren Tobias Nyholm Tobias Rundström Tobias Schaefer Tobias Stoeckmann Toby Peterson Todd A Ouska Todd Kaufmann Todd Kulesza Todd Short Todd Vierling Tom Benoist Tom Donovan Tom Eccles Tom G. Christensen Tom Grace Tom Greenslade Tom Lee Tom Mattison Tom Moers Tom Mueller Tom Regner Tom Seddon Tom Sparrow Tom van der Woerdt Tom Wright Tom Zerucha Tomas Berger Tomas Hoger Tomas Jakobsson Tomas Mlcoch Tomas Mraz Tomas Pospisek Tomas Szepe Tomas Tomecek Tomasz Kojm Tomasz Lacki Tommie Gannert tommink[at]post.pl Tommy Chiang Tommy Odom Tommy Petty Tommy Tam Ton Voon Toni Moreno Tony Kelman tonystz on Github Toon Verwaest Tor Arntsen Torben Dannhauer Torsten Foertsch Toshio Kuratomi Toshiyuki Maezawa tpaukrt on github Traian Nicolescu Trail of Bits Travis Burtrum Travis Obenhaus Trivikram Kamat Troels Walsted Hansen Troy Engel Tseng Jun Tuomas Siipola Tuomo Rinne Tupone Alfredo Tyler Hall Török Edwin u20221022 on github Ulf Härnhammar Ulf Samuelsson Ulrich Doehner Ulrich Telle Ulrich Zadow UnicornZhang on Github updatede on github UrsusArctos on github User Sg ustcqidi on github Vadim Grinshpun Valentin David Valentin Richter Valentyn Korniienko Valentín Gutiérrez Valerii Zapodovnikov vanillajonathan on github Varnavas Papaioannou Vasiliy Faronov Vasiliy Ulyanov Vasily Lobaskin Vasy Okhin Venkat Akella Venkataramana Mokkapati Vicente Garcia Victor Magierski Victor Snezhko Victor Vieux VictorVG on github Vijay Panghal Vikram Saxena Viktor Szakats Vilhelm Prytz Ville Skyttä Vilmos Nebehaj Vincas Razma Vincent Bronner Vincent Grande Vincent Le Normand Vincent Penquerc'h Vincent Sanders Vincent Torri violetlige on github vitaha85 on github Vitaly Varyvdin vl409 on github Vlad Grachov Vlad Ureche Vladimir Grishchenko Vladimir Kotal Vladimir Lazarenko Vladimir Panteleev Vladimir Varlamov Vlastimil Ovčáčík vlkl-sap on github vlubart on github Vojtech Janota Vojtech Minarik Vojtěch Král Volker Schmid Vsevolod Novikov vshmuk on hackerone vvb2060 on github Vyron Tsingaras Vítor Galvão W. Mark Kubacki Waldek Kozba Walter J. Mack Ward Willats Warren Menzer Wayne Haigh Wei Chong Tan Wenchao Li Wenxiang Qian Werner Koch Werner Stolz Wes Hinsley wesinator on github Wesley Laxton Wesley Miaw Wez Furlong Wham Bang Wilfredo Sanchez Will Dietz Will Roberts Willem Hoek Willem Sparreboom William A. Rowe Jr William Ahern William Desportes William Tang wmsch on github wncboy on github Wojciech Zwiefka Wolf Vollprecht Wouter Van Rooy Wu Yongzheng Wu Zheng Wyatt O'Day Wyatt OʼDay x2018 on github Xavier Bouchoux XhmikosR on github XhstormR on github Xiang Xiao Xiangbin Li xianghongai on github Xiaoke Wang Xiaoyin Liu XmiliaH on github xnynx on github xtonik on github xwxbug on github Xì Gà Yaakov Selkowitz Yair Lenga Yang Tse Yaobin Wen Yarram Sunil Yasuharu Yamada Yasuhiro Matsumoto Yechiel Kalmenson Yehezkel Horowitz Yehoshua Hershberg ygthien on github Yi Huang Yiming Jing Yingwei Liu yiyuaner on github Ymir1711 on github Yonggang Luo Yongkang Huang Younes El-karama youngchopin on github Yousuke Kimoto Yu Xin Yukihiro Kawada Yun SangHo Yuri Slobodyanyuk Yurii Rashkovskii Yuriy Chernyshov Yuriy Sosov Yusuke Nakamura Yves Arrouye Yves Lejeune YX Hao z2-2z on github z2_ on hackerone Zachary Seguin Zdenek Pavlas Zekun Ni zelinchen on github Zenju on github Zero King Zespre Schmidt Zhang Xiuhua zhanghu on xiaomi Zhao Yisha Zhaoyang Wu Zhibiao Wu Zhouyihai Ding ZimCodes on github zloi-user on github Zmey Petroff Zvi Har'El zzq1015 on github Ádler Jonas Gross Érico Nogueira Érico Nogueira Rolim İsmail Dönmez Łukasz Domeradzki Štefan Kremeň Борис Верховский Коваленко Анатолий Викторович Никита Дорохин ウさん 不确定 加藤郁之 左潇峰 梦终无痕 積丹尼 Dan Jacobson ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/KNOWN_BUGS���������������������������������������������������������������������������0000644�����������������00000050543�15253042577�0011010 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | | (__| |_| | _ <| |___ \___|\___/|_| \_\_____| Known Bugs These are problems and bugs known to exist at the time of this release. Feel free to join in and help us correct one or more of these. Also be sure to check the changelog of the current development status, as one or more of these problems may have been fixed or changed somewhat since this was written. 1. HTTP 1.1 hyper memory-leaks 1.5 Expect-100 meets 417 2. TLS 2.3 Unable to use PKCS12 certificate with Secure Transport 2.4 Secure Transport will not import PKCS#12 client certificates without a password 2.5 Client cert handling with Issuer DN differs between backends 2.7 Client cert (MTLS) issues with Schannel 2.8 Schannel disable CURLOPT_SSL_VERIFYPEER and verify hostname 2.11 Schannel TLS 1.2 handshake bug in old Windows versions 2.12 FTPS with Schannel times out file list operation 2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel 3. Email protocols 3.1 IMAP SEARCH ALL truncated response 3.2 No disconnect command 3.3 POP3 expects "CRLF.CRLF" eob for some single-line responses 3.4 AUTH PLAIN for SMTP is not working on all servers 4. Command line 5. Build and portability issues 5.1 OS400 port requires deprecated IBM library 5.2 curl-config --libs contains private details 5.3 building for old macOS fails with gcc 5.5 cannot handle Unicode arguments in non-Unicode builds on Windows 5.9 Utilize Requires.private directives in libcurl.pc 5.11 configure --with-gssapi with Heimdal is ignored on macOS 5.12 flaky CI builds 5.13 long paths are not fully supported on Windows 5.14 Windows Unicode builds use homedir in current locale 6. Authentication 6.1 NTLM authentication and unicode 6.2 MIT Kerberos for Windows build 6.3 NTLM in system context uses wrong name 6.4 Negotiate and Kerberos V5 need a fake user name 6.5 NTLM does not support password with § character 6.6 libcurl can fail to try alternatives with --proxy-any 6.7 Do not clear digest for single realm 6.9 SHA-256 digest not supported in Windows SSPI builds 6.10 curl never completes Negotiate over HTTP 6.11 Negotiate on Windows fails 6.12 cannot use Secure Transport with Crypto Token Kit 6.13 Negotiate against Hadoop HDFS 7. FTP 7.3 FTP with NOBODY and FAILONERROR 7.4 FTP with ACCT 7.11 FTPS upload data loss with TLS 1.3 7.12 FTPS directory listing hangs on Windows with Schannel 9. SFTP and SCP 9.1 SFTP does not do CURLOPT_POSTQUOTE correct 9.2 wolfssh: publickey auth does not work 9.3 Remote recursive folder creation with SFTP 9.4 libssh blocking and infinite loop problem 10. SOCKS 10.3 FTPS over SOCKS 11. Internals 11.2 error buffer not set if connection to multiple addresses fails 11.4 HTTP test server 'connection-monitor' problems 11.5 Connection information when using TCP Fast Open 12. LDAP 12.1 OpenLDAP hangs after returning results 12.2 LDAP on Windows does authentication wrong? 12.3 LDAP on Windows does not work 12.4 LDAPS with NSS is slow 13. TCP/IP 13.2 Trying local ports fails on Windows 15. CMake 15.2 support build with GnuTLS 15.3 unusable tool_hugehelp.c with MinGW 15.4 build docs/curl.1 15.6 uses -lpthread instead of Threads::Threads 15.7 generated .pc file contains strange entries 15.8 libcurl.pc uses absolute library paths 15.11 ExternalProject_Add does not set CURL_CA_PATH 15.13 CMake build with MIT Kerberos does not work 16. Applications 17. HTTP/2 17.2 HTTP/2 frames while in the connection pool kill reuse 17.3 ENHANCE_YOUR_CALM causes infinite retries 18. HTTP/3 18.1 connection migration does not work ============================================================================== 1. HTTP 1.1 hyper memory-leaks Building curl with the hyper backend causes mysterious memory-leaks https://github.com/curl/curl/issues/10803 1.5 Expect-100 meets 417 If an upload using Expect: 100-continue receives an HTTP 417 response, it ought to be automatically resent without the Expect:. A workaround is for the client application to redo the transfer after disabling Expect:. https://curl.se/mail/archive-2008-02/0043.html 2. TLS 2.3 Unable to use PKCS12 certificate with Secure Transport See https://github.com/curl/curl/issues/5403 2.4 Secure Transport will not import PKCS#12 client certificates without a password libcurl calls SecPKCS12Import with the PKCS#12 client certificate, but that function rejects certificates that do not have a password. https://github.com/curl/curl/issues/1308 2.5 Client cert handling with Issuer DN differs between backends When the specified client certificate does not match any of the server-specified DNs, the OpenSSL and GnuTLS backends behave differently. The github discussion may contain a solution. See https://github.com/curl/curl/issues/1411 2.7 Client cert (MTLS) issues with Schannel See https://github.com/curl/curl/issues/3145 2.8 Schannel disable CURLOPT_SSL_VERIFYPEER and verify hostname This seems to be a limitation in the underlying Schannel API. https://github.com/curl/curl/issues/3284 2.11 Schannel TLS 1.2 handshake bug in old Windows versions In old versions of Windows such as 7 and 8.1 the Schannel TLS 1.2 handshake implementation likely has a bug that can rarely cause the key exchange to fail, resulting in error SEC_E_BUFFER_TOO_SMALL or SEC_E_MESSAGE_ALTERED. https://github.com/curl/curl/issues/5488 2.12 FTPS with Schannel times out file list operation "Instead of the command completing, it just sits there until the timeout expires." - the same command line seems to work with other TLS backends and other operating systems. See https://github.com/curl/curl/issues/5284. 2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel https://github.com/curl/curl/issues/8741 3. Email protocols 3.1 IMAP SEARCH ALL truncated response IMAP "SEARCH ALL" truncates output on large boxes. "A quick search of the code reveals that pingpong.c contains some truncation code, at line 408, when it deems the server response to be too large truncating it to 40 characters" https://curl.se/bug/view.cgi?id=1366 3.2 No disconnect command The disconnect commands (LOGOUT and QUIT) may not be sent by IMAP, POP3 and SMTP if a failure occurs during the authentication phase of a connection. 3.3 POP3 expects "CRLF.CRLF" eob for some single-line responses You have to tell libcurl not to expect a body, when dealing with one line response commands. Please see the POP3 examples and test cases which show this for the NOOP and DELE commands. https://curl.se/bug/?i=740 3.4 AUTH PLAIN for SMTP is not working on all servers Specifying "--login-options AUTH=PLAIN" on the command line does not seem to work correctly. See https://github.com/curl/curl/issues/4080 4. Command line 5. Build and portability issues 5.1 OS400 port requires deprecated IBM library curl for OS400 requires QADRT to build, which provides ASCII wrappers for libc/POSIX functions in the ILE, but IBM no longer supports or even offers this library to download. See https://github.com/curl/curl/issues/5176 5.2 curl-config --libs contains private details "curl-config --libs" will include details set in LDFLAGS when configure is run that might be needed only for building libcurl. Further, curl-config --cflags suffers from the same effects with CFLAGS/CPPFLAGS. 5.3 building for old macOS fails with gcc Building curl for certain old macOS versions fails when gcc is used. We command using clang in those cases. See https://github.com/curl/curl/issues/11441 5.5 cannot handle Unicode arguments in non-Unicode builds on Windows If a URL or filename cannot be encoded using the user's current codepage then it can only be encoded properly in the Unicode character set. Windows uses UTF-16 encoding for Unicode and stores it in wide characters, however curl and libcurl are not equipped for that at the moment except when built with _UNICODE and UNICODE defined. And, except for Cygwin, Windows cannot use UTF-8 as a locale. https://curl.se/bug/?i=345 https://curl.se/bug/?i=731 https://curl.se/bug/?i=3747 5.9 Utilize Requires.private directives in libcurl.pc https://github.com/curl/curl/issues/864 5.11 configure --with-gssapi with Heimdal is ignored on macOS ... unless you also pass --with-gssapi-libs https://github.com/curl/curl/issues/3841 5.12 flaky CI builds We run many CI builds for each commit and PR on github, and especially a number of the Windows builds are flaky. This means that we rarely get all CI builds go green and complete without errors. This is unfortunate as it makes us sometimes miss actual build problems and it is surprising to newcomers to the project who (rightfully) do not expect this. See https://github.com/curl/curl/issues/6972 5.13 long paths are not fully supported on Windows curl on Windows cannot access long paths (paths longer than 260 characters). However, as a workaround, the Windows path prefix \\?\ which disables all path interpretation may work to allow curl to access the path. For example: \\?\c:\longpath. See https://github.com/curl/curl/issues/8361 5.14 Windows Unicode builds use homedir in current locale The Windows Unicode builds of curl use the current locale, but expect Unicode UTF-8 encoded paths for internal use such as open, access and stat. The user's home directory is retrieved via curl_getenv in the current locale and not as UTF-8 encoded Unicode. See https://github.com/curl/curl/pull/7252 and https://github.com/curl/curl/pull/7281 6. Authentication 6.1 NTLM authentication and unicode NTLM authentication involving unicode user name or password only works properly if built with UNICODE defined together with the Schannel backend. The original problem was mentioned in: https://curl.se/mail/lib-2009-10/0024.html https://curl.se/bug/view.cgi?id=896 The Schannel version verified to work as mentioned in https://curl.se/mail/lib-2012-07/0073.html 6.2 MIT Kerberos for Windows build libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's library header files exporting symbols/macros that should be kept private to the KfW library. See ticket #5601 at https://krbdev.mit.edu/rt/ 6.3 NTLM in system context uses wrong name NTLM authentication using SSPI (on Windows) when (lib)curl is running in "system context" will make it use wrong(?) user name - at least when compared to what winhttp does. See https://curl.se/bug/view.cgi?id=535 6.4 Negotiate and Kerberos V5 need a fake user name In order to get Negotiate (SPNEGO) authentication to work in HTTP or Kerberos V5 in the email protocols, you need to provide a (fake) user name (this concerns both curl and the lib) because the code wrongly only considers authentication if there's a user name provided by setting conn->bits.user_passwd in url.c https://curl.se/bug/view.cgi?id=440 How? https://curl.se/mail/lib-2004-08/0182.html A possible solution is to either modify this variable to be set or introduce a variable such as new conn->bits.want_authentication which is set when any of the authentication options are set. 6.5 NTLM does not support password with § character https://github.com/curl/curl/issues/2120 6.6 libcurl can fail to try alternatives with --proxy-any When connecting via a proxy using --proxy-any, a failure to establish an authentication will cause libcurl to abort trying other options if the failed method has a higher preference than the alternatives. As an example, --proxy-any against a proxy which advertise Negotiate and NTLM, but which fails to set up Kerberos authentication will not proceed to try authentication using NTLM. https://github.com/curl/curl/issues/876 6.7 Do not clear digest for single realm https://github.com/curl/curl/issues/3267 6.9 SHA-256 digest not supported in Windows SSPI builds Windows builds of curl that have SSPI enabled use the native Windows API calls to create authentication strings. The call to InitializeSecurityContext fails with SEC_E_QOP_NOT_SUPPORTED which causes curl to fail with CURLE_AUTH_ERROR. Microsoft does not document supported digest algorithms and that SEC_E error code is not a documented error for InitializeSecurityContext (digest). https://github.com/curl/curl/issues/6302 6.10 curl never completes Negotiate over HTTP Apparently it is not working correctly...? See https://github.com/curl/curl/issues/5235 6.11 Negotiate on Windows fails When using --negotiate (or NTLM) with curl on Windows, SSL/TLS handshake fails despite having a valid kerberos ticket cached. Works without any issue in Unix/Linux. https://github.com/curl/curl/issues/5881 6.12 cannot use Secure Transport with Crypto Token Kit https://github.com/curl/curl/issues/7048 6.13 Negotiate authentication against Hadoop HDFS https://github.com/curl/curl/issues/8264 7. FTP 7.3 FTP with NOBODY and FAILONERROR It seems sensible to be able to use CURLOPT_NOBODY and CURLOPT_FAILONERROR with FTP to detect if a file exists or not, but it is not working: https://curl.se/mail/lib-2008-07/0295.html 7.4 FTP with ACCT When doing an operation over FTP that requires the ACCT command (but not when logging in), the operation will fail since libcurl does not detect this and thus fails to issue the correct command: https://curl.se/bug/view.cgi?id=635 7.11 FTPS upload data loss with TLS 1.3 During FTPS upload curl does not attempt to read TLS handshake messages sent after the initial handshake. OpenSSL servers running TLS 1.3 may send such a message. When curl closes the upload connection if unread data has been received (such as a TLS handshake message) then the TCP protocol sends an RST to the server, which may cause the server to discard or truncate the upload if it has not read all sent data yet, and then return an error to curl on the control channel connection. Since 7.78.0 this is mostly fixed. curl will do a single read before closing TLS connections (which causes the TLS library to read handshake messages), however there is still possibility of an RST if more messages need to be read or a message arrives after the read but before close (network race condition). https://github.com/curl/curl/issues/6149 7.12 FTPS directory listing hangs on Windows with Schannel https://github.com/curl/curl/issues/9161 9. SFTP and SCP 9.1 SFTP does not do CURLOPT_POSTQUOTE correct When libcurl sends CURLOPT_POSTQUOTE commands when connected to a SFTP server using the multi interface, the commands are not being sent correctly and instead the connection is "cancelled" (the operation is considered done) prematurely. There is a half-baked (busy-looping) patch provided in the bug report but it cannot be accepted as-is. See https://curl.se/bug/view.cgi?id=748 9.2 wolfssh: publickey auth does not work When building curl to use the wolfSSH backend for SFTP, the publickey authentication does not work. This is simply functionality not written for curl yet, the necessary API for make this work is provided by wolfSSH. See https://github.com/curl/curl/issues/4820 9.3 Remote recursive folder creation with SFTP On this servers, the curl fails to create directories on the remote server even when the CURLOPT_FTP_CREATE_MISSING_DIRS option is set. See https://github.com/curl/curl/issues/5204 9.4 libssh blocking and infinite loop problem In the SSH_SFTP_INIT state for libssh, the ssh session working mode is set to blocking mode. If the network is suddenly disconnected during sftp transmission, curl will be stuck, even if curl is configured with a timeout. https://github.com/curl/curl/issues/8632 10. SOCKS 10.3 FTPS over SOCKS libcurl does not support FTPS over a SOCKS proxy. 11. Internals 11.2 error buffer not set if connection to multiple addresses fails If you ask libcurl to resolve a hostname like example.com to IPv6 addresses only. But you only have IPv4 connectivity. libcurl will correctly fail with CURLE_COULDNT_CONNECT. But the error buffer set by CURLOPT_ERRORBUFFER remains empty. Issue: https://github.com/curl/curl/issues/544 11.4 HTTP test server 'connection-monitor' problems The 'connection-monitor' feature of the sws HTTP test server does not work properly if some tests are run in unexpected order. Like 1509 and then 1525. See https://github.com/curl/curl/issues/868 11.5 Connection information when using TCP Fast Open CURLINFO_LOCAL_PORT (and possibly a few other) fails when TCP Fast Open is enabled. See https://github.com/curl/curl/issues/1332 and https://github.com/curl/curl/issues/4296 12. LDAP 12.1 OpenLDAP hangs after returning results By configuration defaults, OpenLDAP automatically chase referrals on secondary socket descriptors. The OpenLDAP backend is asynchronous and thus should monitor all socket descriptors involved. Currently, these secondary descriptors are not monitored, causing OpenLDAP library to never receive data from them. As a temporary workaround, disable referrals chasing by configuration. The fix is not easy: proper automatic referrals chasing requires a synchronous bind callback and monitoring an arbitrary number of socket descriptors for a single easy handle (currently limited to 5). Generic LDAP is synchronous: OK. See https://github.com/curl/curl/issues/622 and https://curl.se/mail/lib-2016-01/0101.html 12.2 LDAP on Windows does authentication wrong? https://github.com/curl/curl/issues/3116 12.3 LDAP on Windows does not work A simple curl command line getting "ldap://ldap.forumsys.com" returns an error that says "no memory" ! https://github.com/curl/curl/issues/4261 12.4 LDAPS with NSS is slow See https://github.com/curl/curl/issues/5874 13. TCP/IP 13.2 Trying local ports fails on Windows This makes '--local-port [range]' to not work since curl can't properly detect if a port is already in use, so it'll try the first port, use that and then subsequently fail anyway if that was actually in use. https://github.com/curl/curl/issues/8112 15. CMake 15.2 support build with GnuTLS 15.3 unusable tool_hugehelp.c with MinGW see https://github.com/curl/curl/issues/3125 15.4 build docs/curl.1 The cmake build does not create the docs/curl.1 file and therefore must rely on it being there already. This makes the --manual option not work and test cases like 1139 cannot function. 15.6 uses -lpthread instead of Threads::Threads See https://github.com/curl/curl/issues/6166 15.7 generated .pc file contains strange entries The Libs.private field of the generated .pc file contains -lgcc -lgcc_s -lc -lgcc -lgcc_s See https://github.com/curl/curl/issues/6167 15.8 libcurl.pc uses absolute library paths The libcurl.pc file generated by cmake contains things like Libs.private: /usr/lib64/libssl.so /usr/lib64/libcrypto.so /usr/lib64/libz.so. The autotools equivalent would say Libs.private: -lssl -lcrypto -lz See https://github.com/curl/curl/issues/6169 15.11 ExternalProject_Add does not set CURL_CA_PATH CURL_CA_BUNDLE and CURL_CA_PATH are not set properly when cmake's ExternalProject_Add is used to build curl as a dependency. See https://github.com/curl/curl/issues/6313 15.13 CMake build with MIT Kerberos does not work Minimum CMake version was bumped in curl 7.71.0 (#5358) Since CMake 3.2 try_compile started respecting the CMAKE_EXE_FLAGS. The code dealing with MIT Kerberos detection sets few variables to potentially weird mix of space, and ;-separated flags. It had to blow up at some point. All the CMake checks that involve compilation are doomed from that point, the configured tree cannot be built. https://github.com/curl/curl/issues/6904 16. Applications 17. HTTP/2 17.2 HTTP/2 frames while in the connection pool kill reuse If the server sends HTTP/2 frames (like for example an HTTP/2 PING frame) to curl while the connection is held in curl's connection pool, the socket will be found readable when considered for reuse and that makes curl think it is dead and then it will be closed and a new connection gets created instead. This is *best* fixed by adding monitoring to connections while they are kept in the pool so that pings can be responded to appropriately. 17.3 ENHANCE_YOUR_CALM causes infinite retries Infinite retries with 2 parallel requests on one connection receiving GOAWAY with ENHANCE_YOUR_CALM error code. See https://github.com/curl/curl/issues/5119 18. HTTP/3 18.1 connection migration does not work https://github.com/curl/curl/issues/7695 �������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/COPYING������������������������������������������������������������������������������0000644�����������������00000002100�15253042577�0010366 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1996 - 2023, Daniel Stenberg, <daniel@haxx.se>, and many contributors, see the THANKS file. All rights reserved. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 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. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/README�������������������������������������������������������������������������������0000644�����������������00000003200�15253042577�0010215 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | | (__| |_| | _ <| |___ \___|\___/|_| \_\_____| README Curl is a command line tool for transferring data specified with URL syntax. Find out how to use curl by reading the curl.1 man page or the MANUAL document. Find out how to install Curl by reading the INSTALL document. libcurl is the library curl is using to do its job. It is readily available to be used by your software. Read the libcurl.3 man page to learn how. You find answers to the most frequent questions we get in the FAQ document. Study the COPYING file for distribution terms. Those documents and more can be found in the docs/ directory. CONTACT If you have problems, questions, ideas or suggestions, please contact us by posting to a suitable mailing list. See https://curl.se/mail/ All contributors to the project are listed in the THANKS document. WEBSITE Visit the curl website for the latest news and downloads: https://curl.se/ GIT To download the latest source code off the GIT server, do this: git clone https://github.com/curl/curl.git (you will get a directory named curl created, filled with the source code) SECURITY PROBLEMS Report suspected security problems via our HackerOne page and not in public. https://hackerone.com/curl NOTICE Curl contains pieces of source code that is Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan. This notice is included here to comply with the distribution terms. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/TODO���������������������������������������������������������������������������������0000644�����������������00000144471�15253042577�0010045 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | | (__| |_| | _ <| |___ \___|\___/|_| \_\_____| Things that could be nice to do in the future Things to do in project curl. Please tell us what you think, contribute and send us patches that improve things. Be aware that these are things that we could do, or have once been considered things we could do. If you want to work on any of these areas, please consider bringing it up for discussions first on the mailing list so that we all agree it is still a good idea for the project. All bugs documented in the KNOWN_BUGS document are subject for fixing. 1. libcurl 1.1 TFO support on Windows 1.2 Consult %APPDATA% also for .netrc 1.3 struct lifreq 1.4 alt-svc sharing 1.5 get rid of PATH_MAX 1.6 native IDN support on macOS 1.8 CURLOPT_RESOLVE for any port number 1.9 Cache negative name resolves 1.10 auto-detect proxy 1.11 minimize dependencies with dynamically loaded modules 1.12 updated DNS server while running 1.13 c-ares and CURLOPT_OPENSOCKETFUNCTION 1.15 Monitor connections in the connection pool 1.16 Try to URL encode given URL 1.17 Add support for IRIs 1.18 try next proxy if one does not work 1.19 provide timing info for each redirect 1.20 SRV and URI DNS records 1.21 netrc caching and sharing 1.22 CURLINFO_PAUSE_STATE 1.23 Offer API to flush the connection pool 1.25 Expose tried IP addresses that failed 1.28 FD_CLOEXEC 1.29 Upgrade to websockets 1.30 config file parsing 1.31 erase secrets from heap/stack after use 1.32 add asynch getaddrinfo support 1.33 make DoH inherit more transfer properties 2. libcurl - multi interface 2.1 More non-blocking 2.2 Better support for same name resolves 2.3 Non-blocking curl_multi_remove_handle() 2.4 Split connect and authentication process 2.5 Edge-triggered sockets should work 2.6 multi upkeep 2.7 Virtual external sockets 2.8 dynamically decide to use socketpair 3. Documentation 3.1 Improve documentation about fork safety 3.2 Provide cmake config-file 4. FTP 4.1 HOST 4.2 Alter passive/active on failure and retry 4.3 Earlier bad letter detection 4.4 Support CURLOPT_PREQUOTE for dir listings too 4.5 ASCII support 4.6 GSSAPI via Windows SSPI 4.7 STAT for LIST without data connection 4.8 Passive transfer could try other IP addresses 5. HTTP 5.1 Provide the error body from a CONNECT response 5.2 Obey Retry-After in redirects 5.3 Rearrange request header order 5.4 Allow SAN names in HTTP/2 server push 5.5 auth= in URLs 5.6 alt-svc should fallback if alt-svc does not work 5.7 Require HTTP version X or higher 6. TELNET 6.1 ditch stdin 6.2 ditch telnet-specific select 6.3 feature negotiation debug data 6.4 exit immediately upon connection if stdin is /dev/null 7. SMTP 7.1 Passing NOTIFY option to CURLOPT_MAIL_RCPT 7.2 Enhanced capability support 7.3 Add CURLOPT_MAIL_CLIENT option 8. POP3 8.2 Enhanced capability support 9. IMAP 9.1 Enhanced capability support 10. LDAP 10.1 SASL based authentication mechanisms 10.2 CURLOPT_SSL_CTX_FUNCTION for LDAPS 10.3 Paged searches on LDAP server 11. SMB 11.1 File listing support 11.2 Honor file timestamps 11.3 Use NTLMv2 11.4 Create remote directories 12. FILE 12.1 Directory listing for FILE: 13. TLS 13.1 TLS-PSK with OpenSSL 13.2 Provide mutex locking API 13.3 Defeat TLS fingerprinting 13.4 Cache/share OpenSSL contexts 13.5 Export session ids 13.6 Provide callback for cert verification 13.7 Less memory massaging with Schannel 13.8 Support DANE 13.9 TLS record padding 13.10 Support Authority Information Access certificate extension (AIA) 13.11 Support intermediate & root pinning for PINNEDPUBLICKEY 13.12 Reduce CA certificate bundle reparsing 13.13 Make sure we forbid TLS 1.3 post-handshake authentication 13.14 Support the clienthello extension 14. GnuTLS 14.2 check connection 15. Schannel 15.1 Extend support for client certificate authentication 15.2 Extend support for the --ciphers option 15.4 Add option to allow abrupt server closure 16. SASL 16.1 Other authentication mechanisms 16.2 Add QOP support to GSSAPI authentication 17. SSH protocols 17.1 Multiplexing 17.2 Handle growing SFTP files 17.3 Read keys from ~/.ssh/id_ecdsa, id_ed25519 17.4 Support CURLOPT_PREQUOTE 17.5 SSH over HTTPS proxy with more backends 17.6 SFTP with SCP:// 18. Command line tool 18.1 sync 18.2 glob posts 18.4 --proxycommand 18.5 UTF-8 filenames in Content-Disposition 18.6 Option to make -Z merge lined based outputs on stdout 18.8 Consider convenience options for JSON and XML? 18.9 Choose the name of file in braces for complex URLs 18.10 improve how curl works in a windows console window 18.11 Windows: set attribute 'archive' for completed downloads 18.12 keep running, read instructions from pipe/socket 18.13 Ratelimit or wait between serial requests 18.14 --dry-run 18.15 --retry should resume 18.16 send only part of --data 18.17 consider file name from the redirected URL with -O ? 18.18 retry on network is unreachable 18.19 expand ~/ in config files 18.20 host name sections in config files 18.21 retry on the redirected-to URL 18.23 Set the modification date on an uploaded file 18.24 Use multiple parallel transfers for a single download 18.25 Prevent terminal injection when writing to terminal 18.26 Custom progress meter update interval 18.27 -J and -O with %-encoded file names 18.28 -J with -C - 18.29 --retry and transfer timeouts 19. Build 19.1 roffit 19.2 Enable PIE and RELRO by default 19.3 Do not use GNU libtool on OpenBSD 19.4 Package curl for Windows in a signed installer 19.5 make configure use --cache-file more and better 19.6 build curl with Windows Unicode support 20. Test suite 20.1 SSL tunnel 20.2 nicer lacking perl message 20.3 more protocols supported 20.4 more platforms supported 20.5 Add support for concurrent connections 20.6 Use the RFC 6265 test suite 20.7 Support LD_PRELOAD on macOS 20.8 Run web-platform-tests URL tests 21. MQTT 21.1 Support rate-limiting ============================================================================== 1. libcurl 1.1 TFO support on Windows libcurl supports the CURLOPT_TCP_FASTOPEN option since 7.49.0 for Linux and Mac OS. Windows supports TCP Fast Open starting with Windows 10, version 1607 and we should add support for it. TCP Fast Open is supported on several platforms but not on Windows. Work on this was once started but never finished. See https://github.com/curl/curl/pull/3378 1.2 Consult %APPDATA% also for .netrc %APPDATA%\.netrc is not considered when running on Windows. should not it? See https://github.com/curl/curl/issues/4016 1.3 struct lifreq Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete. To support IPv6 interface addresses for network interfaces properly. 1.4 Better and more sharing The share interface could benefit from allowing the alt-svc cache to be possible to share between easy handles. See https://github.com/curl/curl/issues/4476 The share interface offers CURL_LOCK_DATA_CONNECT to have multiple easy handle share a connection cache, but due to how connections are used they are still not thread-safe when used shared. See https://github.com/curl/curl/issues/4915 and lib1541.c The share interface offers CURL_LOCK_DATA_HSTS to have multiple easy handle share a HSTS cache, but this is not thread-safe. 1.5 get rid of PATH_MAX Having code use and rely on PATH_MAX is not nice: https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html Currently the libssh2 SSH based code uses it, but to remove PATH_MAX from there we need libssh2 to properly tell us when we pass in a too small buffer and its current API (as of libssh2 1.2.7) does not. 1.6 native IDN support on macOS On recent macOS versions, the getaddrinfo() function itself has built-in IDN support. By setting the AI_CANONNAME flag, the function will return the encoded name in the ai_canonname struct field in the returned information. This could be used by curl on macOS when built without a separate IDN library and an IDN host name is used in a URL. See initial work in https://github.com/curl/curl/pull/5371 1.8 CURLOPT_RESOLVE for any port number This option allows applications to set a replacement IP address for a given host + port pair. Consider making support for providing a replacement address for the host name on all port numbers. See https://github.com/curl/curl/issues/1264 1.9 Cache negative name resolves A name resolve that has failed is likely to fail when made again within a short period of time. Currently we only cache positive responses. 1.10 auto-detect proxy libcurl could be made to detect the system proxy setup automatically and use that. On Windows, macOS and Linux desktops for example. The pull-request to use libproxy for this was deferred due to doubts on the reliability of the dependency and how to use it: https://github.com/curl/curl/pull/977 libdetectproxy is a (C++) library for detecting the proxy on Windows https://github.com/paulharris/libdetectproxy 1.11 minimize dependencies with dynamically loaded modules We can create a system with loadable modules/plug-ins, where these modules would be the ones that link to 3rd party libs. That would allow us to avoid having to load ALL dependencies since only the necessary ones for this app/invoke/used protocols would be necessary to load. See https://github.com/curl/curl/issues/349 1.12 updated DNS server while running If /etc/resolv.conf gets updated while a program using libcurl is running, it is may cause name resolves to fail unless res_init() is called. We should consider calling res_init() + retry once unconditionally on all name resolve failures to mitigate against this. Firefox works like that. Note that Windows does not have res_init() or an alternative. https://github.com/curl/curl/issues/2251 1.13 c-ares and CURLOPT_OPENSOCKETFUNCTION curl will create most sockets via the CURLOPT_OPENSOCKETFUNCTION callback and close them with the CURLOPT_CLOSESOCKETFUNCTION callback. However, c-ares does not use those functions and instead opens and closes the sockets itself. This means that when curl passes the c-ares socket to the CURLMOPT_SOCKETFUNCTION it is not owned by the application like other sockets. See https://github.com/curl/curl/issues/2734 1.15 Monitor connections in the connection pool libcurl's connection cache or pool holds a number of open connections for the purpose of possible subsequent connection reuse. It may contain a few up to a significant amount of connections. Currently, libcurl leaves all connections as they are and first when a connection is iterated over for matching or reuse purpose it is verified that it is still alive. Those connections may get closed by the server side for idleness or they may get an HTTP/2 ping from the peer to verify that they are still alive. By adding monitoring of the connections while in the pool, libcurl can detect dead connections (and close them) better and earlier, and it can handle HTTP/2 pings to keep such ones alive even when not actively doing transfers on them. 1.16 Try to URL encode given URL Given a URL that for example contains spaces, libcurl could have an option that would try somewhat harder than it does now and convert spaces to %20 and perhaps URL encoded byte values over 128 etc (basically do what the redirect following code already does). https://github.com/curl/curl/issues/514 1.17 Add support for IRIs IRIs (RFC 3987) allow localized, non-ascii, names in the URL. To properly support this, curl/libcurl would need to translate/encode the given input from the input string encoding into percent encoded output "over the wire". To make that work smoothly for curl users even on Windows, curl would probably need to be able to convert from several input encodings. 1.18 try next proxy if one does not work Allow an application to specify a list of proxies to try, and failing to connect to the first go on and try the next instead until the list is exhausted. Browsers support this feature at least when they specify proxies using PACs. https://github.com/curl/curl/issues/896 1.19 provide timing info for each redirect curl and libcurl provide timing information via a set of different time-stamps (CURLINFO_*_TIME). When curl is following redirects, those returned time value are the accumulated sums. An improvement could be to offer separate timings for each redirect. https://github.com/curl/curl/issues/6743 1.20 SRV and URI DNS records Offer support for resolving SRV and URI DNS records for libcurl to know which server to connect to for various protocols (including HTTP). 1.21 netrc caching and sharing The netrc file is read and parsed each time a connection is setup, which means that if a transfer needs multiple connections for authentication or redirects, the file might be reread (and parsed) multiple times. This makes it impossible to provide the file as a pipe. 1.22 CURLINFO_PAUSE_STATE Return information about the transfer's current pause state, in both directions. https://github.com/curl/curl/issues/2588 1.23 Offer API to flush the connection pool Sometimes applications want to flush all the existing connections kept alive. An API could allow a forced flush or just a forced loop that would properly close all connections that have been closed by the server already. 1.25 Expose tried IP addresses that failed When libcurl fails to connect to a host, it could offer the application the addresses that were used in the attempt. Source + dest IP, source + dest port and protocol (UDP or TCP) for each failure. Possibly as a callback. Perhaps also provide "reason". https://github.com/curl/curl/issues/2126 1.28 FD_CLOEXEC It sets the close-on-exec flag for the file descriptor, which causes the file descriptor to be automatically (and atomically) closed when any of the exec-family functions succeed. Should probably be set by default? https://github.com/curl/curl/issues/2252 1.29 Upgrade to websockets libcurl could offer a smoother path to get to a websocket connection. See https://github.com/curl/curl/issues/3523 Michael Kaufmann suggestion here: https://curl.se/video/curlup-2017/2017-03-19_05_Michael_Kaufmann_Websocket_support_for_curl.mp4 1.30 config file parsing Consider providing an API, possibly in a separate companion library, for parsing a config file like curl's -K/--config option to allow applications to get the same ability to read curl options from files. See https://github.com/curl/curl/issues/3698 1.31 erase secrets from heap/stack after use Introducing a concept and system to erase secrets from memory after use, it could help mitigate and lessen the impact of (future) security problems etc. However: most secrets are passed to libcurl as clear text from the application and then clearing them within the library adds nothing... https://github.com/curl/curl/issues/7268 1.32 add asynch getaddrinfo support Use getaddrinfo_a() to provide an asynch name resolver backend to libcurl that does not use threads and does not depend on c-ares. The getaddrinfo_a function is (probably?) glibc specific but that is a widely used libc among our users. https://github.com/curl/curl/pull/6746 1.33 make DoH inherit more transfer properties Some options are not inherited because they are not relevant for the DoH SSL connections, or inheriting the option may result in unexpected behavior. For example the user's debug function callback is not inherited because it would be unexpected for internal handles (ie DoH handles) to be passed to that callback. If an option is not inherited then it is not possible to set it separately for DoH without a DoH-specific option. For example: CURLOPT_DOH_SSL_VERIFYHOST, CURLOPT_DOH_SSL_VERIFYPEER and CURLOPT_DOH_SSL_VERIFYSTATUS. See https://github.com/curl/curl/issues/6605 2. libcurl - multi interface 2.1 More non-blocking Make sure we do not ever loop because of non-blocking sockets returning EWOULDBLOCK or similar. Blocking cases include: - Name resolves on non-windows unless c-ares or the threaded resolver is used. - The threaded resolver may block on cleanup: https://github.com/curl/curl/issues/4852 - file:// transfers - TELNET transfers - GSSAPI authentication for FTP transfers - The "DONE" operation (post transfer protocol-specific actions) for the protocols SFTP, SMTP, FTP. Fixing multi_done() for this is a worthy task. - curl_multi_remove_handle for any of the above. See section 2.3. 2.2 Better support for same name resolves If a name resolve has been initiated for name NN and a second easy handle wants to resolve that name as well, make it wait for the first resolve to end up in the cache instead of doing a second separate resolve. This is especially needed when adding many simultaneous handles using the same host name when the DNS resolver can get flooded. 2.3 Non-blocking curl_multi_remove_handle() The multi interface has a few API calls that assume a blocking behavior, like add_handle() and remove_handle() which limits what we can do internally. The multi API need to be moved even more into a single function that "drives" everything in a non-blocking manner and signals when something is done. A remove or add would then only ask for the action to get started and then multi_perform() etc still be called until the add/remove is completed. 2.4 Split connect and authentication process The multi interface treats the authentication process as part of the connect phase. As such any failures during authentication will not trigger the relevant QUIT or LOGOFF for protocols such as IMAP, POP3 and SMTP. 2.5 Edge-triggered sockets should work The multi_socket API should work with edge-triggered socket events. One of the internal actions that need to be improved for this to work perfectly is the 'maxloops' handling in transfer.c:readwrite_data(). 2.6 multi upkeep In libcurl 7.62.0 we introduced curl_easy_upkeep. It unfortunately only works on easy handles. We should introduces a version of that for the multi handle, and also consider doing "upkeep" automatically on connections in the connection pool when the multi handle is in used. See https://github.com/curl/curl/issues/3199 2.7 Virtual external sockets libcurl performs operations on the given file descriptor that presumes it is a socket and an application cannot replace them at the moment. Allowing an application to fully replace those would allow a larger degree of freedom and flexibility. See https://github.com/curl/curl/issues/5835 2.8 dynamically decide to use socketpair For users who do not use curl_multi_wait() or do not care for curl_multi_wakeup(), we could introduce a way to make libcurl NOT create a socketpair in the multi handle. See https://github.com/curl/curl/issues/4829 3. Documentation 3.1 Improve documentation about fork safety See https://github.com/curl/curl/issues/6968 3.2 Provide cmake config-file A config-file package is a set of files provided by us to allow applications to write cmake scripts to find and use libcurl easier. See https://github.com/curl/curl/issues/885 4. FTP 4.1 HOST HOST is a command for a client to tell which host name to use, to offer FTP servers named-based virtual hosting: https://datatracker.ietf.org/doc/html/rfc7151 4.2 Alter passive/active on failure and retry When trying to connect passively to a server which only supports active connections, libcurl returns CURLE_FTP_WEIRD_PASV_REPLY and closes the connection. There could be a way to fallback to an active connection (and vice versa). https://curl.se/bug/feature.cgi?id=1754793 4.3 Earlier bad letter detection Make the detection of (bad) %0d and %0a codes in FTP URL parts earlier in the process to avoid doing a resolve and connect in vain. 4.4 Support CURLOPT_PREQUOTE for dir listings too The lack of support is mostly an oversight and requires the FTP state machine to get updated to get fixed. https://github.com/curl/curl/issues/8602 4.5 ASCII support FTP ASCII transfers do not follow RFC 959. They do not convert the data accordingly. 4.6 GSSAPI via Windows SSPI In addition to currently supporting the SASL GSSAPI mechanism (Kerberos V5) via third-party GSS-API libraries, such as Heimdal or MIT Kerberos, also add support for GSSAPI authentication via Windows SSPI. 4.7 STAT for LIST without data connection Some FTP servers allow STAT for listing directories instead of using LIST, and the response is then sent over the control connection instead of as the otherwise usedw data connection: https://www.nsftools.com/tips/RawFTP.htm#STAT This is not detailed in any FTP specification. 4.8 Passive transfer could try other IP addresses When doing FTP operations through a proxy at localhost, the reported spotted that curl only tried to connect once to the proxy, while it had multiple addresses and a failed connect on one address should make it try the next. After switching to passive mode (EPSV), curl could try all IP addresses for "localhost". Currently it tries ::1, but it should also try 127.0.0.1. See https://github.com/curl/curl/issues/1508 5. HTTP 5.1 Provide the error body from a CONNECT response When curl receives a body response from a CONNECT request to a proxy, it will always just read and ignore it. It would make some users happy if curl instead optionally would be able to make that responsible available. Via a new callback? Through some other means? See https://github.com/curl/curl/issues/9513 5.2 Obey Retry-After in redirects The Retry-After is said to dicate "the minimum time that the user agent is asked to wait before issuing the redirected request" and libcurl does not obey this. See https://github.com/curl/curl/issues/11447 5.3 Rearrange request header order Server implementors often make an effort to detect browser and to reject clients it can detect to not match. One of the last details we cannot yet control in libcurl's HTTP requests, which also can be exploited to detect that libcurl is in fact used even when it tries to impersonate a browser, is the order of the request headers. I propose that we introduce a new option in which you give headers a value, and then when the HTTP request is built it sorts the headers based on that number. We could then have internally created headers use a default value so only headers that need to be moved have to be specified. 5.4 Allow SAN names in HTTP/2 server push curl only allows HTTP/2 push promise if the provided :authority header value exactly matches the host name given in the URL. It could be extended to allow any name that would match the Subject Alternative Names in the server's TLS certificate. See https://github.com/curl/curl/pull/3581 5.5 auth= in URLs Add the ability to specify the preferred authentication mechanism to use by using ;auth=<mech> in the login part of the URL. For example: http://test:pass;auth=NTLM@example.com would be equivalent to specifying --user test:pass;auth=NTLM or --user test:pass --ntlm from the command line. Additionally this should be implemented for proxy base URLs as well. 5.6 alt-svc should fallback if alt-svc does not work The alt-svc: header provides a set of alternative services for curl to use instead of the original. If the first attempted one fails, it should try the next etc and if all alternatives fail go back to the original. See https://github.com/curl/curl/issues/4908 5.7 Require HTTP version X or higher curl and libcurl provide options for trying higher HTTP versions (for example HTTP/2) but then still allows the server to pick version 1.1. We could consider adding a way to require a minimum version. See https://github.com/curl/curl/issues/7980 6. TELNET 6.1 ditch stdin Reading input (to send to the remote server) on stdin is a crappy solution for library purposes. We need to invent a good way for the application to be able to provide the data to send. 6.2 ditch telnet-specific select Move the telnet support's network select() loop go away and merge the code into the main transfer loop. Until this is done, the multi interface will not work for telnet. 6.3 feature negotiation debug data Add telnet feature negotiation data to the debug callback as header data. 6.4 exit immediately upon connection if stdin is /dev/null If it did, curl could be used to probe if there's an server there listening on a specific port. That is, the following command would exit immediately after the connection is established with exit code 0: curl -s --connect-timeout 2 telnet://example.com:80 </dev/null 7. SMTP 7.1 Passing NOTIFY option to CURLOPT_MAIL_RCPT Is there a way to pass the NOTIFY option to the CURLOPT_MAIL_RCPT option ? I set a string that already contains a bracket. For instance something like that: curl_slist_append( recipients, "<foo@bar> NOTIFY=SUCCESS,FAILURE" ); https://github.com/curl/curl/issues/8232 7.2 Enhanced capability support Add the ability, for an application that uses libcurl, to obtain the list of capabilities returned from the EHLO command. 7.3 Add CURLOPT_MAIL_CLIENT option Rather than use the URL to specify the mail client string to present in the HELO and EHLO commands, libcurl should support a new CURLOPT specifically for specifying this data as the URL is non-standard and to be honest a bit of a hack ;-) Please see the following thread for more information: https://curl.se/mail/lib-2012-05/0178.html 8. POP3 8.2 Enhanced capability support Add the ability, for an application that uses libcurl, to obtain the list of capabilities returned from the CAPA command. 9. IMAP 9.1 Enhanced capability support Add the ability, for an application that uses libcurl, to obtain the list of capabilities returned from the CAPABILITY command. 10. LDAP 10.1 SASL based authentication mechanisms Currently the LDAP module only supports ldap_simple_bind_s() in order to bind to an LDAP server. However, this function sends username and password details using the simple authentication mechanism (as clear text). However, it should be possible to use ldap_bind_s() instead specifying the security context information ourselves. 10.2 CURLOPT_SSL_CTX_FUNCTION for LDAPS CURLOPT_SSL_CTX_FUNCTION works perfectly for HTTPS and email protocols, but it has no effect for LDAPS connections. https://github.com/curl/curl/issues/4108 10.3 Paged searches on LDAP server https://github.com/curl/curl/issues/4452 11. SMB 11.1 File listing support Add support for listing the contents of a SMB share. The output should probably be the same as/similar to FTP. 11.2 Honor file timestamps The timestamp of the transferred file should reflect that of the original file. 11.3 Use NTLMv2 Currently the SMB authentication uses NTLMv1. 11.4 Create remote directories Support for creating remote directories when uploading a file to a directory that does not exist on the server, just like --ftp-create-dirs. 12. FILE 12.1 Directory listing for FILE: Add support for listing the contents of a directory accessed with FILE. The output should probably be the same as/similar to FTP. 13. TLS 13.1 TLS-PSK with OpenSSL Transport Layer Security pre-shared key ciphersuites (TLS-PSK) is a set of cryptographic protocols that provide secure communication based on pre-shared keys (PSKs). These pre-shared keys are symmetric keys shared in advance among the communicating parties. https://github.com/curl/curl/issues/5081 13.2 Provide mutex locking API Provide a libcurl API for setting mutex callbacks in the underlying SSL library, so that the same application code can use mutex-locking independently of OpenSSL or GnutTLS being used. 13.3 Defeat TLS fingerprinting By changing the order of TLS extensions provided in the TLS handshake, it is sometimes possible to circumvent TLS fingerprinting by servers. The TLS extension order is of course not the only way to fingerprint a client. See https://github.com/curl/curl/issues/8119 13.4 Cache/share OpenSSL contexts "Look at SSL cafile - quick traces look to me like these are done on every request as well, when they should only be necessary once per SSL context (or once per handle)". The major improvement we can rather easily do is to make sure we do not create and kill a new SSL "context" for every request, but instead make one for every connection and re-use that SSL context in the same style connections are re-used. It will make us use slightly more memory but it will libcurl do less creations and deletions of SSL contexts. Technically, the "caching" is probably best implemented by getting added to the share interface so that easy handles who want to and can reuse the context specify that by sharing with the right properties set. https://github.com/curl/curl/issues/1110 13.5 Export session ids Add an interface to libcurl that enables "session IDs" to get exported/imported. Cris Bailiff said: "OpenSSL has functions which can serialise the current SSL state to a buffer of your choice, and recover/reset the state from such a buffer at a later date - this is used by mod_ssl for apache to implement and SSL session ID cache". 13.6 Provide callback for cert verification OpenSSL supports a callback for customised verification of the peer certificate, but this does not seem to be exposed in the libcurl APIs. Could it be? There's so much that could be done if it were. 13.7 Less memory massaging with Schannel The Schannel backend does a lot of custom memory management we would rather avoid: the repeated alloc + free in sends and the custom memory + realloc system for encrypted and decrypted data. That should be avoided and reduced for 1) efficiency and 2) safety. 13.8 Support DANE DNS-Based Authentication of Named Entities (DANE) is a way to provide SSL keys and certs over DNS using DNSSEC as an alternative to the CA model. https://www.rfc-editor.org/rfc/rfc6698.txt An initial patch was posted by Suresh Krishnaswamy on March 7th 2013 (https://curl.se/mail/lib-2013-03/0075.html) but it was a too simple approach. See Daniel's comments: https://curl.se/mail/lib-2013-03/0103.html . libunbound may be the correct library to base this development on. Björn Stenberg wrote a separate initial take on DANE that was never completed. 13.9 TLS record padding TLS (1.3) offers optional record padding and OpenSSL provides an API for it. I could make sense for libcurl to offer this ability to applications to make traffic patterns harder to figure out by network traffic observers. See https://github.com/curl/curl/issues/5398 13.10 Support Authority Information Access certificate extension (AIA) AIA can provide various things like CRLs but more importantly information about intermediate CA certificates that can allow validation path to be fulfilled when the HTTPS server does not itself provide them. Since AIA is about downloading certs on demand to complete a TLS handshake, it is probably a bit tricky to get done right. See https://github.com/curl/curl/issues/2793 13.11 Support intermediate & root pinning for PINNEDPUBLICKEY CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root certificates when comparing the pinned keys. Therefore it is not compatible with "HTTP Public Key Pinning" as there also intermediate and root certificates can be pinned. This is useful as it prevents webadmins from "locking themselves out of their servers". Adding this feature would make curls pinning 100% compatible to HPKP and allow more flexible pinning. 13.12 Reduce CA certificate bundle reparsing When using the OpenSSL backend, curl will load and reparse the CA bundle at the creation of the "SSL context" when it sets up a connection to do a TLS handshake. A more effective way would be to somehow cache the CA bundle to avoid it having to be repeatedly reloaded and reparsed. See https://github.com/curl/curl/issues/9379 13.13 Make sure we forbid TLS 1.3 post-handshake authentication RFC 8740 explains how using HTTP/2 must forbid the use of TLS 1.3 post-handshake authentication. We should make sure to live up to that. See https://github.com/curl/curl/issues/5396 13.14 Support the clienthello extension Certain stupid networks and middle boxes have a problem with SSL handshake packets that are within a certain size range because how that sets some bits that previously (in older TLS version) were not set. The clienthello extension adds padding to avoid that size range. https://datatracker.ietf.org/doc/html/rfc7685 https://github.com/curl/curl/issues/2299 14. GnuTLS 14.2 check connection Add a way to check if the connection seems to be alive, to correspond to the SSL_peak() way we use with OpenSSL. 15. Schannel 15.1 Extend support for client certificate authentication The existing support for the -E/--cert and --key options could be extended by supplying a custom certificate and key in PEM format, see: - Getting a Certificate for Schannel https://msdn.microsoft.com/en-us/library/windows/desktop/aa375447.aspx 15.2 Extend support for the --ciphers option The existing support for the --ciphers option could be extended by mapping the OpenSSL/GnuTLS cipher suites to the Schannel APIs, see - Specifying Schannel Ciphers and Cipher Strengths https://msdn.microsoft.com/en-us/library/windows/desktop/aa380161.aspx 15.4 Add option to allow abrupt server closure libcurl w/schannel will error without a known termination point from the server (such as length of transfer, or SSL "close notify" alert) to prevent against a truncation attack. Really old servers may neglect to send any termination point. An option could be added to ignore such abrupt closures. https://github.com/curl/curl/issues/4427 16. SASL 16.1 Other authentication mechanisms Add support for other authentication mechanisms such as OLP, GSS-SPNEGO and others. 16.2 Add QOP support to GSSAPI authentication Currently the GSSAPI authentication only supports the default QOP of auth (Authentication), whilst Kerberos V5 supports both auth-int (Authentication with integrity protection) and auth-conf (Authentication with integrity and privacy protection). 17. SSH protocols 17.1 Multiplexing SSH is a perfectly fine multiplexed protocols which would allow libcurl to do multiple parallel transfers from the same host using the same connection, much in the same spirit as HTTP/2 does. libcurl however does not take advantage of that ability but will instead always create a new connection for new transfers even if an existing connection already exists to the host. To fix this, libcurl would have to detect an existing connection and "attach" the new transfer to the existing one. 17.2 Handle growing SFTP files The SFTP code in libcurl checks the file size *before* a transfer starts and then proceeds to transfer exactly that amount of data. If the remote file grows while the transfer is in progress libcurl will not notice and will not adapt. The OpenSSH SFTP command line tool does and libcurl could also just attempt to download more to see if there is more to get... https://github.com/curl/curl/issues/4344 17.3 Read keys from ~/.ssh/id_ecdsa, id_ed25519 The libssh2 backend in curl is limited to only reading keys from id_rsa and id_dsa, which makes it fail connecting to servers that use more modern key types. https://github.com/curl/curl/issues/8586 17.4 Support CURLOPT_PREQUOTE The two other QUOTE options are supported for SFTP, but this was left out for unknown reasons. 17.5 SSH over HTTPS proxy with more backends The SSH based protocols SFTP and SCP did not work over HTTPS proxy at all until PR https://github.com/curl/curl/pull/6021 brought the functionality with the libssh2 backend. Presumably, this support can/could be added for the other backends as well. 17.6 SFTP with SCP:// OpenSSH 9 switched their 'scp' tool to speak SFTP under the hood. Going forward it might be worth having curl or libcurl attempt SFTP if SCP fails to follow suite. 18. Command line tool 18.1 sync "curl --sync http://example.com/feed[1-100].rss" or "curl --sync http://example.net/{index,calendar,history}.html" Downloads a range or set of URLs using the remote name, but only if the remote file is newer than the local file. A Last-Modified HTTP date header should also be used to set the mod date on the downloaded file. 18.2 glob posts Globbing support for -d and -F, as in 'curl -d "name=foo[0-9]" URL'. This is easily scripted though. 18.4 --proxycommand Allow the user to make curl run a command and use its stdio to make requests and not do any network connection by itself. Example: curl --proxycommand 'ssh pi@raspberrypi.local -W 10.1.1.75 80' \ http://some/otherwise/unavailable/service.php See https://github.com/curl/curl/issues/4941 18.5 UTF-8 filenames in Content-Disposition RFC 6266 documents how UTF-8 names can be passed to a client in the Content-Disposition header, and curl does not support this. https://github.com/curl/curl/issues/1888 18.6 Option to make -Z merge lined based outputs on stdout When a user requests multiple lined based files using -Z and sends them to stdout, curl will not "merge" and send complete lines fine but may send partial lines from several sources. https://github.com/curl/curl/issues/5175 18.8 Consider convenience options for JSON and XML? Could we add `--xml` or `--json` to add headers needed to call rest API: `--xml` adds -H 'Content-Type: application/xml' -H "Accept: application/xml" and `--json` adds -H 'Content-Type: application/json' -H "Accept: application/json" Setting Content-Type when doing a GET or any other method without a body would be a bit strange I think - so maybe only add CT for requests with body? Maybe plain `--xml` and ` --json` are a bit too brief and generic. Maybe `--http-json` etc? See https://github.com/curl/curl/issues/5203 18.9 Choose the name of file in braces for complex URLs When using braces to download a list of URLs and you use complicated names in the list of alternatives, it could be handy to allow curl to use other names when saving. Consider a way to offer that. Possibly like {partURL1:name1,partURL2:name2,partURL3:name3} where the name following the colon is the output name. See https://github.com/curl/curl/issues/221 18.10 improve how curl works in a windows console window If you pull the scrollbar when transferring with curl in a Windows console window, the transfer is interrupted and can get disconnected. This can probably be improved. See https://github.com/curl/curl/issues/322 18.11 Windows: set attribute 'archive' for completed downloads The archive bit (FILE_ATTRIBUTE_ARCHIVE, 0x20) separates files that shall be backed up from those that are either not ready or have not changed. Downloads in progress are neither ready to be backed up, nor should they be opened by a different process. Only after a download has been completed it's sensible to include it in any integer snapshot or backup of the system. See https://github.com/curl/curl/issues/3354 18.12 keep running, read instructions from pipe/socket Provide an option that makes curl not exit after the last URL (or even work without a given URL), and then make it read instructions passed on a pipe or over a socket to make further instructions so that a second subsequent curl invoke can talk to the still running instance and ask for transfers to get done, and thus maintain its connection pool, DNS cache and more. 18.13 Ratelimit or wait between serial requests Consider a command line option that can make curl do multiple serial requests slow, potentially with a (random) wait between transfers. There's also a proposed set of standard HTTP headers to let servers let the client adapt to its rate limits: https://www.ietf.org/id/draft-polli-ratelimit-headers-02.html See https://github.com/curl/curl/issues/5406 18.14 --dry-run A command line option that makes curl show exactly what it would do and send if it would run for real. See https://github.com/curl/curl/issues/5426 18.15 --retry should resume When --retry is used and curl actually retries transfer, it should use the already transferred data and do a resumed transfer for the rest (when possible) so that it does not have to transfer the same data again that was already transferred before the retry. See https://github.com/curl/curl/issues/1084 18.16 send only part of --data When the user only wants to send a small piece of the data provided with --data or --data-binary, like when that data is a huge file, consider a way to specify that curl should only send a piece of that. One suggested syntax would be: "--data-binary @largefile.zip!1073741823-2147483647". See https://github.com/curl/curl/issues/1200 18.17 consider file name from the redirected URL with -O ? When a user gives a URL and uses -O, and curl follows a redirect to a new URL, the file name is not extracted and used from the newly redirected-to URL even if the new URL may have a much more sensible file name. This is clearly documented and helps for security since there's no surprise to users which file name that might get overwritten. But maybe a new option could allow for this or maybe -J should imply such a treatment as well as -J already allows for the server to decide what file name to use so it already provides the "may overwrite any file" risk. This is extra tricky if the original URL has no file name part at all since then the current code path will error out with an error message, and we cannot *know* already at that point if curl will be redirected to a URL that has a file name... See https://github.com/curl/curl/issues/1241 18.18 retry on network is unreachable The --retry option retries transfers on "transient failures". We later added --retry-connrefused to also retry for "connection refused" errors. Suggestions have been brought to also allow retry on "network is unreachable" errors and while totally reasonable, maybe we should consider a way to make this more configurable than to add a new option for every new error people want to retry for? https://github.com/curl/curl/issues/1603 18.19 expand ~/ in config files For example .curlrc could benefit from being able to do this. See https://github.com/curl/curl/issues/2317 18.20 host name sections in config files config files would be more powerful if they could set different configurations depending on used URLs, host name or possibly origin. Then a default .curlrc could a specific user-agent only when doing requests against a certain site. 18.21 retry on the redirected-to URL When curl is told to --retry a failed transfer and follows redirects, it might get an HTTP 429 response from the redirected-to URL and not the original one, which then could make curl decide to rather retry the transfer on that URL only instead of the original operation to the original URL. Perhaps extra emphasized if the original transfer is a large POST that redirects to a separate GET, and that GET is what gets the 529 See https://github.com/curl/curl/issues/5462 18.23 Set the modification date on an uploaded file For SFTP and possibly FTP, curl could offer an option to set the modification time for the uploaded file. See https://github.com/curl/curl/issues/5768 18.24 Use multiple parallel transfers for a single download To enhance transfer speed, downloading a single URL can be split up into multiple separate range downloads that get combined into a single final result. An ideal implementation would not use a specified number of parallel transfers, but curl could: - First start getting the full file as transfer A - If after N seconds have passed and the transfer is expected to continue for M seconds or more, add a new transfer (B) that asks for the second half of A's content (and stop A at the middle). - If splitting up the work improves the transfer rate, it could then be done again. Then again, etc up to a limit. This way, if transfer B fails (because Range: is not supported) it will let transfer A remain the single one. N and M could be set to some sensible defaults. See https://github.com/curl/curl/issues/5774 18.25 Prevent terminal injection when writing to terminal curl could offer an option to make escape sequence either non-functional or avoid cursor moves or similar to reduce the risk of a user getting tricked by clever tricks. See https://github.com/curl/curl/issues/6150 18.26 Custom progress meter update interval Users who are for example doing large downloads in CI or remote setups might want the occasional progress meter update to see that the transfer is progressing and has not stuck, but they may not appreciate the many-times-a-second frequency curl can end up doing it with now. 18.27 -J and -O with %-encoded file names -J/--remote-header-name does not decode %-encoded file names. RFC 6266 details how it should be done. The can of worm is basically that we have no charset handling in curl and ascii >=128 is a challenge for us. Not to mention that decoding also means that we need to check for nastiness that is attempted, like "../" sequences and the like. Probably everything to the left of any embedded slashes should be cut off. https://curl.se/bug/view.cgi?id=1294 -O also does not decode %-encoded names, and while it has even less information about the charset involved the process is similar to the -J case. Note that we will not add decoding to -O without the user asking for it with some other means as well, since -O has always been documented to use the name exactly as specified in the URL. 18.28 -J with -C - When using -J (with -O), automatically resumed downloading together with "-C -" fails. Without -J the same command line works. This happens because the resume logic is worked out before the target file name (and thus its pre-transfer size) has been figured out. This can be improved. https://curl.se/bug/view.cgi?id=1169 18.29 --retry and transfer timeouts If using --retry and the transfer timeouts (possibly due to using -m or -y/-Y) the next attempt does not resume the transfer properly from what was downloaded in the previous attempt but will truncate and restart at the original position where it was at before the previous failed attempt. See https://curl.se/mail/lib-2008-01/0080.html and Mandriva bug report https://qa.mandriva.com/show_bug.cgi?id=22565 19. Build 19.1 roffit Consider extending 'roffit' to produce decent ASCII output, and use that instead of (g)nroff when building src/tool_hugehelp.c 19.2 Enable PIE and RELRO by default Especially when having programs that execute curl via the command line, PIE renders the exploitation of memory corruption vulnerabilities a lot more difficult. This can be attributed to the additional information leaks being required to conduct a successful attack. RELRO, on the other hand, masks different binary sections like the GOT as read-only and thus kills a handful of techniques that come in handy when attackers are able to arbitrarily overwrite memory. A few tests showed that enabling these features had close to no impact, neither on the performance nor on the general functionality of curl. 19.3 Do not use GNU libtool on OpenBSD When compiling curl on OpenBSD with "--enable-debug" it will give linking errors when you use GNU libtool. This can be fixed by using the libtool provided by OpenBSD itself. However for this the user always needs to invoke make with "LIBTOOL=/usr/bin/libtool". It would be nice if the script could have some magic to detect if this system is an OpenBSD host and then use the OpenBSD libtool instead. See https://github.com/curl/curl/issues/5862 19.4 Package curl for Windows in a signed installer See https://github.com/curl/curl/issues/5424 19.5 make configure use --cache-file more and better The configure script can be improved to cache more values so that repeated invokes run much faster. See https://github.com/curl/curl/issues/7753 19.6 build curl with Windows Unicode support The user wants an easier way to tell autotools to build curl with Windows Unicode support, like ./configure --enable-windows-unicode See https://github.com/curl/curl/issues/7229 20. Test suite 20.1 SSL tunnel Make our own version of stunnel for simple port forwarding to enable HTTPS and FTP-SSL tests without the stunnel dependency, and it could allow us to provide test tools built with either OpenSSL or GnuTLS 20.2 nicer lacking perl message If perl was not found by the configure script, do not attempt to run the tests but explain something nice why it does not. 20.3 more protocols supported Extend the test suite to include more protocols. The telnet could just do FTP or http operations (for which we have test servers). 20.4 more platforms supported Make the test suite work on more platforms. OpenBSD and Mac OS. Remove fork()s and it should become even more portable. 20.5 Add support for concurrent connections Tests 836, 882 and 938 were designed to verify that separate connections are not used when using different login credentials in protocols that should not re-use a connection under such circumstances. Unfortunately, ftpserver.pl does not appear to support multiple concurrent connections. The read while() loop seems to loop until it receives a disconnect from the client, where it then enters the waiting for connections loop. When the client opens a second connection to the server, the first connection has not been dropped (unless it has been forced - which we should not do in these tests) and thus the wait for connections loop is never entered to receive the second connection. 20.6 Use the RFC 6265 test suite A test suite made for HTTP cookies (RFC 6265) by Adam Barth is available at https://github.com/abarth/http-state/tree/master/tests It'd be really awesome if someone would write a script/setup that would run curl with that test suite and detect deviances. Ideally, that would even be incorporated into our regular test suite. 20.7 Support LD_PRELOAD on macOS LD_RELOAD does not work on macOS, but there are tests which require it to run properly. Look into making the preload support in runtests.pl portable such that it uses DYLD_INSERT_LIBRARIES on macOS. 20.8 Run web-platform-tests URL tests Run web-platform-tests URL tests and compare results with browsers on wpt.fyi It would help us find issues to fix and help us document where our parser differs from the WHATWG URL spec parsers. See https://github.com/curl/curl/issues/4477 21. MQTT 21.1 Support rate-limiting The rate-limiting logic is done in the PERFORMING state in multi.c but MQTT is not (yet) implemented to use that. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/VERSIONS.md��������������������������������������������������������������������������0000644�����������������00000004356�15253042577�0011144 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Version Numbers and Releases ============================ Curl is not only curl. Curl is also libcurl. They are actually individually versioned, but they usually follow each other closely. The version numbering is always built up using the same system: X.Y.Z - X is main version number - Y is release number - Z is patch number ## Bumping numbers One of these numbers will get bumped in each new release. The numbers to the right of a bumped number will be reset to zero. The main version number will get bumped when *really* big, world colliding changes are made. The release number is bumped when changes are performed or things/features are added. The patch number is bumped when the changes are mere bugfixes. It means that after release 1.2.3, we can release 2.0.0 if something really big has been made, 1.3.0 if not that big changes were made or 1.2.4 if only bugs were fixed. Bumping, as in increasing the number with 1, is unconditionally only affecting one of the numbers (except the ones to the right of it, that may be set to zero). 1 becomes 2, 3 becomes 4, 9 becomes 10, 88 becomes 89 and 99 becomes 100. So, after 1.2.9 comes 1.2.10. After 3.99.3, 3.100.0 might come. All original curl source release archives are named according to the libcurl version (not according to the curl client version that, as said before, might differ). As a service to any application that might want to support new libcurl features while still being able to build with older versions, all releases have the libcurl version stored in the `curl/curlver.h` file using a static numbering scheme that can be used for comparison. The version number is defined as: ```c #define LIBCURL_VERSION_NUM 0xXXYYZZ ``` Where `XX`, `YY` and `ZZ` are the main version, release and patch numbers in hexadecimal. All three number fields are always represented using two digits (eight bits each). 1.2 would appear as "0x010200" while version 9.11.7 appears as `0x090b07`. This 6-digit hexadecimal number is always a greater number in a more recent release. It makes comparisons with greater than and less than work. This number is also available as three separate defines: `LIBCURL_VERSION_MAJOR`, `LIBCURL_VERSION_MINOR` and `LIBCURL_VERSION_PATCH`. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/INSTALL������������������������������������������������������������������������������0000644�����������������00000000473�15253042577�0010377 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | | (__| |_| | _ <| |___ \___|\___/|_| \_\_____| How To Compile see INSTALL.md �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/CHANGES������������������������������������������������������������������������������0000644�����������������00000733207�15253042577�0010351 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | | (__| |_| | _ <| |___ \___|\___/|_| \_\_____| Changelog Version 8.2.1 (26 Jul 2023) Daniel Stenberg (26 Jul 2023) - RELEASE-NOTES: synced curl 8.2.1 release - THANKS: add contributors from 8.2.1 - docs: provide more see also for cipher options More cross references. Hide nroff errors. Closes #11513 - docs: mark two TLS options for TLS, not SSL Closes #11514 Brad Harder (25 Jul 2023) - curl_multi_wait.3: fix arg quoting to doc macro .BR Closes #11511 Daniel Stenberg (24 Jul 2023) - RELEASE-NOTES: synced Viktor Szakats (24 Jul 2023) - cmake: update ngtcp2 detection Replace `OpenSSL` with `quictls` to follow the same change in the v0.17.0 ngtcp2 release. Follow-up to e0093b4b732f6495b0fb1cd6747cbfedcdcf63ed Closes #11508 Stefan Eissing (24 Jul 2023) - http: VLH, very large header test and fixes - adding tests using very large passwords in auth - fixes general http sending to treat h3 like h2, and not like http1.1 - eliminate H2_HEADER max definitions and use the commmon DYN_HTTP_REQUEST everywhere, different limits do not help - fix http2 handling of requests denied by nghttp2 on send to immediately report the refused stream Closes #11509 Andrei Rybak (23 Jul 2023) - CONTRIBUTE: drop mention of copyright year ranges Year ranges in copyrights were dropped in commits [1] and [2]. Verification of year ranges in copyrights was dropped from script 'scripts/copyright.pl' in commit [3]. However, the corresponding passages in file 'docs/CONTRIBUTE.md' weren't updated. Drop mentions of copyright year ranges from 'docs/CONTRIBUTE.md'. [1] 2bc1d775f (copyright: update all copyright lines and remove year ranges, 2023-01-02) [2] c46761bd8 (tests/http: remove year ranges from copyrights, 2023-03-14) [3] 0e293bacb (copyright.pl: cease doing year verifications, 2023-01-28) Closes #11504 - CONTRIBUTE: fix syntax in commit message description File 'docs/CONTRIBUTE.md' includes a description of how one should write commit messages in the curl project. Different possible parts of the message are enclosed in square brackets. One exception is the section describing how the curl project doesn't use "Signed-off-by" commit trailers [1], which is enclosed in an opening curly brace paired with a closing square bracket. Fix the enclosing square brackets in description of "Signed-off-by" trailers in commit messages in file 'docs/CONTRIBUTE.md'. [1] See description of option '--signoff' in Git documentation: https://git-scm.com/docs/git-commit Closes #11504 Daniel Stenberg (23 Jul 2023) - src/mkhelp: strip off escape sequences At some point the nroff command stopped stripping off escape sequences, so then this script needs to do the job instead. Reported-by: VictorVG on github Fixes #11501 Closes #11503 - KNOWN_BUGS: building for old macOS fails with gcc Closes #11441 Jacob Hoffman-Andrews (22 Jul 2023) - rustls: update rustls-ffi 0.10.0 This brings in version 0.21.0 of the upstream rustls implementation, which notable includes support for IP address certificates. Closes #10865 Brad Harder (22 Jul 2023) - websocket: rename arguments/variables to match docs Pedantry/semantic-alignment between functions, docs, comments with respect to websocket protocol code; No functional change intended. * "totalsize", "framesize" becomes "fragsize" (we deal in frame fragments). * "sendflags" becomes "flags" * use canonical CURL *handle Closes #11493 Jan Macku (21 Jul 2023) - bug_report: use issue forms instead of markdown template Issue forms allow you to define web-like input forms using YAML syntax. It allows you to guide the reporter to get the required information. Signed-off-by: Jan Macku <jamacku@redhat.com> Closes #11474 Daniel Stenberg (21 Jul 2023) - TODO: Obey Retry-After in redirects (remove "Set custom client ip when using haproxy protocol" which was shipped in 8.2.0) Mentioned-by: Yair Lenga Closes #11447 - RELEASE-NOTES: synced Oliver Roberts (21 Jul 2023) - amissl: fix AmiSSL v5 detection Due to changes in the AmiSSL SDK, the detection needed adjusting. Closes #11477 Alois Klink (21 Jul 2023) - unittest/makefile: remove unneeded unit1621_LDADD The `unit1621_LDADD` variable has the exact same value as the `LDADD` flag in `Makefile.am`, except without `@LDFLAGS@ @LIBCURL_LIBS@`. This was originally added by [98e6629][], but I can't see any reason why it exists, so we should remove it to clean things up. [98e6629]: https://github.com/curl/curl/commit/98e6629154044e4ab1ee7cff8351c7 ebcb131e88 Closes #11494 - unittest/makefile: remove unneeded unit1394_LDADD These custom `unit1394_LDADD` and similar automake overrides are no longer neded. They were originally added by added by [8dac7be][] for metalink support, but are no longer after [265b14d][] removed metalink. [8dac7be]: https://github.com/curl/curl/commit/8dac7be438512a8725d3c71e9139bd fdcac1ed8c [265b14d]: https://github.com/curl/curl/commit/265b14d6b37c4298bd5556fabcbc37 d36f911693 Closes #11494 - cmake: add `libcurlu`/`libcurltool` for unit tests Add a `libcurlu`/`libcurltool` static library that is compiled only for unit tests. We use `EXCLUDE_FROM_ALL` to make sure that they're not built by default, they're only built if unit tests are built. These libraries allow us to compile every unit test with CMake. Closes #11446 Daniel Stenberg (21 Jul 2023) - test979: test -u with redirect to (the same) absolute host Verifies #11492 - transfer: do not clear the credentials on redirect to absolute URL Makes test 979 work. Regression shipped in 8.2.0 from commit dd4d1a26959f63a2c Fixes #11486 Reported-by: Cloudogu Siebels Closes #11492 Jon Rumsey (20 Jul 2023) - os400: correct EXPECTED_STRING_LASTZEROTERMINATED Correct EXPECTED_STRING_LASTZEROTERMINATED to account for CURLOPT_HAPROXY_CLIENT_IP which requires EBCDIC to ASCII conversion when passed into curl_easy_setopt(). Closes #11476 Oliver Roberts (20 Jul 2023) - amissl: add missing signal.h include In some environments, signal.h is already included, but not in others which cause compilation to fail, so explictly include it. Closes #11478 - amigaos: fix sys/mbuf.h m_len macro clash The updated Curl_http_req_make and Curl_http_req_make2 functions spawned a parameter called m_len. The AmigaOS networking headers, derived from NetBSD, contain "#define m_len m_hdr.mh_len" which clashes with this. Since we do not actually use mbuf, force the include file to be ignored, removing the clash. Closes #11479 Daniel Stenberg (20 Jul 2023) - socks: print ipv6 address within brackets Fixes #11483 Closes #11484 Christian Schmitz (20 Jul 2023) - libcurl-errors.3: add CURLUE_OK Closes #11488 Oliver Roberts (20 Jul 2023) - cfilters: rename close/connect functions to avoid clashes Rename `close` and `connect` in `struct Curl_cftype` for consistency and to avoid clashes with macros of the same name (the standard AmigaOS networking connect() function is implemented via a macro). Closes #11491 Stefan Eissing (20 Jul 2023) - http2: fix regression on upload EOF handling - a regression introduced by c9ec85121110d7cbbbed2990024222c8f5b8afe5 where optimization of small POST bodies leads to a new code path for such uploads that did not trigger the "done sending" event - add triggering this event for early "upload_done" situations Fixes #11485 Closes #11487 Reported-by: Aleksander Mazur Daniel Stenberg (19 Jul 2023) - configure: check for nghttp2_session_get_stream_local_window_size The http2 code uses it now. Introduced in nghttp2 1.15.0 (Sep 2016) Fixes #11470 Reported-by: Paul Howarth Closes #11473 Stefan Eissing (19 Jul 2023) - quiche: fix segfault and other things - refs #11449 where a segfault is reported when IP Eyeballing did not immediately connect but made several attempts - The transfer initiating the eyeballing was initialized too early, leadding to references to the filter instance that was then replaced in the subsequent eyeball attempts. That led to a use after free in the buffer handling for the transfer - transfers are initiated now more lazy (like in the ngtcp2 filter), when the stream is actually opened - suppress reporting on quiche event errors for "other" transfers than the current one to not fail a transfer due to faults in another one. - revert recent return value handling for quiche_h3_recv_body() to not indicate an error but an EAGAIN situation. We wish quiche would document what functions return. Fixes #11449 Closes #11469 Reported-by: ウさん Daniel Stenberg (19 Jul 2023) - hostip: return IPv6 first for localhost resolves Fixes #11465 Reported-by: Chilledheart on github Closes #11466 Harry Sintonen (19 Jul 2023) - tool: fix tool_seek_cb build when SIZEOF_CURL_OFF_T > SIZEOF_OFF_T - a variable was renamed, and some use of it wasn't. this fixes the build. Closes #11468 Stefan Eissing (19 Jul 2023) - quiche: fix lookup of transfer at multi - refs #11449 where weirdness in quiche multi connection tranfers was observed - fixes lookup of transfer for a quiche event to take the connection into account - formerly, a transfer with the same stream_id, but on another connection could be found Closes #11462 Daniel Stenberg (19 Jul 2023) - RELEASE-NOTES: synced bump to 8.2.1 John Haugabook (19 Jul 2023) - ciphers.d: put URL in first column This makes the URL turn into a link properly when "webified". Fixes https://github.com/curl/curl-www/issues/270 Closes #11464 Version 8.2.0 (19 Jul 2023) Daniel Stenberg (19 Jul 2023) - RELEASE-NOTES: synced 8.2.0 release - THANKS-filter: strip out "GitHub" - THANKS: add contributors from 8.2.0 - RELEASE-PROCEDURE.md: adjust the release dates Stefan Eissing (17 Jul 2023) - quiche: fix defects found in latest coverity report Closes #11455 Daniel Stenberg (17 Jul 2023) - quiche: avoid NULL deref in debug logging Coverity reported "Dereference after null check" If stream is NULL and the function exits, the logging must not deref it. Closes #11454 Stefan Eissing (17 Jul 2023) - http2: treat initial SETTINGS as a WINDOW_UPDATE - refs #11426 where spurious stalls on large POST requests are reported - the issue seems to involve the following * first stream on connection adds up to 64KB of POST data, which is the max default HTTP/2 stream window size transfer is set to HOLD * initial SETTINGS from server arrive, enlarging the stream window. But no WINDOW_UPDATE is received. * curl stalls - the fix un-HOLDs a stream on receiving SETTINGS, not relying on a WINDOW_UPDATE from lazy servers Closes #11450 Daniel Stenberg (17 Jul 2023) - ngtcp2: assigning timeout, but value is overwritten before used Reported by Coverity Closes #11453 - krb5: add typecast to please Coverity Derzsi Dániel (16 Jul 2023) - wolfssl: support setting CA certificates as blob Closes #11445 - wolfssl: detect when TLS 1.2 support is not built into wolfssl Closes #11444 Graham Campbell (15 Jul 2023) - CI: bump nghttp2 from 1.55.0 to 1.55.1 Closes #11442 Daniel Stenberg (15 Jul 2023) - curl: return error when asked to use an unsupported HTTP version When one of the following options are used but the libcurl in use does not support it: --http2 --http2-prior-knowledge --proxy-http2 Closes #11440 Chris Paulson-Ellis (14 Jul 2023) - cf-socket: don't bypass fclosesocket callback if cancelled before connect After upgrading to 8.1.2 from 7.84.0, I found that sockets were being closed without calling the fclosesocket callback if a request was cancelled after the associated socket was created, but before the socket was connected. This lead to an imbalance of fopensocket & fclosesocket callbacks, causing problems with a custom event loop integration using the multi-API. This was caused by cf_socket_close() calling sclose() directly instead of calling socket_close() if the socket was not active. For regular TCP client connections, the socket is activated by cf_socket_active(), which is only called when the socket completes the connect. As far as I can tell, this issue has existed since 7.88.0. That is, since the code in question was introduced by: commit 71b7e0161032927cdfb4e75ea40f65b8898b3956 Author: Stefan Eissing <stefan@eissing.org> Date: Fri Dec 30 09:14:55 2022 +0100 lib: connect/h2/h3 refactor Closes #11439 Daniel Stenberg (13 Jul 2023) - tool_parsecfg: accept line lengths up to 10M Bumped from 100K set in 47dd957daff9 Reported-by: Antoine du Hamel Fixes #11431 Closes #11435 Stefan Eissing (13 Jul 2023) - CI: brew fix for openssl in default path If brew install/update links openssl into /usr/local, it will be found before anything we add with `-isystem path` to CPP/LDLFAGS. Get rid of that by unlinking the keg. Fixes #11413 Closes #11436 Daniel Stenberg (13 Jul 2023) - RELEASE-NOTES: synced Ondřej Koláček (13 Jul 2023) - sectransp: fix EOF handling Regression since the large refactor from 2022 Closes #11427 Daniel Stenberg (13 Jul 2023) - checksrc: quote the file name to work with "funny" letters Closes #11437 Karthikdasari0423 (13 Jul 2023) - HTTP3.md: ngtcp2 updated to v0.17.0 and nghttp3 to v0.13.0 Follow-up to e0093b4b732f6 Closes #11433 Daniel Stenberg (13 Jul 2023) - CURLOPT_MIMEPOST.3: clarify what setting to NULL means Follow-up to e08382a208d4e480 Closes #11430 Tatsuhiro Tsujikawa (12 Jul 2023) - ngtcp2: build with 0.17.0 and nghttp3 0.13.0 - ngtcp2_crypto_openssl was renamed to ngtcp2_crypto_quictls. Closes #11428 - CI: Bump ngtcp2, nghttp3, and nghttp2 Closes #11428 James Fuller (11 Jul 2023) - example/maxconnects: set maxconnect example Closes #11343 Pontakorn Prasertsuk (11 Jul 2023) - http2: send HEADER & DATA together if possible Closes #11420 Daniel Stenberg (11 Jul 2023) - CI: use wolfSSL 5.6.3 in builds No using master anymore Closes #11424 SaltyMilk (11 Jul 2023) - fopen: optimize Closes #11419 Daniel Stenberg (11 Jul 2023) - cmake: make use of snprintf Follow-up to 935b1bd4544a23a91d68 Closes #11423 Stefan Eissing (11 Jul 2023) - macOS: fix taget detection - TARGET_OS_OSX is not always defined on macOS - this leads to missing symbol Curl_macos_init() - TargetConditionals.h seems to define these only when dynamic targets are enabled (somewhere?) - this PR fixes that on my macOS 13.4.1 - I have no clue why CI builds worked without it Follow-up to c7308592fb8ba213fc2c1 Closes #11417 Stan Hu (9 Jul 2023) - hostip.c: Move macOS-specific calls into global init call https://github.com/curl/curl/pull/7121 introduced a macOS system call to `SCDynamicStoreCopyProxies`, which is invoked every time an IP address needs to be resolved. However, this system call is not thread-safe, and macOS will kill the process if the system call is run first in a fork. To make it possible for the parent process to call this once and prevent the crash, only invoke this system call in the global initialization routine. In addition, this change is beneficial because it: 1. Avoids extra macOS system calls for every IP lookup. 2. Consolidates macOS-specific initialization in a separate file. Fixes #11252 Closes #11254 Daniel Stenberg (9 Jul 2023) - docs: use a space after RFC when spelling out RFC numbers Closes #11382 Margu (9 Jul 2023) - imap-append.c: update to make it more likely to work Fixes #10300 Closes #11397 Emanuele Torre (9 Jul 2023) - tool_writeout_json: fix encoding of control characters Control characters without a special escape sequence e.g. %00 or %06 were being encoded as "u0006" instead of "\u0006". Ref: https://github.com/curl/trurl/pull/214#discussion_r1257487858 Closes #11414 Stefan Eissing (9 Jul 2023) - http3/ngtcp2: upload EAGAIN handling - refs #11389 where IDLE timeouts on upload are reported - reword ngtcp2 expiry handling to apply to both send+recv calls into the filter - EAGAIN uploads similar to the recent changes in HTTP/2, e.g. report success only when send data was ACKed. - HOLD sending of EAGAINed uploads to avoid cpu busy loops - rename internal function for consistency with HTTP/2 implementation Fixes #11389 Closes #11390 Brian Nixon (9 Jul 2023) - tool_easysrc.h: correct `easysrc_perform` for `CURL_DISABLE_LIBCURL_OPTION` Closes #11398 Daniel Stenberg (9 Jul 2023) - RELEASE-NOTES: synced - transfer: clear credentials when redirecting to absolute URL Make sure the user and password for the second request is taken from the redirected-to URL. Add test case 899 to verify. Reported-by: James Lucas Fixes #11410 Closes #11412 Stefan Eissing (8 Jul 2023) - hyper: fix EOF handling on input We ran out of disc space due to an infinite loop with debug logging Fixes #11377 Closes #11385 Reported-by: Dan Fandrich - http2: raise header limitations above and beyond - not quite to infinity - rewrote the implementation of our internal HTTP/1.x request parsing to work with very large lines using dynbufs. - new default limit is `DYN_HTTP_REQUEST`, aka 1MB, which is also the limit of curl's general HTTP request processing. Fixes #11405 Closes #11407 Juan Cruz Viotti (8 Jul 2023) - curl_easy_nextheader.3: add missing open parenthesis examples Closes #11409 Signed-off-by: Juan Cruz Viotti <jv@jviotti.com> Dan Fandrich (7 Jul 2023) - CI: enable verbose test output on pytest This shows individual pass/fail status on tests and makes this output consistent with other jobs' pytest invocations. Stefan Eissing (28 Jun 2023) - http2: fix crash in handling stream weights - Delay the priority handling until the stream has been opened. - Add test2404 to reproduce and verify. Weights may change "on the run", which is why there are checks in general egress handling. These must not trigger when the stream has not been opened yet. Reported-by: jbgoog@users.noreply.github.com Fixes https://github.com/curl/curl/issues/11379 Closes https://github.com/curl/curl/pull/11384 - tests/http: Add mod_h2 directive `H2ProxyRequests` master of mod_h2 now requires H2ProxyRequests directives for forward proxying with HTTP/2 to work. Ref: https://github.com/icing/mod_h2/commit/3897a7086 Closes https://github.com/curl/curl/pull/11392 Dan Fandrich (28 Jun 2023) - CI: make Appveyor job names unique Two otherwise identical mingw-w64 jobs now have their differing compiler versions mentioned in their names. Sheshadri.V (25 Jun 2023) - curl.h: include <sys/select.h> for vxworks Closes #11356 Dan Fandrich (24 Jun 2023) - CI: enable parallel make in more builds Most CI services provide at least two cores, so enable parallel make jobs to take advantage of that for builds. Some dependencies aren't safe to build in parallel so leave those as-is. Also, rename a few workflows to eliminate duplicate names and provide a better idea what they're about. - CI: don't install impacket if tests are not run It just wastes time and bandwidth and isn't even used. divinity76 (24 Jun 2023) - configure: the --without forms of the options are also gone --without-darwin-ssl and --without-metalink Closes #11378 Daniel Stenberg (23 Jun 2023) - configure: add check for ldap_init_fd ... as otherwise the configure script will say it is OpenLDAP in the summary, but not set the USE_OPENLDAP define, therefor not using the intended OpenLDAP code paths. Regression since 4d7385446 (7.85.0) Fixes #11372 Closes #11374 Reported-by: vlkl-sap on github Michał Petryka (23 Jun 2023) - cmake: stop CMake from quietly ignoring missing Brotli The CMake project was set to `QUIET` for Brotli instead of `REQUIRED`. This makes builds unexpectedly ignore missing Brotli even when `CURL_BROTLI` is enabled. Closes #11376 Emanuele Torre (22 Jun 2023) - docs: add more .IP after .RE to fix indentation of generate paragraphs follow-up from 099f41e097c030077b8ec078f2c2d4038d31353b I just thought of checking all the other files with .RE, and I found 6 other files that were missing .IP at the end. Closes #11375 Stefan Eissing (22 Jun 2023) - http2: h2 and h2-PROXY connection alive check fixes - fix HTTP/2 check to not declare a connection dead when the read attempt results in EAGAIN - add H2-PROXY alive check as for HTTP/2 that was missing and is needed - add attach/detach around Curl_conn_is_alive() and remove these in filter methods - add checks for number of connections used in some test_10 proxy tunneling tests Closes #11368 - http2: error stream resets with code CURLE_HTTP2_STREAM - refs #11357, where it was reported that HTTP/1.1 downgrades no longer works - fixed with suggested change - added test_05_03 and a new handler in the curltest module to reproduce that downgrades work Fixes #11357 Closes #11362 Reported-by: Jay Satiro Daniel Stenberg (22 Jun 2023) - connect-timeout.d: mention that the DNS lookup is included Closes #11370 Emanuele Torre (22 Jun 2023) - quote.d: fix indentation of generated paragraphs quote.d was missing a .IP at the end which caused the paragraphs generated for See-also, Multi, and Example to not be indented correctly. I also remove a redundant "This option can be used multiple times.", and replaced .IP "item" with .TP .B "item" to make more clear which lines are part of the list of commands and which aren't. Closes #11371 Paul Wise (22 Jun 2023) - checksrc: modernise perl file open Use regular variables and separate file open modes from filenames. Suggested by perlcritic Copied from https://github.com/curl/trurl/commit/f2784a9240f47ee28a845 Closes #11358 Dan Fandrich (21 Jun 2023) - runtests: work around a perl without SIGUSR1 At least msys2 perl v5.32.1 doesn't seem to define this signal. Since this signal is only used for debugging, just ignore if setting it fails. Reported-by: Marcel Raad Fixes #11350 Closes #11366 - runtests: include missing valgrind package use valgrind was missing which caused torture tests with valgrind enabled to fail. Reported-by: Daniel Stenberg Fixes #11364 Closes #11365 - runtests: use more consistent failure lines After a test failure log a consistent log message to make it easier to parse the log file. Also, log a consistent message with "ignored" for failures that cause the test to be not considered at all. These should perhaps be counted in the skipped category, but this commit does not change that behaviour. - runtests: consistently write the test check summary block The memory check character was erroneously omitted if the memory checking file was not available for some reason, making the block of characters an inconsistent length. - test2600: fix the description It looks like it was cut-and-pasted. Closes #11354 Daniel Stenberg (21 Jun 2023) - TODO: "Support HTTP/2 for HTTP(S) proxies" *done* humbleacolyte (21 Jun 2023) - cf-socket: move ctx declaration under HAVE_GETPEERNAME Closes #11352 Daniel Stenberg (20 Jun 2023) - RELEASE-NOTES: synced - example/connect-to: show CURLOPT_CONNECT_TO Closes #11340 Stefan Eissing (20 Jun 2023) - hyper: unslow - refs #11203 where hyper was reported as being slow - fixes hyper_executor_poll to loop until it is out of tasks as advised by @seanmonstar in https://github.com/hyperium/hyper/issue s/3237 - added a fix in hyper io handling for detecting EAGAIN - added some debug logs to see IO results - pytest http/1.1 test cases pass - pytest h2 test cases fail on connection reuse. HTTP/2 connection reuse does not seem to work. Hyper submits a request on a reused connection, curl's IO works and thereafter hyper declares `Hyper: [1] operation was canceled: connection cl osed` on stderr without any error being logged before. Fixes #11203 Reported-by: Gisle Vanem Advised-by: Sean McArthur Closes #11344 - HTTP/2: upload handling fixes - fixes #11242 where 100% CPU on uploads was reported - fixes possible stalls on last part of a request body when that information could not be fully send on the connection due to an EAGAIN - applies the same EGAIN handling to HTTP/2 proxying Reported-by: Sergey Alirzaev Fixed #11242 Closes #11342 Daniel Stenberg (20 Jun 2023) - example/opensslthreadlock: remove This shows how to setup OpenSSL mutex callbacks, but this is not necessary since OpenSSL 1.1.0 - meaning that no currently supported OpenSSL version requires this anymore Closes #11341 Dan Fandrich (19 Jun 2023) - libtest: display the times after a test timeout error This is to help with test failure debugging. Ref: #11328 Closes #11329 - test2600: bump a test timeout Case 1 failed at least once on GHA by going 30 msec too long. Ref: #11328 - runtests: better detect and handle pipe errors in the controller Errors reading and writing to the pipes are now better detected and propagated up to the main test loop so it can be cleanly shut down. Such errors are usually due to a runner dying so it doesn't make much sense to try to continue the test run. - runtests: cleanly abort the runner if the controller dies If the controller dies unexpectedly, have the runner stop its servers and exit cleanly. Otherwise, the orphaned servers will stay running in the background. - runtests: improve error logging Give more information about test harness error conditions to help figure out what might be wrong. Print some internal test state when SIGUSR1 is sent to runtests.pl. Ref: #11328 - runtests: better handle ^C during slow tests Since the SIGINT handler now just sets a flag that must be checked in the main controller loop, make sure that runs periodically. Rather than blocking on a response from a test runner near the end of the test run, add a short timeout to allow it. - runtests: rename server command file The name ftpserver.cmd was historical and has been used for more than ftp for many years now. Rename it to plain server.cmd to reduce confusion. - tests: improve reliability of TFTP tests Stop checking the timeout used by the client under test (for most tests). The timeout will change if the TFTP test server is slow (such as happens on an overprovisioned CI server) because the client will retry and reduce its timeout, and the actual value is not important for most tests. test285 is changed a different way, by increasing the connect timeout. This improves test coverage by allowing the changed timeout value to be checked, but improves reliability with a carefully-chosen timeout that not only allows twice the time to respond as before, but also allows several retries before the client will change its timeout value. Ref: #11328 Daniel Stenberg (19 Jun 2023) - cf-socket: skip getpeername()/getsockname for TFTP Since the socket is not connected then the call fails. When the call fails, failf() is called to write an error message that is then surviving and is returned when the *real* error occurs later. The earlier, incorrect, error therefore hides the actual error message. This could be seen in stderr for test 1007 Test 1007 has now been extended to verify the stderr message. Closes #11332 - example/crawler: make it use a few more options For show, but reasonable - libcurl-ws.3: mention raw mode Closes #11339 - example/default-scheme: set the default scheme for schemeless URLs Closes #11338 - example/hsts-preload: show one way to HSTS preload Closes #11337 - examples/http-options: show how to send "OPTIONS *" With CURLOPT_REQUEST_TARGET. Also add use of CURLOPT_QUICK_EXIT to show. Closes #11333 - examples: make use of CURLOPT_(REDIR_|)PROTOCOLS_STR To show how to use them Closes #11334 - examples/smtp-mime: use CURLOPT_MAIL_RCPT_ALLOWFAILS For show Closes #11335 - http: rectify the outgoing Cookie: header field size check Previously it would count the size of the entire outgoing request and not just the size of only the Cookie: header field - which was the intention. This could make the check be off by several hundred bytes in some cases. Closes #11331 Jay Satiro (17 Jun 2023) - lib: fix some format specifiers - Use CURL_FORMAT_CURL_OFF_T where %zd was erroneously used for some curl_off_t variables. - Use %zu where %zd was erroneously used for some size_t variables. Prior to this change some of the Windows CI tests were failing because in Windows 32-bit targets have a 32-bit size_t and a 64-bit curl_off_t. When %zd was used for some curl_off_t variables then only the lower 32-bits was read and the upper 32-bits would be read for part or all of the next specifier. Fixes https://github.com/curl/curl/issues/11327 Closes https://github.com/curl/curl/pull/11321 Marcel Raad (16 Jun 2023) - test427: add `cookies` feature and keyword This test doesn't work with `--disable-cookies`. Closes https://github.com/curl/curl/pull/11320 Chris Talbot (15 Jun 2023) - imap: Provide method to disable SASL if it is advertised - Implement AUTH=+LOGIN for CURLOPT_LOGIN_OPTIONS to prefer plaintext LOGIN over SASL auth. Prior to this change there was no method to be able to fall back to LOGIN if an IMAP server advertises SASL capabilities. However, this may be desirable for e.g. a misconfigured server. Per: https://www.ietf.org/rfc/rfc5092.html#section-3.2 ";AUTH=<enc-auth-type>" looks to be the correct way to specify what authenication method to use, regardless of SASL or not. Closes https://github.com/curl/curl/pull/10041 Daniel Stenberg (15 Jun 2023) - RELEASE-NOTES: synced - examples/multi-debugcallback.c: avoid the bool typedef Apparently this cannot be done in c23 Reported-by: Cristian Rodríguez Fixes #11299 Closes #11319 - docs/libcurl/libcurl.3: cleanups and improvements Closes #11317 - libcurl-ws.3: fix typo - curl_ws_*.3: enhance - all: SEE ALSO the libcurl-ws man page - send: add example and return value information - meta: mention that the returned data is read-only Closes #11318 - docs/libcurl/libcurl-ws.3: see also CURLOPT_WS_OPTIONS - docs/libcurl/libcurl-ws.3: minor polish - libcurl-ws.3. WebSocket API overview Closes #11314 - libcurl-url.3: also mention CURLUPART_ZONEID ... and sort the two part-using lists alphabetically Marcel Raad (14 Jun 2023) - fopen: fix conversion warning on 32-bit Android When building for 32-bit ARM or x86 Android, `st_mode` is defined as `unsigned int` instead of `mode_t`, resulting in a -Wimplicit-int-conversion clang warning because `mode_t` is `unsigned short`. Add a cast to silence the warning. Ref: https://android.googlesource.com/platform/bionic/+/refs/tags/ndk-r25c/li bc/include/sys/stat.h#86 Closes https://github.com/curl/curl/pull/11313 - http2: fix variable type `max_recv_speed` is `curl_off_t`, so using `size_t` might result in -Wconversion GCC warnings for 32-bit `size_t`. Visible in the NetBSD ARM autobuilds. Closes https://github.com/curl/curl/pull/11312 Daniel Stenberg (13 Jun 2023) - vtls: fix potentially uninitialized local variable warnings Follow-up from a4a5e438ae533c Closes #11310 - timeval: use CLOCK_MONOTONIC_RAW if available Reported-by: Harry Sintonen Ref: #11288 Closes #11291 Stefan Eissing (12 Jun 2023) - tool: add curl command line option `--trace-ids` - added and documented --trace-ids to prepend (after the timestamp) the transfer and connection identifiers to each verbose log line - format is [n-m] with `n` being the transfer id and `m` being the connection id. In case there is not valid connection id, print 'x'. - Log calls with a handle that has no transfer id yet, are written without any ids. Closes #11185 - lib: add CURLINFO_CONN_ID and CURLINFO_XFER_ID - add an `id` long to Curl_easy, -1 on init - once added to a multi (or its own multi), it gets a non-negative number assigned by the connection cache - `id` is unique among all transfers using the same cache until reaching LONG_MAX where it will wrap around. So, not unique eternally. - CURLINFO_CONN_ID returns the connection id attached to data or, if none present, data->state.lastconnect_id - variables and type declared in tool for write out Closes #11185 Daniel Stenberg (12 Jun 2023) - CURLOPT_INFILESIZE.3: mention -1 triggers chunked Ref: #11300 Closes #11304 Philip Heiduck (12 Jun 2023) - CI: openssl-3.0.9+quic Closes #11296 Karthikdasari0423 (12 Jun 2023) - HTTP3.md: update openssl version Closes #11297 Daniel Stenberg (12 Jun 2023) - vtls: avoid memory leak if sha256 call fails ... in the pinned public key handling function. Reported-by: lizhuang0630 on github Fixes #11306 Closes #11307 - examples/ipv6: disable on win32 I can't make if_nametoindex() work there Follow-up to c23dc42f3997acf23 Closes #11305 - tool_operate: allow cookie lines up to 8200 bytes Since this option might set multiple cookies in the same line, it does not make total sense to cap this at 4096 bytes, which is the limit for a single cookie name or value. Closes #11303 - test427: verify sending more cookies than fit in a 8190 bytes line curl will then only populate the header with cookies that fit, dropping ones that otherwise would have been sent Ref: https://curl.se/mail/lib-2023-06/0020.html Closes #11303 - testutil: allow multiple %-operators on the same line Closes #11303 Oleg Jukovec (12 Jun 2023) - docs: update CURLOPT_UPLOAD.3 The behavior of CURLOPT_UPLOAD differs from what is described in the documentation. The option automatically adds the 'Transfer-Encoding: chunked' header if the upload size is unknown. Closes #11300 Daniel Stenberg (12 Jun 2023) - RELEASE-NOTES: synced - CURLOPT_AWS_SIGV4.3: remove unused variable from example Closes #11302 - examples/https.c: use CURLOPT_CA_CACHE_TIMEOUT for demonstration purposes Closes #11290 - example/ipv6: feature CURLOPT_ADDRESS_SCOPE in use Closes #11282 Karthikdasari0423 (10 Jun 2023) - docs: Update HTTP3.md for newer ngtcp2 and nghttp3 Follow-up to fb9b9b58 Ref: #11184 Closes #11295 Dan Fandrich (10 Jun 2023) - docs: update the supported ngtcp2 and nghttp3 versions Follow-up to cae9d10b Ref: #11184 Closes #11294 - tests: fix error messages & handling around sockets The wrong error code was checked on Windows on UNIX socket failures, which could have caused all UNIX sockets to be reported as having errored and the tests therefore skipped. Also, a useless error message was displayed on socket errors in many test servers on Windows because strerror() doesn't work on WinSock error codes; perror() is overridden there to work on all errors and is used instead. Ref #11258 Closes #11265 Daniel Stenberg (9 Jun 2023) - CURLOPT_SSH_PRIVATE_KEYFILE.3: expand on the file search Reported-by: atjg on github Ref: #11287 Closes #11289 Stefan Eissing (9 Jun 2023) - ngtcp2: use ever increasing timestamp in io - ngtcp2 v0.16.0 asserts that timestamps passed to its function will only ever increase. - Use a context shared between ingress/egress operations that uses a shared timestamp, regularly updated during calls. Closes #11288 Daniel Stenberg (9 Jun 2023) - GHA: use nghttp2 1.54.0 for the ngtcp2 jobs Philip Heiduck (9 Jun 2023) - GHA: ngtcp2: use 0.16.0 and nghttp3 0.12.0 Daniel Stenberg (9 Jun 2023) - ngtcp2: build with 0.16.0 and nghttp3 0.12.0 - moved to qlog_write - crypto => encryption - CRYPTO => ENCRYPTION - removed "_is_" - ngtcp2_conn_shutdown_stream_read and ngtcp2_conn_shutdown_stream_write got flag arguments - the nghttp3_callbacks struct got a recv_settings callback Closes #11184 - example/http2-download: set CURLOPT_BUFFERSIZE Primarily because no other example sets it, and remove the disabling of the certificate check because we should not recommend that. Closes #11284 - example/crawler: also set CURLOPT_AUTOREFERER Could make sense, and it was not used in any example before. Closes #11283 Wyatt OʼDay (9 Jun 2023) - tls13-ciphers.d: include Schannel Closes #11271 Daniel Stenberg (9 Jun 2023) - curl_pushheader_byname/bynum.3: document in their own man pages These two functions were added in 7.44.0 when CURLMOPT_PUSHFUNCTION was introduced but always lived a life in the shadows, embedded in the CURLMOPT_PUSHFUNCTION man page. Until now. It makes better sense and gives more visibility to document them in their own stand-alone man pages. Closes #11286 - curl_mprintf.3: minor fix of the example - curl_url_set: enforce the max string length check for all parts Update the docs and test 1559 accordingly Closes #11273 - examples/ftpuploadresume.c: add use of CURLOPT_ACCEPTTIMEOUT_MS For show Closes #11277 - examples/unixsocket.c: example using CURLOPT_UNIX_SOCKET_PATH and alternatively CURLOPT_ABSTRACT_UNIX_SOCKET Closes #11276 Anssi Kolehmainen (8 Jun 2023) - docs: fix missing parameter names in examples Closes #11278 Daniel Stenberg (8 Jun 2023) - urlapi: have *set(PATH) prepend a slash if one is missing Previously the code would just do that for the path when extracting the full URL, which made a subsequent curl_url_get() of the path to (unexpectedly) still return it without the leading path. Amend lib1560 to verify this. Clarify the curl_url_set() docs about it. Bug: https://curl.se/mail/lib-2023-06/0015.html Closes #11272 Reported-by: Pedro Henrique Dan Fandrich (7 Jun 2023) - runtests; give each server a unique log lock file Logs are written by several servers and all of them must be finished writing before the test results can be determined. This means each server must have its own lock file rather than sharing a single one, which is how it was done up to now. Previously, the first server to complete a test would clear the lock before the other server was done, which caused flaky tests. Lock files are now all found in their own directory, so counting locks equals counting the files in that directory. The result is that the proxy logs are now reliably written which actually changes the expected output for two tests. Fixes #11231 Closes #11259 - runtests: make test file directories in log/N Test files in subdirectories were not created after parallel test log directories were moved down a level due to a now-bad comparison. Follow-up to 92d7dd39 Ref #11264 Closes #11267 Daniel Stenberg (7 Jun 2023) - ws: make the curl_ws_meta() return pointer a const The returned info is read-only for the user. Closes #11261 - RELEASE-NOTES: synced - runtests: move parallel log dirs from logN to log/N Having several hundreds of them in there gets annoying. Closes #11264 Dan Fandrich (7 Jun 2023) - test447: move the test file into %LOGDIR Viktor Szakats (7 Jun 2023) - cmake: add support for "unity" builds Aka "jumbo" or "amalgamation" builds. It means to compile all sources per target as a single C source. This is experimental. You can enable it by passing `-DCMAKE_UNITY_BUILD=ON` to cmake. It requires CMake 3.16 or newer. It makes builds (much) faster, allows for better optimizations and tends to promote less ambiguous code. Also add a new AppVeyor CI job and convert an existing one to use "unity" mode (one MSVC, one MinGW), and enable it for one macOS CI job. Fix related issues: - add missing include guard to `easy_lock.h`. - rename static variables and functions (and a macro) with names reused across sources, or shadowed by local variables. - add an `#undef` after use. - add a missing `#undef` before use. - move internal definitions from `ftp.h` to `ftp.c`. - `curl_memory.h` fixes to make it work when included repeatedly. - stop building/linking curlx bits twice for a static-mode curl tool. These caused doubly defined symbols in unity builds. - silence missing extern declarations compiler warning for ` _CRT_glob`. - fix extern declarations for `tool_freq` and `tool_isVistaOrGreater`. - fix colliding static symbols in debug mode: `debugtime()` and `statename`. - rename `ssl_backend_data` structure to unique names for each TLS-backend, along with the `ssl_connect_data` struct member referencing them. This required adding casts for each access. - add workaround for missing `[P]UNICODE_STRING` types in certain Windows builds when compiling `lib/ldap.c`. To support "unity" builds, we had to enable `SCHANNEL_USE_BLACKLISTS` for Schannel (a Windows `schannel.h` option) _globally_. This caused an indirect inclusion of Windows `schannel.h` from `ldap.c` via `winldap.h` to have it enabled as well. This requires `[P]UNICODE_STRING` types, which is apperantly not defined automatically (as seen with both MSVS and mingw-w64). This patch includes `<subauth.h>` to fix it. Ref: https://github.com/curl/curl/runs/13987772013 Ref: https://dev.azure.com/daniel0244/curl/_build/results?buildId=15827&vie w=logs&jobId=2c9f582d-e278-56b6-4354-f38a4d851906&j=2c9f582d-e278-56b6-4354-f 38a4d851906&t=90509b00-34fa-5a81-35d7-5ed9569d331c - tweak unity builds to compile `lib/memdebug.c` separately in memory trace builds to avoid PP confusion. - force-disable unity for test programs. - do not compile and link libcurl sources to libtests _twice_ when libcurl is built in static mode. KNOWN ISSUES: - running tests with unity builds may fail in cases. - some build configurations/env may not compile in unity mode. E.g.: https://ci.appveyor.com/project/curlorg/curl/builds/47230972/job/51wfesgnfu auwl8q#L250 Ref: https://github.com/libssh2/libssh2/issues/1034 Ref: https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html Ref: https://en.wikipedia.org/wiki/Unity_build Closes #11095 Daniel Stenberg (7 Jun 2023) - examples/websocket.c: websocket example using CONNECT_ONLY Closes #11262 - websocket-cb: example doing WebSocket download using callback Very basic Closes #11260 - test/.gitignore: ignore log* Dan Fandrich (5 Jun 2023) - runtests: document the -j parallel testing option Reported-by: Daniel Stenberg Ref: #10818 Closes #11255 - runtests: create multiple test runners when requested Parallel testing is enabled by using a nonzero value for the -j option to runtests.pl. Performant values seem to be about 7*num CPU cores, or 1.3*num CPU cores if Valgrind is in use. Flaky tests due to improper log locking (bug #11231) are exacerbated while parallel testing, so it is not enabled by default yet. Fixes #10818 Closes #11246 - runtests: handle repeating tests in multiprocess mode Such as what happens with the --repeat option. Some functions are changed to pass the runner ID instead of relying on the non-unique test number. Ref: #10818 - runtests: buffer logmsg while running singletest() This allows all messages relating to a single test case to be displayed together at the end of the test. Ref: #10818 - runtests: call initserverconfig() in the runner This must be done so variables pick up the runner's unique $LOGDIR. Ref: #10818 - runtests: use a per-runner random seed Each runner needs a unique random seed to reduce the chance of port number collisions. The new scheme uses a consistent per-runner source of randomness which results in deterministic behaviour, as it did before. Ref: #10818 - runtests: complete main test loop refactor for multiple runners The main test loop is now able to handle multiple runners, or no additional runner processes at all. At most one process is still created, however. Ref: #10818 - runtests: prepare main test loop for multiple runners Some variables are expanded to arrays and hashes so that multiple runners can be used for running tests. Ref: #10818 Stefan Eissing (5 Jun 2023) - bufq: make write/pass methods more robust - related to #11242 where curl enters busy loop when sending http2 data to the server Closes #11247 Boris Verkhovskiy (5 Jun 2023) - tool_getparam: fix comment Closes #11253 Raito Bezarius (5 Jun 2023) - haproxy: add --haproxy-clientip flag to spoof client IPs CURLOPT_HAPROXY_CLIENT_IP in the library Closes #10779 Daniel Stenberg (5 Jun 2023) - curl: add --ca-native and --proxy-ca-native These are two boolean options to ask curl to use the native OS's CA store when verifying TLS servers. For peers and for proxies respectively. They currently only have an effect for curl on Windows when built to use OpenSSL for TLS. Closes #11049 Viktor Szakats (5 Jun 2023) - build: drop unused/redundant `HAVE_WINLDAP_H` Sources did not use it. Autotools used it when checking for the `winldap` library, which is redundant. With CMake, detection was broken: ``` Run Build Command(s):/usr/local/Cellar/cmake/3.26.3/bin/cmake -E env VERBOSE= 1 /usr/bin/make -f Makefile cmTC_2d8fe/fast && /Library/Developer/CommandLine Tools/usr/bin/make -f CMakeFiles/cmTC_2d8fe.dir/build.make CMakeFiles/cmTC_2 d8fe.dir/build Building C object CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj /usr/local/opt/llvm/bin/clang --target=x86_64-w64-mingw32 --sysroot=/usr/loca l/opt/mingw-w64/toolchain-x86_64 -D_WINSOCKAPI_="" -I/my/quictls/x64-ucrt/usr /include -I/my/zlib/x64-ucrt/usr/include -I/my/brotli/x64-ucrt/usr/include -W no-unused-command-line-argument -D_UCRT -DCURL_HIDDEN_SYMBOLS -DHAVE_SSL_SE T0_WBIO -DHAS_ALPN -DNGHTTP2_STATICLIB -DNGHTTP3_STATICLIB -DNGTCP2_STATICLIB -DUSE_MANUAL=1 -fuse-ld=lld -Wl,-s -static-libgcc -lucrt -Wextra -Wall -p edantic -Wbad-function-cast -Wconversion -Winline -Wmissing-declarations -Wmi ssing-prototypes -Wnested-externs -Wno-long-long -Wno-multichar -Wpointer-ari th -Wshadow -Wsign-compare -Wundef -Wunused -Wwrite-strings -Wcast-align -Wde claration-after-statement -Wempty-body -Wendif-labels -Wfloat-equal -Wignored -qualifiers -Wno-format-nonliteral -Wno-sign-conversion -Wno-system-headers - Wstrict-prototypes -Wtype-limits -Wvla -Wshift-sign-overflow -Wshorten-64-to- 32 -Wdouble-promotion -Wenum-conversion -Wunused-const-variable -Wcomma -Wmis sing-variable-declarations -Wassign-enum -Wextra-semi-stmt -MD -MT CMakeFile s/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -MF CMakeFiles/cmTC_2d8fe.dir/HAVE_WINL DAP_H.c.obj.d -o CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj -c /my/curl/b ld-cmake-llvm-x64-shared/CMakeFiles/CMakeScratch/TryCompile-3JP6dR/HAVE_WINLD AP_H.c In file included from /my/curl/bld-cmake-llvm-x64-shared/CMakeFiles/CMakeScra tch/TryCompile-3JP6dR/HAVE_WINLDAP_H.c:2: In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi ngw32/include/winldap.h:17: In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi ngw32/include/schnlsp.h:9: In file included from /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mi ngw32/include/schannel.h:10: /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt .h:5041:254: error: unknown type name 'PSYSTEMTIME' WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_ NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT ENSIONS pExtensions); ^ /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32/include/wincrypt .h:5041:278: error: unknown type name 'PSYSTEMTIME' WINIMPM PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate (HCRYPTPROV_OR_ NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey, PCERT_NAME_BLOB pSubjectIssuerBlob, DWORD dwFlags, PCRYPT_KEY_PROV_INFO pKeyProvInfo, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, PSYSTEMTIME pStartTime, PSYSTEMTIME pEndTime, PCERT_EXT ENSIONS pExtensions); ^ 2 errors generated. make[1]: *** [CMakeFiles/cmTC_2d8fe.dir/HAVE_WINLDAP_H.c.obj] Error 1 make: *** [cmTC_2d8fe/fast] Error 2 exitCode: 2 ``` Cherry-picked from #11095 88e4a21ff70ccef391cf99c8165281ff81374503 Reviewed-by: Daniel Stenberg Closes #11245 Daniel Stenberg (5 Jun 2023) - urlapi: scheme starts with alpha Add multiple tests to lib1560 to verify Fixes #11249 Reported-by: ad0p on github Closes #11250 - RELEASE-NOTES: synced - CURLOPT_MAIL_RCPT_ALLOWFAILS: replace CURLOPT_MAIL_RCPT_ALLLOWFAILS Deprecate the name using three Ls and prefer the name with two. Replaces #10047 Closes #11218 - tests/servers: generate temp names in /tmp for unix domain sockets ... instead of putting them in the regular pid directories because systems generally have strict length requirements for the path name to be shorter than 107 bytes and we easily hit that boundary otherwise. The new concept generates two random names: one for the socks daemon and one for http. Reported-by: Andy Fiddaman Fixes #11152 Closes #11166 Stefan Eissing (2 Jun 2023) - http2: better support for --limit-rate - leave transfer loop when --limit-rate is in effect and has been received - adjust stream window size to --limit-rate plus some slack to make the server observe the pacing we want - add test case to confirm behaviour Closes #11115 - curl_log: evaluate log statement only when transfer is verbose Closes #11238 Daniel Stenberg (2 Jun 2023) - libssh2: provide error message when setting host key type fails Ref: https://curl.se/mail/archive-2023-06/0001.html Closes #11240 Igor Todorovski (2 Jun 2023) - system.h: remove __IBMC__/__IBMCPP__ guards and apply to all z/OS compiles Closes #11241 Daniel Stenberg (2 Jun 2023) - docs/SECURITY-PROCESS.md: link to example of previous critical flaw Mark Seuffert (2 Jun 2023) - README.md: updated link to opencollective Closes #11232 Daniel Stenberg (1 Jun 2023) - libssh2: use custom memory functions Because of how libssh2_userauth_keyboard_interactive_ex() works: the libcurl callback allocates memory that is later free()d by libssh2, we must set the custom memory functions. Reverts 8b5f100db388ee60118c08aa28 Ref: https://github.com/libssh2/libssh2/issues/1078 Closes #11235 - test447: test PUTting a file that grows ... and have curl trim the end when it reaches the expected total amount of bytes instead of over-sending. Reported-by: JustAnotherArchivist on github Closes #11223 - curl: count uploaded data to stop at the originally given size Closes #11223 Fixes #11222 Reported-by: JustAnotherArchivist on github - tool: remove exclamation marks from error/warning messages - tool: use errorf() for error output Convert a number of fprintf() calls. - tool: remove newlines from all helpf/notef/warnf/errorf calls Make voutf() always add one. Closes #11226 - tests/servers.pm: pick unused port number with a server socket This change replaces the previous method of picking a port number at random to try to start servers on, then retrying up to ten times with new random numbers each time, with a function that creates a server socket on port zero, thereby getting a suitable random port set by the kernel. That server socket is then closed and that port number is used to setup the actual test server on. There is a risk that *another* server can be started on the machine in the time gap, but the server verification feature will detect that. Closes #11220 - RELEASE-NOTES: synced bump to 8.2.0 Alejandro R. Sedeño (31 May 2023) - configure: fix run-compiler for old /bin/sh If you try to assign and export on the same line on some older /bin/sh implementations, it complains: ``` $ export "NAME=value" NAME=value: is not an identifier ``` This commit rewrites run-compiler's assignments and exports to work with old /bin/sh, splitting assignment and export into two separate statements, and only quote the value. So now we have: ``` NAME="value" export NAME ``` While we're here, make the same change to the two supporting assign+export lines preceeding the script to be consistent with how exports work throughout the rest of configure.ac. Closes #11228 Philip Heiduck (31 May 2023) - circleci: install impacket & wolfssl 5.6.0 Closes #11221 Daniel Stenberg (31 May 2023) - tool_urlglob: use curl_off_t instead of longs To handle more globs better (especially on Windows) Closes #11224 Dan Fandrich (30 May 2023) - scripts: Fix GHA matrix job detection in cijobs.pl The parsing is pretty brittle and it broke detecting some jobs at some point. Also, detect if Windows is used in GHA. - runtests: abort test run after failure without -a This was broken in a recent refactor and test runs would not stop. Follow-up to d4a1b5b6 Reported-by: Daniel Stenberg Fixes #11225 Closes #11227 Version 8.1.2 (30 May 2023) Daniel Stenberg (30 May 2023) - RELEASE-NOTES: synced 8.1.2 release - THANKS: contributors from 8.1.2 - lib1560: verify more scheme guessing - on 2nd level domains - on names without dots As mentioned in #11161, "imap.com" will be guessed IMAP Closes #11219 - page-header: minor wording polish in the URL segment Closes #11217 - page-header: mention curl version and how to figure out current release Closes #11216 - RELEASE-NOTES: synced - configure: without pkg-config and no custom path, use -lnghttp2 Reported-by: correctmost on github Fixes #11186 Closes #11210 Stefan Eissing (28 May 2023) - curl: cache the --trace-time value for a second - caches HH:MM:SS computed and reuses it for logging during the same second. - common function for plain log line start formatting Closes #11211 Kev Jackson (28 May 2023) - libcurl.m4: remove trailing 'dnl' that causes this to break autoconf Closes #11212 Stefan Eissing (26 May 2023) - http3: send EOF indicator early as possible - ngtcp2 and quiche implementations relied on the DONE_SEND event to forward the EOF for uploads to the libraries. This often result in a last 0 length EOF data. Tracking the amount of data left to upload allows EOF indication earlier. - refs #11205 where CloudFlare DoH servers did not like to receive the initial upload DATA without EOF and returned a 400 Bad Request Reported-by: Sergey Fionov Fixes #11205 Closes #11207 Daniel Stenberg (26 May 2023) - scripts/contri*sh: no longer grep -v ' ' Originally these scripts filtered out names that have no space so that they better avoid nick names not intended for credits. Such names are not too commonly used, plus we now give credit even to those. Additionally: non-latin names, like Asian, don't have spaces at all so they were also filtered out and had to be manually added which made it an error-prone operation where Asian names eventually easily fell off by mistake. Closes #11206 - cf-socket: restore Curl_sock_assign_addr() Regression since it was not private. Also used by msh3.c Follow-up to 8e85764b7bd7f05f5 Reported-by: Gisle Vanem Fixes #11202 Closes #11204 - RELEASE-NOTES: synced Taken down to 8.1.2 now for pending patch release - libssh: when keyboard-interactive auth fails, try password The state machine had a mistake in that it would not carry on to that next step. This also adds a verbose output what methods that are available from the server and renames the macros that change to the next auth methods to try. Reported-by: 左潇峰 Fixes #11196 Closes #11197 Emanuele Torre (25 May 2023) - configure: fix build with arbitrary CC and LD_LIBRARY_PATH Since ./configure and processes that inherit its environment variables are the only callers of the run-compiler script, we can just save the current value of the LD_LIBRARY_PATH and CC variables to another pair of environment variables, and make run-compiler a static script that simply restores CC and LD_LIBRARY_PATH to the saved value, and before running the compiler. This avoids having to inject the values of the variables in the script, possibly causing problems if they contains spaces, quotes, and other special characters. Also add exports in the script just in case LD_LIBRARY_PATH and CC are not already in the environment. follow-up from 471dab2 Closes #11182 Daniel Stenberg (25 May 2023) - urlapi: remove superfluous host name check ... as it is checked later more proper. Closes #11195 Stefan Eissing (25 May 2023) - http2: fix EOF handling on uploads with auth negotiation - doing a POST with `--digest` does an override on the initial request with `Content-Length: 0`, but the http2 filter was unaware of that and expected the originally request body. It did therefore not send a final DATA frame with EOF flag to the server. - The fix overrides any initial notion of post size when the `done_send` event is triggered by the transfer loop, leading to the EOF that is necessary. - refs #11194. The fault did not happen in testing, as Apache httpd never tries to read the request body of the initial request, sends the 401 reply and closes the stream. The server used in the reported issue however tried to read the EOF and timed out on the request. Reported-by: Aleksander Mazur Fixes #11194 Cloes #11200 Daniel Stenberg (23 May 2023) - RELEASE-NOTES: synced bump to 8.2.0 - lib: remove unused functions, make single-use static Closes #11174 - scripts/singleuse.pl: add more API calls Christian Hesse (23 May 2023) - configure: quote the assignments for run-compiler Building for multilib failed, as the compiler command contains an extra argument. That needs quoting. Regression from b78ca50cb3dda361f9c1 Fixes #11179 Closes #11180 Daniel Stenberg (23 May 2023) - misc: fix spelling mistakes Reported-by: musvaage on github Fixes #11171 Closes #11172 Version 8.1.1 (23 May 2023) Daniel Stenberg (23 May 2023) - RELEASE-NOTES: synced curl 8.1.1 - THANKS: contributors from the 8.1.1 release Dan Fandrich (22 May 2023) - docs: fix fuzzing documentation link Follow-up to 4c712a1b - CI: add an Alpine build with MUSL MUSL is another libc implementation which has its own unique issues worth testing. Ref: #11140 Closes #11178 - runtests: add a missing \n at the end of a log message correctmost on github (22 May 2023) - SECURITY-PROCESS.md: link security advisory doc and fix typo Closes #11177 Daniel Stenberg (22 May 2023) - TODO: build curl with Windows Unicode support Closes #7229 - KNOWN_BUGS: hyper memory-leaks Closes #10803 Stefan Eissing (22 May 2023) - http/2: unstick uploads - refs #11157 and #11175 where uploads get stuck or lead to RST streams - fixes our h2 send behaviour to continue sending in the nghttp2 session as long as it wants to. This will empty our send buffer as long as the remote stream/connection window allows. - in case the window is exhausted, the data remaining in the send buffer will wait for a WINDOW_UPDATE from the server. Which is a socket event that engages our transfer loop again - the problem in the issue was that we did not exhaust the window, but left data in the sendbuffer and no further socket events did happen. The server was just waiting for us to send more. - relatedly, there was an issue fixed that closing a stream with KEEP_HOLD set kept the transfer from shutting down - as it should have - leading to a timeout. Closes #11176 Daniel Stenberg (21 May 2023) - workflows/macos: add a job using gcc + debug + secure transport Jay Satiro (21 May 2023) - lib: fix conversion warnings with gcc on macOS Daniel Stenberg (21 May 2023) - sectransp.c: make the code c89 compatible Follow-up to dd2bb485521c2ec713001b3a Reported-by: FeignClaims on github Fixes #11155 Closes #11159 Emanuele Torre (21 May 2023) - Revert "urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirect s" This reverts commit df6c2f7b544f1f35f2a3e0be11f345affeb6fe9c. (It only keep the test case that checks redirection to an absolute URL without hostname and CURLU_NO_AUTHORITY). I originally wanted to make CURLU_ALLOW_SPACE accept spaces in the hostname only because I thought curl_url_set(CURLUPART_URL, CURLU_ALLOW_SPACE) was already accepting them, and they were only not being accepted in the hostname when curl_url_set(CURLUPART_URL) was used for a redirection. That is not actually the case, urlapi never accepted hostnames with spaces, and a hostname with a space in it never makes sense. I probably misread the output of my original test when I they were normally accepted when using CURLU_ALLOW_SPACE, and not redirecting. Some other URL parsers seems to allow space in the host part of the URL, e.g. both python3's urllib.parse module, and Chromium's javascript URL object allow spaces (chromium percent escapes the spaces with %20), (they also both ignore TABs, and other whitespace characters), but those URLs with spaces in the hostname are useless, neither python3's requests module nor Chromium's window.location can actually use them. There is no reason to add support for URLs with spaces in the host, since it was not a inconsistency bug; let's revert that patch before it makes it into release. Sorry about that. I also reverted the extra check for CURLU_NO_AUTHORITY since that does not seem to be necessary, CURLU_NO_AUTHORITY already worked for redirects. Closes #11169 Dan Fandrich (20 May 2023) - runtests: use the correct fd after select The code was using the wrong fd when determining which runner was ready with a response. Ref: #10818 Closes #11160 - test425: fix the log directory for the upload This must be %LOGDIR to let it work with parallel tests. Ref: #10969 - runtests: handle interrupted reads from IPC pipes These can be interrupted by signals, especially SIGINT to shut down, and must be restarted so the IPC call arrives correctly. If the read just returns an error instead, the IPC calling state will go out of sync and a proper shutdown won't happen. Ref: #10818 Stefan Eissing (20 May 2023) - http2: upload improvements Make send buffer smaller to have progress and "upload done" reporting closer to reality. Fix handling of send "drain" condition to no longer trigger once the transfer loop reports it is done sending. Also do not trigger the send "drain" on RST streams. Background: - a upload stall was reported in #11157 that timed out - test_07_33a reproduces a problem with such a stall if the server 404s the request and RSTs the stream. - test_07_33b verifies a successful PUT, using the parameters from #11157 and checks success Ref: #11157 Closes #11165 - http2: increase stream window size to 10 MB Reported-by: pandada8 on github Fixes #11162 Closes #11167 Daniel Stenberg (20 May 2023) - lib: rename struct 'http_req' to 'httpreq' Because FreeBSD 14 kidnapped the name. Ref: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271526 Fixes #11163 Closes #11164 Viktor Szakats (20 May 2023) - cmake: avoid `list(PREPEND)` for compatibility `list(PREPEND)` requires CMake v3.15, our minimum is v3.7. Ref: https://cmake.org/cmake/help/latest/command/list.html#prepend Regression from 1e3319a167d2f32d295603167486e9e88af9bb4e Reported-by: Keitagit-kun on Github Fixes #11141 Closes #11144 Daniel Stenberg (19 May 2023) - RELEASE-NOTES: synced Stefan Eissing (19 May 2023) - ngtcp2: proper handling of uint64_t when adjusting send buffer Fixes #11149 Closes #11153 - ngtcp2: fix compiler warning about possible null-deref - compiler analyzer did not include the call context for this static function where the condition had already been checked. - eleminating the problem by making stream a call parameter Fixes #11147 Closes #11151 Emanuele Torre (19 May 2023) - docs: document that curl_url_cleanup(NULL) is a safe no-op This has always been the case, but it was not documented. The paragraph was copied verbatim from curl_easy_cleanup.3 Closes #11150 Antoine Pitrou (19 May 2023) - select: avoid returning an error on EINTR from select() or poll() This was already done for the poll() and select() calls made directly from Curl_poll(), but was missed in Curl_wait_ms(), which is called when there are no fds to wait on. Fixes #11135 Closes #11143 Daniel Stenberg (19 May 2023) - vquic.c: make recvfrom_packets static, avoid compiler warning warning: no previous prototype for 'recvfrom_packets' Reported-by: Keitagit-kun on github Fixes #11146 Closes #11148 - urlapi: allow numerical parts in the host name It can only be an IPv4 address if all parts are all digits and no more than four parts, otherwise it is a host name. Even slightly wrong IPv4 will now be passed through as a host name. Regression from 17a15d88467 shipped in 8.1.0 Extended test 1560 accordingly. Reported-by: Pavel Kalyugin Fixes #11129 Closes #11131 Emilio Cobos Álvarez (19 May 2023) - http2: double http request parser max line length This works around #11138, by doubling the limit, and should be a relatively safe fix. Ideally the buffer would grow as needed and there would be no need for a limit? But that might be follow-up material. Fixes #11138 Closes #11139 Emanuele Torre (18 May 2023) - configure: fix --help alignment AC_ARG_ENABLE seems to only trim off whitespace from the start and end of its help-string argument, while prepending two spaces of indentation to all lines. This means that the two spaces of indentation between the --enable-rtsp and the --disable-rtsp line were not removed causing ./configure --help to print: Optional Features: [...] --enable-rtsp Enable RTSP support --disable-rtsp Disable RTSP support I removed the indentation to fix the issue, now it prints: Optional Features: [...] --enable-rtsp Enable RTSP support --disable-rtsp Disable RTSP support The --enable-hsts and --disable-hsts lines had the same problems, and have been fixed too. Closes #11142 Deal(一线灵) (18 May 2023) - cmake: repair cross compiling It cannot *run* code for testing purposes when cross-compiling. Closes #11130 Daniel Stenberg (18 May 2023) - configure: generate a script to run the compiler in the CURL_RUN_IFELSE macro, with LD_LIBRARY_PATH set to the value of the configure invoke, and not the value that might be used later, intended for the execution of the output the compiler ouputs. For example when the compiler uses the same library (like libz) that configure checks for. Reported-by: Jonas Bülow Fixes #11114 Closes #11120 Stefan Eissing (18 May 2023) - cf-socket: completely remove the disabled USE_RECV_BEFORE_SEND_WORKAROUND Closes #11118 Emanuele Torre (18 May 2023) - urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirects curl_url_set(uh, CURLUPART_URL, redirurl, flags) was not respecing CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY in the host part of redirurl when redirecting to an absolute URL. Closes #11136 Colin Cross (18 May 2023) - hostip: move easy_lock.h include above curl_memory.h Similar to #9561, move easy_lock.h above curl_memory.h to fix building against musl libc. Closes #11140 Hind Montassif (18 May 2023) - curl_easy_getinfo: clarify on return data types Closes #11126 Emanuele Torre (18 May 2023) - checksrc: disallow spaces before labels Out of 415 labels throughout the code base, 86 of those labels were not at the start of the line. Which means labels always at the start of the line is the favoured style overall with 329 instances. Out of the 86 labels not at the start of the line: * 75 were indented with the same indentation level of the following line * 8 were indented with exactly one space * 2 were indented with one fewer indentation level then the following line * 1 was indented with the indentation level of the following line minus three space (probably unintentional) Co-Authored-By: Viktor Szakats Closes #11134 Daniel Stenberg (18 May 2023) - cookie: update the comment on cookie length and size limits To refer to the proper cookie RFC and the upcoming RFC refresh. Closes #11127 - url: provide better error message when URLs fail to parse By providing the URL API error message into the error message. Ref: #11129 Closes #11137 - RELEASE-NOTES: synced bumped to 8.1.1 Jon Rumsey (18 May 2023) - os400: update chkstrings.c Compensate changes for recent changes to urldata.h to reclassify STRING_AWS_SIGV4. Fixes #11132 Closes #11133 Version 8.1.0 (17 May 2023) Daniel Stenberg (17 May 2023) - RELEASE-NOTES: synced - THANKS: contributors from the 8.1.0 release - hostip: include easy_lock.h before using GLOBAL_INIT_IS_THREADSAFE Since that header file is the only place that define can be defined. Reported-by: Marc Deslauriers Follow-up to 13718030ad4b3209 Closes #11121 Thomas Taylor (16 May 2023) - aws-sigv4.d: fix region identifier in example Closes #11117 Philip Heiduck (15 May 2023) - mlc_config.json: remove this linkcheck CI job config file Closes #11113 Daniel Silverstone (15 May 2023) - ssh: Add support for libssh2 read timeout Hook the new (1.11.0 or newer) libssh2 support for setting a read timeout into the SERVER_RESPONSE_TIMEOUT option. With this done, clients can use the standard curl response timeout setting to also control the time that libssh2 will wait for packets from a slow server. This is necessary to enable use of very slow SFTP servers. Signed-off-by: Daniel Silverstone <daniel.silverstone@codethink.co.uk> Closes #10965 Osama Albahrani (14 May 2023) - GIT-INFO: add --with-openssl Closes #11110 Daniel Stenberg (13 May 2023) - RELEASE-NOTES: synced Marcel Raad (13 May 2023) - md(4|5): don't use deprecated iOS functions They are marked as deprecated in iOS 13.0, which might result in warnings-as-errors. Also, use `*_MIN_REQUIRED` instead of `*_MIN_ALLOWED`, which seems to be what's currently used. Bug: https://github.com/curl/curl/issues/11098 Closes https://github.com/curl/curl/pull/11102 - md4: only build when used Its only usage in curl_ntlm_core.c is guarded by `USE_CURL_NTLM_CORE`, so let's use this here too. Ref: https://github.com/curl/curl/issues/11098 Closes https://github.com/curl/curl/pull/11102 Vítor Galvão (12 May 2023) - write-out.d: Use response_code in example Closes #11107 Shohei Maeda (12 May 2023) - url: fix null dispname for --connect-to option Closes #11106 Daniel Stenberg (12 May 2023) - test2306: verify getting a second response with folded headers Reproduces the isue #11101 and verifies the fix. Verifies a17b2a503f - headers: clear (possibly) lingering pointer in init The "prevhead" pointer is used for the headers storage but was not cleared correctly in init, which made it possible to act up when a handle is reused. Reported-by: Steve Herrell Fixes #11101 Closes #11103 - RELEASE-NOTES: synced - ngtcp2: use 0.15.0 - nghttp3 0.11.0 - nghttp2 1.53.0 Adapt to new API calls Closes #11031 Jay Satiro (10 May 2023) - openssl: fix indent Daniel Stenberg (10 May 2023) - CURLOPT_DNS_CACHE_TIMEOUT.3: fix spelling Follow-up to 9ed7d56e044f5aa1b29 Closes #11096 - hostip: use time_t for storing oldest DNS entry Theoretically, the oldest time could overflow an int. In practice that won't happen, but let's do this to please analyzers. Follow-up to 9ed7d56e044f5aa1b2928ccde6245d0 Pointed out by Coverity. Closes #11094 - http: free the url before storing a new copy To avoid a memory-leak. Reported-by: Hiroki Kurosawa Closes #11093 - compressed.d: clarify the words on "not notifying headers" Reported-by: Dylan Anthony Fixes #11091 Closes #11092 - libssh2: free fingerprint better Reported-by: Wei Chong Tan Closes #11088 - CURLOPT_IPRESOLVE.3: clarify that this for host names, not IP addresses Reported-by: Harry Sintonen Closes #11087 - hostip: enforce a maximum DNS cache size independent of timeout value To reduce the damage an application can cause if using -1 or other ridiculous timeout values and letting the cache live long times. The maximum number of entries in the DNS cache is now totally arbitrarily and hard-coded set to 29999. Closes #11084 - hostip: store dns timeout as 'int' ... because it set and held as an 'int' elsewhere and can never be larger. - RELEASE-NOTES: synced - tool_operate: refuse (--data or --form) and --continue-at combo libcurl assumes that a --continue-at resumption is done to continue an upload using the read callback and neither --data nor --form use that and thus won't do what the user wants. Whatever the user wants with this strange combination. Add test 426 to verify. Reported-by: Smackd0wn on github Fixes #11081 Closes #11083 - transfer: refuse POSTFIELDS + RESUME_FROM combo The code assumes that such a resume is wanting to continue an upload using the read callback, and since POSTFIELDS is done without callback libcurl will just misbehave. This combo will make the transfer fail with CURLE_BAD_FUNCTION_ARGUMENT with an explanation in the error message. Reported-by: Smackd0wn on github Fixes #11081 Closes #11083 - ipv4.d/ipv6.d: they are "mutex", not "boolean" ... which for example means they do not have --no-* versions. Reported-by: Harry Sintonen Fixes #11085 Closes #11086 - docs/SECURITY-ADVISORY.md: how to write a curl security advisory Closes #11080 nobedee on github (5 May 2023) - MANUAL.md: add dict example for looking up a single definition Closes #11077 Dan Fandrich (5 May 2023) - runtests: fix -c option when run with valgrind The curl binary argument wasn't being quoted properly. This seems to have broken at some point after quoting was added in commit 606b29fe. Reported-by: Daniel Stenberg Ref: #11073 Fixes #11074 Closes #11076 - runtests: support creating more than one runner process The controller currently only creates and uses one, but more are now possible. Ref: #10818 - runtests: spawn a new process for the test runner When the -j option is given, a new process is spawned in which the test programs are run and from which test servers are started. Only one process can be started at once, but this is sufficient to test that the infrastructure can isolate those functions in a new task. There should be no visible difference between the two modes at the moment. Ref: #10818 Closes #11064 - runtests: turn singletest() into a state machine This allows it to run in a non-blocking manner. Ref: #10818 - runtests: change runner interface to be asynchronous Program arguments are marshalled and then written to the end of a pipe which is later read from and the arguments unmarshalled before the desired function is called normally. The function return values are then marshalled and written into another pipe when is later read from and unmarshalled before being returned to the caller. The implementation is currently blocking but can be made non-blocking without any changes to the API. This allows calling multiple runners without blocking in the future. Ref: #10818 - runtests: call citest_finishtest in singletest This is where citest_starttest is called. Ref: #10818 - runtests: add a runner initialization function This sets up the runner environment to start running tests. Ref: #10818 - runtests: remove directory from server filename variables There will soon be multiple log directories so the paths will no longer be static in runtests.pl. Also, get rid of $SERVER2IN which was not used. Ref: #10818 - runtests: reduce package exports after refactoring Some recent refactoring made these export no longer necessary. Also, stop displaying the Unix socket paths at startup since there will soon be many of them and they're not that interesting. Ref: #10818 - runtests: use a function to obtain $LOGDIR for a test This will no longer be static soon. Ref: #10818 Jay Satiro (5 May 2023) - tool_cb_hdr: Fix 'Location:' formatting for early VTE terminals - Disable hyperlink formatting for the 'Location:' header value in VTE 0.48.1 and earlier, since it is buggy in some of those versions. Prior to this change those terminals may show the location header value as gibberish or show it twice. Ref: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#backw ard-compatibility Fixes https://github.com/curl/curl/issues/10428 Closes https://github.com/curl/curl/pull/11071 François Michel (3 May 2023) - quiche: disable pacing while pacing is not actually performed Closes #11068 Daniel Stenberg (2 May 2023) - easy_cleanup: require a "good" handle to act By insisting that the passed in handle is "good" (the magic number is intact), this can limit the potential damage if a bad pointer is passed in. Like when this function is called twice on the same handle pointer. Ref: #10964 Closes #11061 Andreas Falkenhahn (1 May 2023) - amiga: Fix CA certificate paths for AmiSSL and MorphOS AmiSSL stores certificates in `AmiSSL:Certs` and MorphOS stores them in `MOSSYS:Data/SSL/curl-ca-bundle.crt`. Closes https://github.com/curl/curl/pull/11059 Daniel Stenberg (30 Apr 2023) - http2: (void)-mark when we explicitly ignore the return code When h2_progress_egress() is called. Pointed out by Coverity. Closes #11057 - checksrc: find bad indentation in conditions without open brace If the previous line starts with if/while/for AND ends with a closed parenthesis and there's an equal number of open and closed parentheses on that line, verify that this line is indented $indent more steps, if not a cpp line. Also adjust the fall-out from this fix. Closes #11054 Diogo Teles Sant'Anna (28 Apr 2023) - CI: Set minimal permissions on workflow ngtcp2-quictls.yml Signed-off-by: Diogo Teles Sant'Anna <diogoteles@google.com> Closes #11055 Dan Fandrich (28 Apr 2023) - CI: use another glob syntax for matching files on Appveyor The previous globbing syntax was not matching files recursively in directories, so try appending a /* to more closely match the examples at https://www.appveyor.com/docs/how-to/filtering-commits/ Daniel Stenberg (28 Apr 2023) - multi: add multi-ignore logic to multi_socket_action The multi-ignore logic that was previously applied to curl_multi_perform() (#10750) is here applied to the loop within curl_multi_socket_action() to make it use the same optimization: most handles have the same signal-ignore option state so this drastically reduces the number of ignore/unignore calls per libcurl function invoke. Follow-up to bc90308328afb8 Closes #11045 Stefan Eissing (28 Apr 2023) - http2: do flow window accounting for cancelled streams - nghttp2 does not free connection level window flow for aborted streams - when closing transfers, make sure that any buffered response data is "given back" to the flow control window - add tests test_02_22 and test_02_23 to reproduce Closes #11052 - pingpong: fix compiler warning "assigning an enum to unsigned char" Closes #11050 Daniel Stenberg (28 Apr 2023) - configure: fix detection of apxs (for httpd) The condition check was turned the wrong way around! Closes #11051 Viktor Szakats (28 Apr 2023) - ci: `-Wno-vla` no longer necessary We handle this issue in the source now. Follow-up to b725fe1944b45406676ea3aff333ae3085a848d9 Reviewed-by: Marcel Raad Reviewed-by: Daniel Stenberg Closes #11048 Marcel Raad (28 Apr 2023) - tests/http: make curl_setup.h the first include This is required for the macros there to take effect for system libraries. Specifically, including the system libraries first led to warnings about `_FILE_OFFSET_BITS` being redefined in curl_config.h on the Solaris autobuilds for ws-data.c and ws-pingpong.c. Also make the curl includes come first for the other source files here for consistency. Closes https://github.com/curl/curl/pull/11046 Emanuele Torre (27 Apr 2023) - checksrc: check for spaces before the colon of switch labels Closes #11047 Daniel Stenberg (27 Apr 2023) - RELEASE-NOTES: synced - libssh: tell it to use SFTP non-blocking Reported-by: Andreas Huebner Fixes #11020 Closes #11039 Stefan Eissing (27 Apr 2023) - http2: enlarge the connection window - fixes stalled connections - Make the connection window large enough, so that there is some room left should 99/100 streams be PAUSED by the application Reported-by: Paweł Wegner Fixes #10988 Closes #11043 Daniel Stenberg (27 Apr 2023) - checksrc: fix SPACEBEFOREPAREN for conditions starting with "*" The open paren check wants to warn for spaces before open parenthesis for if/while/for but also for any function call. In order to avoid catching function pointer declarations, the logic allows a space if the first character after the open parenthesis is an asterisk. I also spotted what we did not include "switch" in the check but we should. This check is a little lame, but we reduce this problem by not allowing that space for if/while/for/switch. Reported-by: Emanuele Torre Closes #11044 - docs: minor polish - "an HTTP*" (not "a") - remove a few contractions - remove a spurious "a" - reduce use of "I" in texts Closes #11040 - ws: fix CONT opcode check Detected by Coverity. Follow-up to 930c00c259 Closes #11037 Dan Fandrich (27 Apr 2023) - CI: switch the awslc builds to build out-of-tree This is a common configuration that should be tested to avoid regressions. The awsls cmake build was already out-of-tree so the automake build now joins it. Ref: #11006 - tests/http: fix out-of-tree builds Add both lib/ directories (src & build) to the search path so curl_setup.h and its dependencies can be found. Followup-to acd82c8b Ref: #11006 Closes #11036 Daniel Stenberg (27 Apr 2023) - urlapi: make internal function start with Curl_ Curl_url_set_authority() it is. Follow-up to acd82c8bfd Closes #11035 YX Hao (26 Apr 2023) - cf-socket: turn off IPV6_V6ONLY on Windows if it is supported IPV6_V6ONLY refs: https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses https://github.com/golang/go/blob/master/src/net/ipsock_posix.go https://en.wikipedia.org/wiki/Unix-like https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-o ptions default value refs: https://datatracker.ietf.org/doc/html/rfc3493#section-5.3 https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html#proc-sys-net -ipv6-variables Closes #10975 Daniel Stenberg (26 Apr 2023) - urldata: shrink *select_bits int => unsigned char - dselect_bits - cselect_bits ... are using less than 8 bits. Changed types and moved them towards the end of the structs to fit better. Closes #11025 Stefan Eissing (26 Apr 2023) - tests/http: more tests with specific clients - Makefile support for building test specific clients in tests/http/clients - auto-make of clients when invoking pytest - added test_09_02 for server PUSH_PROMISEs using clients/h2-serverpush - added test_02_21 for lib based downloads and pausing/unpausing transfers curl url parser: - added internal method `curl_url_set_authority()` for setting the authority part of a url (used for PUSH_PROMISE) http2: - made logging of PUSH_PROMISE handling nicer Placing python test requirements in requirements.txt files - separate files to base test suite and http tests since use and module lists differ - using the files in the gh workflows websocket test cases, fixes for we and bufq - bufq: account for spare chunks in space calculation - bufq: reset chunks that are skipped empty - ws: correctly encode frames with 126 bytes payload - ws: update frame meta information on first call of collect callback that fills user buffer - test client ws-data: some test/reporting improvements Closes #11006 Jay Satiro (26 Apr 2023) - libssh2: fix crash in keyboard callback - Always set the libssh2 'abstract' user-pointer to the libcurl easy handle associated with the ssh session, so it is always passed to the ssh keyboard callback. Prior to this change and since 8b5f100 (precedes curl 8.0.0), if libcurl was built without CURL_DEBUG then it could crash during the ssh auth phase due to a null dereference in the ssh keyboard callback. Reported-by: Andreas Falkenhahn Fixes https://github.com/curl/curl/pull/11024 Closes https://github.com/curl/curl/pull/11026 Daniel Stenberg (26 Apr 2023) - docs: clarify that more backends have HTTPS proxy support Closes #11033 - KNOWN_BUGS: remove two not-bugs - 11.7 signal-based resolver timeouts Not considered a bug anymore but just implementation details. People should avoid using timeouts with the synchronous name resolver. - 11.16 libcurl uses renames instead of locking for atomic operations Not a bug, just a description of how it works Closes #11032 Harry Sintonen (26 Apr 2023) - hostip: add locks around use of global buffer for alarm() When building with the sync name resolver and timeout ability we now require thread-safety to be present to enable it. Closes #11030 Daniel Stenberg (26 Apr 2023) - curl_path: bring back support for SFTP path ending in /~ libcurl used to do a directory listing for this case (even though the documentation says a URL needs to end in a slash for this), but 4e2b52b5f7a3 modified the behavior. This change brings back a directory listing for SFTP paths that are specified exactly as /~ in the URL. Reported-by: Pavel Mayorov Fixes #11001 Closes #11023 Emanuele Torre (26 Apr 2023) - docs/libcurl/curl_*escape.3: rename "url" argument to "input"/"string" Also reword the DESCRIPTION section to mention "input"/"string" argument in bold. Closes #11027 - docs/libcurl: minor cleanups I was reading curl_unescape(3) and I noticed that there was an extra space after the open parenthesis in the SYNOPSIS; I removed the extra space. I also ran a few grep -r commands to find and remove extra spaces after '(' in other files, and to find and replace uses of `T*' instead of `T *'. Some of the instances of `T*` where unnecessary casts that I removed. I also fixed a comment that was misaligned in CURLMOPT_SOCKETFUNCTION.3. And I fixed some formatting inconsistencies: in curl_unescape(3), all function parameter were mentioned with bold text except length, that was mentioned as 'length'; and, in curl_easy_unescape(3), all parameters were mentioned in bold text except url that was italicised. Now they are all mentioned in bold. Documentation is not very consistent in how function parameter are formatted: many pages italicise them, and others display them in bold text; but I think it makes sense to at least be consistent with formatting within the same page. Closes #11027 Daniel Stenberg (26 Apr 2023) - man pages: simplify the .TH sections - remove the version numbers - simplify the texts The date and version number will be put there for releases when maketgz runs the updatemanpages.pl script. Closes #11029 - hostcheck: fix host name wildcard checking The leftmost "label" of the host name can now only match against single '*'. Like the browsers have worked for a long time. - extended unit test 1397 for this - move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc Reported-by: Hiroki Kurosawa Closes #11018 Dan Fandrich (25 Apr 2023) - smbserver: remove temporary files before exit Each execution of test 1451 would leave a file in /tmp before. Since Windows can't delete a file while it's open, all the temporary file names are stored and deleted on exit. Closes #10990 Stefan Eissing (25 Apr 2023) - Websocket en-/decoding - state is fully kept at connection, since curl_ws_send() and curl_ws_rec() have lifetime beyond usual transfers - no more limit on frame sizes Reported-by: simplerobot on github Fixes #10962 Closes #10999 Patrick Monnerat (25 Apr 2023) - urldata: copy CURLOPT_AWS_SIGV4 value on handle duplication Prior to this change STRING_AWS_SIGV4 (CURLOPT_AWS_SIGV4) was wrongly marked as binary data that could not be duplicated. Without this fix, this option's value is not copied upon calling curl_easy_duphandle(). Closes https://github.com/curl/curl/pull/11021 Stefan Eissing (25 Apr 2023) - http3: expire unpaused transfers in all HTTP/3 backends Closes #11005 - http2: always EXPIRE_RUN_NOW unpaused http/2 transfers - just increasing the http/2 flow window does not necessarily make a server send new data. It may already have exhausted the window before Closes #11005 - http2: pass `stream` to http2_handle_stream_close to avoid NULL checks Closes #11005 - h2/h3: replace `state.drain` counter with `state.dselect_bits` - `drain` was used by http/2 and http/3 implementations to indicate that the transfer requires send/recv independant from its socket poll state. Intended as a counter, it was used as bool flag only. - a similar mechanism exists on `connectdata->cselect_bits` where specific protocols can indicate something similar, only for the whole connection. - `cselect_bits` are cleard in transfer.c on use and, importantly, also set when the transfer loop expended its `maxloops` tries. `drain` was not cleared by transfer and the http2/3 implementations had to take care of that. - `dselect_bits` is cleared *and* set by the transfer loop. http2/3 does no longer clear it, only set when new events happen. This change unifies the handling of socket poll overrides, extending `cselect_bits` by a easy handle specific value and a common treatment in transfers. Closes #11005 Daniel Stenberg (25 Apr 2023) - socketpair: verify with a random value ... instead of using the curl time struct, since it would use a few uninitialized bytes and the sanitizers would complain. This is a neater approach I think. Reported-by: Boris Kuschel Fixes #10993 Closes #11015 Stefan Eissing (25 Apr 2023) - HTTP3: document the ngtcp2/nghttp3 versions to use for building curl - refs #11011 to clarify this for people building curl themselves Closes #11019 Daniel Stenberg (25 Apr 2023) - lib: unify the upload/method handling By making sure we set state.upload based on the set.method value and not independently as set.upload, we reduce confusion and mixup risks, both internally and externally. Closes #11017 - RELEASE-NOTES: synced Dan Fandrich (24 Apr 2023) - CI: don't run CI jobs if only another CI was changed A few paths were missed in the last commit, as well as a job added since then. Followup-to 395b9175 - CI: adjust labeler match patterns - runtests: support buffering log messages in runner & servers Log messages generated with logmsg can now be buffered and returned from the runner as a return value. This will be needed with parallel testing to allow all messages for one test to be displayed together instead of interspersed with messages of multiple tests. Buffering can be disabled by setting a logging callback function with setlogfunc, which is currently being done to preserve existing logging behaviour for now. Some additional output is generated in verbose and debugprotocol modes, which don't always use logmsg. These modes also impact some servers which generate extra messages. No attempt is made to buffer everything if these modes are enabled. Ref: #10818 Closes #11016 - runtests: more consistently use logmsg in server control code Also, display an error when sshversioninfo returns one. Ref: #10818 - runtests: create runner functions for clearlocks and stopservers runtests.pl now uses runner for all server actions beyond the initial variable configuration. Ref: #10818 - runtests: tightened servers package exports The defaults are intended for runtests.pl, whereas runner.pm needs to explicitly specify them. - runtests: display logs on server failure in singletest() This is closer to the place where logs are displayed on test failure. Also, only display these logs if -p is given, which is the same flag that controls display of test failure logs. Some server log files need to be deleted later so that they stay around long enough to be displayed on failure. Ref: #10818 - runtests: turn a print into a logmsg Also enable another couple of useful messages in verbose mode. Ref: #10818 Daniel Stenberg (24 Apr 2023) - http: store the password in the correct variable Typo from fc2f1e547a4a, detected by Coverity (because there's dead code due to this). Closes #11002 Stefan Eissing (24 Apr 2023) - HTTP3/quiche: terminate h1 response header when no body is sent - fixes a failure in test2501 where a response without body was missing the final empty line Closes #11003 Dan Fandrich (22 Apr 2023) - runtests: move showdiff into runtests.pl It's not used anywhere else. - devtest: add a new script for testing the test harness This is currently useful for starting a test server on its own without an associated test, which can be used for interactive curl testing or for validating parts of the test harness itself. More commands can be added to perform additional functions in the future. Ref: #10818 Closes #11008 - runtests: refactor the main test loop into two The test loop now has an initial loop that first runs through all possible tests to build a set of those to attempt on this run based on features and keywords and only then goes through that new list to run them. This actually makes it three loops through all tests cases, as there is an existing loop that gathers possible test numbers from the test files on disk. This has two minor effects on the output: all the tests that will be skipped are displayed at the start (instead of being interspersed with other tests) and the -l option no longer shows a count of tests at the end or a (misleading) statement that tests have run successfully. The skipped tests are also omitted from the test results sent to AppVeyor and Azure in CI builds. Another effect is a reduction in the amount of work considered part of the "Test definition reading and preparation time" reported with -r making those figures slightly lower than before. Ref: #10818 - runtests: track only the current test timings in runner.pm This avoids passing these data through through global variables, which soon won't be possible. Ref: #10818 - runtests: skip test preprocessing when doing -l This speeds up the output tremendously by avoiding unnecessary work. - runtests: simplify value returned regarding use of valgrind As a side effect this will now also show in verbose mode that valgrind is being skipped on tests that explicitly disable it, such as 600. Ref: #10818 - runtests: fix quoting in Appveyor and Azure test integration Test 1442's name was not quoted correctly so wasn't registered in Appveyor and it had the wrong name in Azure. The JSON string quotes were also invalid, even though both servers happened to accept it regardless. Closes #11010 Daniel Stenberg (19 Apr 2023) - RELEASE-NOTES: synced Dan Fandrich (18 Apr 2023) - runtests: spread out the port numbers used by servers The server ports are chosen randomly for each server, but the random ranges chosen were inconsistently-sized and overlapping. Now, they are spread out more so at least the first random port chosen for each server is guaranteed to not also be chosen by another server. The starting port numbers are also raised to put them in the Ephemeral Port range—not the range defined by RFC 6335 but the one used by Linux, which starts lower and gives us more room to work with. Reported-by: Daniel Stenberg - runtests: fix problems on <killserver> failure The verify time must be set in this case, like all cases. An error message needs to be displayed as well. - runtests: fix perl warning when <tool> is wrong - runtests: don't try to stop stunnel before trying again Calling stopserver() before retrying stunnel due to an error would stop the dependent server (such as HTTP) meaning stunnel would have nothing to talk to when it came up. Don't try to force a stop when it didn't actually start. Also, don't mark the server as bad for future use when it starts up on a retry. Reported-by: eaglegai at github Tested-by: eaglegai at github Fixes #10976 - runtests: don't accidentally randomly choose the same port If a server couldn't be started on a port, a new one is randomly chosen and the server is tried again. Avoid accidentally using a randomly-chosen 0 port offset by adding 1 to the random number. Found-by: Daniel Stenberg - runtests: don't attempt to use a port we know is in use This reduces the startup time when there is a known conflict on the random port chosen for a server. This was already done for stunnel, but now it's done for all servers. - http-server: fix server name in a log message This changed when the file was renamed in commit cbf57176 - runtests: refactor into more packages testutil.pm now contains a few miscellaneous functions that are used in several places but have no better place to live. subvariables moves to servers.pm since most variables that it substitutes relate to servers, so this is the most appropriate place. Rename a few functions for better naming consistency. Ref: #10818 Closes #10995 - runtests: call timestampskippedevents() in singletest ..rather than by the runner - runtests: assume a newer Valgrind by default The tests for an older Valgrind version should probably just be deleted, given that they're testing for an 18-year-old version. - runtests: refactor test runner code into runner.pm This is code that is directly responsible for running a single test. This will eventually run in a separate process as part of the parallel testing project. Ref: #10818 - runtests: skip unneeded work if test won't be running This speeds up tests by avoiding unnecessary processing. Ref: #10818 - runtests: factor out singletest_postcheck This will eventually need to be part of the test runner. Ref: #10818 - test303: kill server after test Otherwise, an HTTP test closely following this one with a tight time constraint (e.g. 672) could fail because the test server stays sitting with the wait command for a while. Patrick Monnerat (18 Apr 2023) - OS400: provide ILE/RPG usage examples Closes https://github.com/curl/curl/pull/10994 - OS400: improve vararg emulation - Use V7R4 RPG procedure overloading to improve vararg emulation. From OS400 V7R4 and above, ILE/RPG implements a limited procedure overloading feature that can be used to improve curl's typed implementation of varargs procedures. This commit applies it to curl_easy_setopt(), curl_multi_setopt(), curl_share_setopt() and curl_easy_getinfo(). Closes https://github.com/curl/curl/pull/10994 - OS400: fix and complete ILE/RPG binding - Fix wrong definitions of CURL_ZERO_TERNINATED, curl_mime_data() and curl_mime_data_ccsid(). - Add recent definitions, in particular blob, header API and WebSockets API. - Support for CURLVERSION_ELEVENTH. - New functions for EBCDIC support. Reflect these changes in README.OS400. Closes https://github.com/curl/curl/pull/10994 - OS400: implement EBCDIC support for recent features - Support CURLVERSION_ELEVENTH. - New function curl_url_strerror_ccsid(). - curl_easy_setopt_ccsid() supports blobs and 3 recent string options. - New function curl_easy_header_ccsid(). - New generic latin1<-->ccsid conversion functions curl_from_ccsid() and curl_to_ccsid() for user convenience. - README.OS400 updated accordingly. - Removed a leftover QsoSSL support identifier. Closes https://github.com/curl/curl/pull/10994 - OS400: rework build scripts - Rename shell function "system" to "CLcommand" to avoid confusion with built-in command. - Reformat scripts. Fix some indentations. Avoid lines > 80 characters where possible. - Support ASCII runtime development files in a user-defined directory path. - FIX SONAME detection. - Drop form API test program compilation (does not exist anymore). Closes https://github.com/curl/curl/pull/10994 Sevan Janiyan (18 Apr 2023) - tests/sshserver.pl: Define AddressFamily earlier As the comment states "Address family must be specified before ListenAddress" , otherwise the tests fail to run `"failed starting SSH server" 52 times (582, 583, 600, 601, 602, 603, 604, 60 5, 606 and 43 more)` Closes #10983 Stefan Eissing (18 Apr 2023) - quiche: Enable IDLE egress handling Follow-up to 544abeea which added the handling but wrongly left it commented out. Closes https://github.com/curl/curl/pull/11000 Daniel Stenberg (18 Apr 2023) - docs/examples/protofeats.c: Outputs all protocols and features Showing off one way to get to char pointer arrays of info returned by curl_version_info() Closes #10991 - tests/keywords.pl: remove This script does not work since the introduction of the test preprocessing. If we need this functionality, it probably needs to be moved into the runtests tool or similar. Reported-by: Dan Fandrich Fixes #10895 Closes #10987 Stefan Eissing (17 Apr 2023) - http2: support HTTP/2 to forward proxies, non-tunneling - with `--proxy-http2` allow h2 ALPN negotiation to forward proxies - applies to http: requests against a https: proxy only, as https: requests will auto-tunnel - adding a HTTP/1 request parser in http1.c - removed h2h3.c - using new request parser in nghttp2 and all h3 backends - adding test 2603 for request parser - adding h2 proxy test cases to test_10_* scorecard.py: request scoring accidentally always run curl with '-v'. Removed that, expect double numbers. labeller: added http1.* and h2-proxy sources to detection Closes #10967 Daniel Stenberg (17 Apr 2023) - curl_easy_unescape.3: rename the argument and highlight it appropriately in the text. Closes #10979 Viktor Szakats (17 Apr 2023) - autotools: sync up clang picky warnings with cmake Bringing missing options over from CMake. Move around existing `-Wno-pointer-bool-conversion` option to come _after_ `-Wconversion`. Reviewed-by: Marcel Raad Closes #10974 Daniel Stenberg (17 Apr 2023) - tests/libtest/lib1900.c: remove This file was left behind when the rest of the test was previously removed. Follow-up to e50a877df74f - src/tool_operhlp.c: fix value stored to 'uerr' is never read Ref: https://github.com/curl/curl/pull/10974#issuecomment-1510461343 Reported-by: Viktor Szakats Closes #10982 Viktor Szakats (16 Apr 2023) - cmake: speed up and extend picky clang/gcc options Extend existing picky compiler options with ones missing compared to autotools builds. Also sync options between clang and gcc. Redesign the way we enable these options to avoid the slow option detection almost completely. This reduces the number of detections from 35 to zero for clang and 3 for gcc, even after adding a bunch of new options. clang 3.0 (2011-11-29) and gcc 2.95 (1999-07-31) now required. Also show enabled picky options. Ref: https://github.com/libssh2/libssh2/pull/952 Reviewed-by: Daniel Stenberg Closes #10973 Andreas Falkenhahn (16 Apr 2023) - nbtlm: use semicolons instead of commas for (void) args Closes #10978 Daniel Stenberg (15 Apr 2023) - multi: free up more data earleier in DONE Before checking for more users of the connection and possibly bailing out. Fixes #10971 Reported-by: Paweł Wegner Closes #10972 - RELEASE-NOTES: synced - curl: do NOT append file name to path for upload when there's a query Added test 425 to verify. Reported-by: Dirk Rosenkranz Bug: https://curl.se/mail/archive-2023-04/0008.html Closes #10969 - libcurl-thread.3: improved name resolver wording And make better .SH sections Closes #10966 Colman Mbuya (14 Apr 2023) - CURLOPT_PROXY_SSL_VERIFYPEER.3: fix minor grammar mistake Closes #10968 Daniel Stenberg (14 Apr 2023) - curl: add --proxy-http2 For trying HTTP/2 with an HTTPS proxy. Closes #10926 - KNOWN_BUGS: remove fixed or outdated issues, move non-bugs - remove h3 issues believed to be fixed - make the flaky CI issue be generic and not Windows specific - "TLS session cache does not work with TFO" now documented This is now a documented restriction and not a bug. TFO in general is rarely used and has other problems, making it a low-priotity thing to work on. - remove "Renegotiate from server may cause hang for OpenSSL backend" This is an OpenSSL issue, not a curl one. Even if it taints curl. - rm "make distclean loops forever" - rm "configure finding libs in wrong directory" Added a section to docs/INSTALL.md about it. - "A shared connection cache is not thread-safe" Moved over to TODO and expanded for other sharing improvements we could do - rm "CURLOPT_OPENSOCKETPAIRFUNCTION is missing" - rm "Blocking socket operations in non-blocking API" Already listed as a TODO - rm "curl compiled on OSX 10.13 failed to run on OSX 10.10" Water under the bridge. No one cares about this anymore. - rm "build on Linux links libcurl to libdl" Verified to not be true (anymore). - rm "libpsl is not supported" The cmake build supports it since cafb356e19cda22 Closes #10963 - url: fix PVS nits - expression 'hostptr' is always true - a part of conditional expression is always true: proxypasswd - expression 'proxyuser' is always true - avoid multiple Curl_now() calls in allocate_conn Ref: #10929 Closes #10959 - bufq: simplify since expression is always true The check for 'len' is already done so it will remain true until updated. Pointed out by PVS. Ref: #10929 Closes #10958 - hash: fix assigning same value Pointed out by PVS Ref: #10929 Closes #10956 - cookie: address PVS nits - avoid assigning the same value again - remove superfluous check of co->domain - reduce variable scope for namep/valuep Ref: #10929 Closes #10954 Stefan Eissing (14 Apr 2023) - cf-socket: Disable socket receive buffer by default - Disable socket receive buffer unless USE_RECV_BEFORE_SEND_WORKAROUND is in place. While we would like to use the receive buffer, we have stalls in parallel transfers where not all buffered data is consumed and no socket events happen. Note USE_RECV_BEFORE_SEND_WORKAROUND is a Windows sockets workaround that has been disabled by default since b4b6e4f1, due to other bugs. Closes https://github.com/curl/curl/pull/10961 - cf-h2-proxy: fix processing ingress to stop too early - progress ingress stopped too early, causing data from the underlying filters to not be processed and report that no tunnel data was available - this lead to "hangers" where no socket activity was seen but data rested in buffers Closes #10952 - http3: check stream_ctx more thoroughly in all backends - callbacks and filter methods might be invoked at unexpected times, e.g. when the transfer's stream_ctx has not been initialized yet or, more likely, has already been taken down. - check for existance of stream_ctx in such places and return an error or silently succeed the call. Closes #10951 Daniel Stenberg (13 Apr 2023) - ftp: fix 'portsock' variable was assigned the same value Pointed out by PVS Ref: #10929 Closes #10955 - ftp: remove dead code This condition can never be true here since it is handled already 28 lines above. Pointed out by PVS. Ref: #10929 Closes #10957 - cf-h1-proxy: skip an extra NULL assign and use Curl_safefree() once to save another NULL assign. Found by PVS. Ref. #10929 Closes #10953 Philip Heiduck (13 Apr 2023) - GHA: suppress git clone output Follow-up: https://github.com/curl/curl/commit/8203aa6ed405ec832d2c62f18dfda2 93f89a23f9 Closes #10949 Stefan Eissing (13 Apr 2023) - cf-socket: remove dead code discovered by PVS Closes #10960 Daniel Stenberg (13 Apr 2023) - http: skip a double NULL assign and also use a local variable to shorten the long names and increase readability in the function. Pointed out by PVS. Ref: #10929 Closes #10950 - mime: skip NULL assigns after Curl_safefree() Pointed out by PVS. Ref: #10929 Closes #10947 - rtsp: skip NULL assigns after Curl_safefree() ... since this is a macro that assigns NULL itself. Pointed out by PVS. Ref: #10929 Closes #10946 - smb: remove double assign The same value is assigned the same value already a few lines above. Pointed out by PVS. Ref: #10929 Closes #10945 - transfer: skip extra assign The 'result' variable already contains CURLE_OK at this point, no use in setting it again. Pointed out by PVS. Ref: #10929 Closes #10944 - urlapi: skip a pointless assign It stores a null byte after already having confirmed there is a null byte there. Detected by PVS. Ref: #10929 Closes #10943 Philip Heiduck (13 Apr 2023) - GHA: suppress git clone output Closes #10939 Stefan Eissing (13 Apr 2023) - tests: make test_12_01 a bit more forgiving on connection counts - cf-socket: add socket recv buffering for most tcp cases - use bufq as recv buffer, also for Windows pre-receive handling - catch small reads followed by larger ones in a single socket call. A common pattern on TLS connections. Closes #10787 Daniel Stenberg (13 Apr 2023) - urlapi: cleanups - move host checks together - simplify the scheme parser loop and the end of host name parser - avoid itermediate buffer storing in multiple places - reduce scope for several variables - skip the Curl_dyn_tail() call for speed - detect IPv6 earlier and skip extra checks for such hosts - normalize directly in dynbuf instead of itermediate buffer - split out the IPv6 parser into its own funciton - call the IPv6 parser directly for ipv6 addresses - remove (unused) special treatment of % in host names - junkscan() once in the beginning instead of scattered - make junkscan return error code - remove unused query management from dedotdotify() - make Curl_parse_login_details use memchr - more use of memchr() instead of strchr() and less strlen() calls - make junkscan check and return the URL length An optimized build runs one of my benchmark URL parsing programs ~41% faster using this branch. (compared against the shipped 7.88.1 library in Debian) Closes #10935 Josh McCullough (13 Apr 2023) - http2: fix typo in infof() call Closes #10940 Daniel Stenberg (12 Apr 2023) - noproxy: pointer to local array 'hostip' is stored outside scope Ref: #10929 Closes #10933 Stefan Eissing (12 Apr 2023) - connect: fix https connection setup to treat ssl_mode correctly - for HTTPS protocol, a disabled ssl should never be acceptables. Closes #10934 Douglas R. Reno (12 Apr 2023) - CMakeLists.txt: fix typo for Haiku detection Closes #10937 Dan Fandrich (11 Apr 2023) - pathhelp: use the cached $use_cygpath when available - runtests: eliminate unneeded variable - runtests: make the # of server start attempts a constant - runtests: on startup failure call displaylogs only in serverfortest This reduces the number of calls spread throughout the code. Ref: #10818 Closes #10919 - runtests: return an error code with startservers() The code indicates the kind of failure encountered in starting a server, which can be used by the caller to tailor the user experience. Ref: #10818 - runtests: abort early if runpingpongserver is given a bad server type - runtests: don't use the SMB server verification time as reference %FTPTIME2 and %FTPTIME3 should be set by the FTP server only, for consistency. - tests: factor out the test server management code This now lives in servers.pm with some configuration variables moved to globalconfig.pm Ref: #10818 - runtests: remove an inappropriate use of runclientoutput This function is intended for running client code, not servers. - runtests: only add $LIBDIR to the path for checktestcmd Since checkcmd is for finding servers, there will never be anything in this directory of interest to them. Ref: #10818 - tests: log sshserver.pl messages to a file The logmsg messages were thrown away before, so they are now available for debugging. - runtests: also show DISABLED tests with -l Other reasons for skipping tests are ignored for -l, so being explicitly disabled should be too. - runtests: move the UNIX sockets into $PIDDIR These were missed when the other server files were moved there. Follow-up to 70d2fca2 Ref: #10818 - tests: tighten up perl exports This reduces namespace pollution a little. Ref: #10818 - tests: turn perl modules into full packages This helps enforce more modularization and encapsulation. Enable and fix warnings on a few packages. Also, rename ftp.pm to processhelp.pm since there's really nothing ftp-specific in it. Ref: #10818 Daniel Stenberg (11 Apr 2023) - multi: remove a few superfluous assigns PVS found these "The 'rc' variable was assigned the same value." cases. Ref: #10929 Closes #10932 - schannel: add clarifying comment Explaining how the PVS warning in #10929 is wrong: Dereferencing of the null pointer 'backend->cred' might take place. Closes #10931 - cookie: clarify that init with data set to NULL reads no file ... and make Curl_cookie_add() require 'data' being set proper with an assert. The function has not worked with a NULL data for quite some time so this just corrects the code and comment. This is a different take than the proposed fixed in #10927 Reported-by: Kvarec Lezki Ref: #10929 Closes #10930 Kvarec Lezki (11 Apr 2023) - vtls: remove int typecast for sizeof() V220 Suspicious sequence of types castings: memsize -> 32-bit integer -> memsize. The value being cast: 'sizeof (buf->data)'. curl\lib\vtls\vtls.c 2025 https://pvs-studio.com/en/docs/warnings/v220/ Closes #10928 Stefan Eissing (11 Apr 2023) - http2: fix copynpaste error reported by coverity - move all code handling HTTP/2 frames for a particular stream into a separate function to keep from confusing the call `data` with the stream `data`. Closes #10924 Dan Fandrich (11 Apr 2023) - tests: log a too-long Unix socket path in sws and socksd Ref: #10919 Daniel Stenberg (11 Apr 2023) - gen.pl: error on duplicated See-Also fields Updated http2.d accordingly. Closes #10925 - http2: avoid possible null pointer dereference Reported-by: Dan Fandrich Fixes #10920 Closes #10923 - lib1560: verify that more bad host names are rejected when setting the hostname component of a URL Closes #10922 - curl_url_set.3: mention that users can set content rather freely ... which then might render bad URLs if you extract a URL later. Closes #10921 Dan Fandrich (10 Apr 2023) - CI: retry failed downloads of aws-lc Don't fail the build in case of a temporary server problem. - test1169: fix so it works properly everywhere - Use an absolute path for the -L option since the module isn't in the perl path - Create the needed test file in a <file> section; <precheck> isn't intended for this - Fix the test number in the file name, which was wrong Follow-up to f754990a Ref: #10818 Fixes #10889 Closes #10917 - tests: stop using strndup(), which isn't portable It's not available on Solaris 10, for example. Since this is just test code that doesn't need to use an optimized system version, replace it with the implementation copied from tool_cb_hdr.c. - runtests: fix an incorrect comment about the ld_preload feature Follow-up to 1f631864 Ref: #10818 Daniel Stenberg (9 Apr 2023) - urlapi: prevent setting invalid schemes with *url_set() A typical mistake would be to try to set "https://" - including the separator - this is now rejected as that would then lead to url_get(... URL...) would get an invalid URL extracted. Extended test 1560 to verify. Closes #10911 Biswapriyo Nath (9 Apr 2023) - http2: remove unused Curl_http2_strerror function declaration Curl_http2_strerror was renamed to http2_strerror in 05b100aee247bb9bec8e9a1b0 and then http2_strerror was removed in 5808a0d0f5ea0399d4a2a2 This also fixes the following compiler error lib/http2.h:41:33: error: unknown type name 'uint32_t' lib/http2.h:1:1: note: 'uint32_t' is defined in header '<stdint.h>' Closes #10912 Daniel Stenberg (8 Apr 2023) - RELEASE-NOTES: synced SuperIlu on github (8 Apr 2023) - config-dos.h: fix SIZEOF_CURL_OFF_T for MS-DOS/DJGPP Fixes #10905 Closes #10910 Daniel Stenberg (8 Apr 2023) - lib: remove CURLX_NO_MEMORY_CALLBACKS The only user of this define was 'chkdecimalpoint' - a special purpose test tool that was built but not used anymore (since 17c18fbc3 - Apr 2020). Closes #10908 - CURLPROXY_HTTPS2: for HTTPS proxy that may speak HTTP/2 Setting this proxy type allows curl to negotiate and use HTTP/2 with HTTPS proxies. Closes #10900 Ali Khodkar (8 Apr 2023) - write-out.d: add missing periods Closes #10897 Daniel Stenberg (7 Apr 2023) - http2: remove check for !data after it was already dereferenced Pointed out by Coverity Closes #10906 - http_proxy: provide missing arg to infof() call Pointed out by Coverity Closes #10904 - content_encoding: only do tranfer-encoding compression if asked to To reduce surprises. Update test 387 and 418 accordingly. Closes #10899 - sws: comparison of unsigned expression < 0 is always false Follow-up to 356dd0b73a75ed6d5 Closes #10903 - lib/cmake: add HAVE_WRITABLE_ARGV check Assisted-by: Jakub Zakrzewski Closes #10896 - configure: don't set HAVE_WRITABLE_ARGV on Windows Ref: #10888 Closes #10896 - vtls: fix build error when proxy-disabled Closes #10901 Stefan Eissing (6 Apr 2023) - tests: increase sws timeout for more robust testing - for https CONNECT forwarding, this was fixed at 5 seconds which led to spurious CI test failures - add --keepalive parameter to sws to control this - let httpserver use 30 seconds Closes #10898 - http2: move HTTP/2 stream vars into local context - remove NGHTTP2 members of `struct HTTP` - add `void *h2_ctx` to `struct HTTP` - add `void *h3_ctx` to `struct HTTP` - separate h2/h3 pointers are needed for eyeballing - manage local stream_ctx in http implementations Closes #10877 - proxy: http2 proxy tunnel implementation - currently only on debug build and when env variable CURL_PROXY_TUNNEL_H2 is present. - will ALPN negotiate with the proxy server and switch tunnel filter based on the protocol negotiated. - http/1.1 tunnel code moved into cf-h1-proxy.[ch] - http/2 tunnel code implemented in cf-h2-proxy.[ch] - tunnel start and ALPN set remains in http_proxy.c - moving all haproxy related code into cf-haproxy.[ch] VTLS changes - SSL filters rely solely on the "alpn" specification they are created with and no longer check conn->bits.tls_enable_alpn. - checks on which ALPN specification to use (or none at all) are done in vtls.c when creating the filter. Testing - added a nghttpx forward proxy to the pytest setup that speaks HTTP/2 and forwards all requests to the Apache httpd forward proxy server. - extending test coverage in test_10 cases - adding proxy tests for direct/tunnel h1/h2 use of basic auth. - adding test for http/1.1 and h2 proxy tunneling to pytest Closes #10780 - vtls and h2 improvements - eliminate receive loop in vtls to fill buffer. This may lead to partial reads of data which is counter productive - let http2 instead loop smarter to process pending network data without transfer switches scorecard improvements - do not start caddy when only httpd is requested - allow curl -v to stderr file on --curl-verbose Closes #10891 Daniel Stenberg (6 Apr 2023) - tests: 1078 1288 1297 use valid IPv4 addresses With the enhanced URL parser, these tests failed because of their bad IPv4 use. - urlapi: detect and error on illegal IPv4 addresses Using bad numbers in an IPv4 numerical address now returns CURLUE_BAD_HOSTNAME. I noticed while working on trurl and it was originally reported here: https://github.com/curl/trurl/issues/78 Updated test 1560 accordingly. Closes #10894 - RELEASE-NOTES: synced - urlapi: URL encoding for the URL missed the fragment Meaning that it would wrongly still store the fragment using spaces instead of %20 if allowing space while also asking for URL encoding. Discovered when playing with trurl. Added test to lib1560 to verify the fix. Closes #10887 - rtsp: convert mallocs to dynbuf for RTP buffering Closes #10786 - tool_writeout: add URL component variables Output specific components from the used URL. The following variables are added for this purpose: url.scheme, url.user, url.password, url.options, url.host, url.port, url.path, url.query, url.fragment, url.zoneid Add the following for outputting parts of the "effective URL": urle.scheme, urle.user, urle.password, urle.options, urle.host, urle.port, urle.path, urle.query, urle.fragment, urle.zoneid Added test 423 and 424 to verify. Closes #10853 Stefan Eissing (4 Apr 2023) - tests/http: improved httpd detection - better error messages when not found/complete - handling of `--without-test-httpd` Reported-by: kwind on github Fixes #10879 Closes #10883 Daniel Stenberg (4 Apr 2023) - configure: make quiche require quiche_conn_send_ack_eliciting curl now requires quiche version >= 1.17.1 to be used and this function was added in this version and makes a convenient check. This requirement is because this is the lowest quiche version that supports peer-initiated key updates correctly. Closes #10886 Dan Fandrich (1 Apr 2023) - unit tests: use the unit test infrastructure better Allow UNITTEST_STOP to return the error code, use the fail & abort macros to indicate test failure and return success instead of fail if the unit test can't test anything because of missing features at compile-time. A couple of tests could never fail because they were overriding the failure return code. - runtests: strip EOL on precheck output on Windows, too Precheck failures would show on two lines in the test summary output otherwise. - tests: move server config files under the pid dir These files are generated by the test servers and must therefore be found in the log directory to make them available to only those servers once multiple test runners are executing in parallel. They must also not be deleted with the log files, so they are stored in the pidfile directory. Ref: #10818 Closes #10875 - runtests: use the ssh key filenames from the sshhelp package - tests: move pidfiles and portfiles under the log directory This is to segregate all files written by a test process into a single root to allow for future parallel testing. Ref: #10818 Closes #10874 - runtests: minor code cleanups - runtests: call processexists() and pidfromfile() rather than duplicating the logic in several places. Viktor Szakats (31 Mar 2023) - cmake: do not add zlib headers for openssl Logic copied earlier from wolfSSL. wolfSSL requires zlib headers for its public headers. OpenSSL does not, so stop adding zlib headers for it. Follow-up to 1e3319a167d2f32d295603167486e9e88af9bb4e Closes #10878 Stefan Eissing (31 Mar 2023) - rustls: fix error in recv handling - when rustls is told to recieve more TLS data and its internal plaintext buffers are full, it returns an IOERROR - avoid receiving TLS data while plaintext is not read empty pytest: - increase curl run timeout when invoking pytest with higher verbosity Closes #10876 - http3: improvements across backends - ngtcp2: using bufq for recv stream data - internal stream_ctx instead of `struct HTTP` members for quiche, ngtcp2 and msh3 - no more QUIC related members in `struct HTTP` - experimental use of recvmmsg(), disabled by default - testing on my old debian box shows no throughput improvements. - leaving it in, but disabled, for future revisit - vquic: common UDP receive code for ngtcp2 and quiche - vquic: common UDP send code for ngtcp2 and quiche - added pytest skips for known msh3 failures - fix unit2601 to survive torture testing - quiche: using latest `master` from quiche and enabling large download tests, now that key change is supported - fixing test_07_21 where retry handling of starting a stream was faulty - msh3: use bufq for recv buffering headers and data - msh3: replace fprintf debug logging with LOG_CF where possible - msh3: force QUIC expire timers on recv/send to have more than 1 request per second served Closes #10772 Dan Fandrich (30 Mar 2023) - test1471/2: add http as a required feature curl bails out early with a different error message if http support is compiled out. Ref: #10705 - tests: limit return code of unit tests and lib tests Values greater than 125 have special meanings, so cap it there. Unit tests and lib tests use the number of failures as the return code, so a large number of failures (such as test 2601 as a torture test) can exceed this causing the test to be erroneously reported as having failed. Ref: #10720 - test1960: point to the correct path for the precheck tool Otherwise, it might find the binary in .libs which can cause it to use the system libcurl which can fail. This error is only visible by noticing that the test is skipped. Follow-up to e4dfe6fc Ref: #10651 - tests: use the proper %LOGDIR path on two tests Follow-up to e7a021e1 Ref: #10818 Daniel Stenberg (30 Mar 2023) - rtsp: fix Value stored to 'skip_size' is never read Pointed out by scan-build Follow-up to 6c6306f3008f2c9b20a64 Closes #10872 Stefan Eissing (30 Mar 2023) - tests/http: relax connection check in test_07_02 Only 1 connection will be used when curl is slow, happens when address-sanitized in CI, for example Closes #10865 - http2: flow control and buffer improvements - use bufq for send/receive of network data - usd bufq for send/receive of stream data - use HTTP/2 flow control with no-auto updates to control the amount of data we are buffering for a stream HTTP/2 stream window set to 128K after local tests, defined code constant for now - elminiating PAUSEing nghttp2 processing when receiving data since a stream can now take in all DATA nghttp2 forwards Improved scorecard and adjuste http2 stream window sizes - scorecard improved output formatting and options default - scorecard now also benchmarks small requests / second Closes #10771 Dan Fandrich (30 Mar 2023) - runtests: show error message if file can't be written - tests: fix remaining servers to run with a dynamic log directory This final commit in the series is sufficient to allow the tests succeed if $LOGDIR is changed in runtests.pl. Ref: #10818 Closes #10866 - tests: fix fake_ntlm to run with a dynamic log directory Ref: #10818 - tests: fix http servers to run with a dynamic log directory Ref: #10818 - tests: fix ftpserver to run with a dynamic log directory Ref: #10818 - tests: fix C servers to run with a dynamic log directory Ref: #10818 - tests: fix lib tests to run with a dynamic log directory Ref: #10818 - tests: fix unit tests to run with a dynamic log directory Ref: #10818 - tests: use %LOGDIR to refer to the log directory This will allow it be set dynamically. Ref: #10818 - runtests: track verification time even if no files to compare - getpart: better handle case of file not found - testcurl: bump version date It hadn't been updated in 9 years; it's time. - tests: switch to 3-argument open in test suite The perl 2-argument open has been considered not-quite-deprecated since the 3-argument form was introduced almost a quarter century ago. - tests: silence some Perl::Critic warnings in test suite Not all warnings are fixed; many are as much stylistic suggestions than anything and IMHO don't do much to actually improve the code. Ref: #10818 Closes #10861 - docs: bump the minimum perl version to 5.6 It's actually been this way since at least 2012 (when a 3-argument open was added to runtests.pl). Given the lack of complaints in the interim, it's safe to call this 23 year old perl version the minimum. - runtests: memoize the getpart* subroutines to speed up access The refactored code calls these functions with the same arguments more often, so this prevents redundant test case file parsing. Approved-by: Daniel Stenberg Ref: #10818 Closes #10833 - runtests: remove duplicated feature variables Use the feature map stored in the hash table instead. Most of the variables were only used only once, to set the value in the hash table. Ref: #10818 - runtests: also ignore test file problems when ignoring results This simplifies error handling in the test verification code and makes it more consistent. Ref: #10818 - runtests: more refactoring for clarity Ref: #10818 - runtests: don't start servers if -l is given - runtests: fix typos - runtests: refactor singletest() into separate functions This takes it from a 1200 line behemoth into something more manageable. The content and order of the functions is taken almost directly from singletest() so the diff sans whitespace is quite short. Ref: #10818 - runtests: refactor singletest() into distinct sections Namely: - Verify that this test case should be run - Start the servers needed to run this test case - Check that test environment is fine to run this test case - Prepare the test environment to run this test case - Run the test command - Clean up after test command - Verify test succeeded Ref: #10818 - runtests: stop copying a few arrays where not needed Unlike some other languages that just copy a pointer, perl copies the entire array contents which takes time for a large array. Ref: #10818 - runtests: reduce redundant calls to getpart/getpartattr These functions scan through the entire test file every time to find the right section, so they can be slow for large test files. Ref: #10818 - tests: document that the unittest keyword is special Also, add other features that were missing. Stefan Eissing (30 Mar 2023) - docs: add documentation for bufq Closes #10869 Daniel Stenberg (30 Mar 2023) - RELEASE-NOTES: synced Matt Jolly (30 Mar 2023) - hostip: refuse to resolve the .onion TLD RFC 7686 states that: > Applications that do not implement the Tor > protocol SHOULD generate an error upon the use of .onion and > SHOULD NOT perform a DNS lookup. Let's do that. https://www.rfc-editor.org/rfc/rfc7686#section-2 Add test 1471 and 1472 to verify Fixes #543 Closes #10705 Philip Heiduck (30 Mar 2023) - GHA: update ngtcp2-*.yml to v0.10.0 Closes #10612 Stefan Eissing (30 Mar 2023) - tests/http: fix log formatting on wrong exit code Closes #10868 Daniel Stenberg (30 Mar 2023) - spellcheck.words: unify the AWS-LC spelling Follow-up to 34ef4fab22d93 Closes #10867 Jim King (30 Mar 2023) - openssl: interop with AWS-LC * Configure changes to detect AWS-LC * CMakeLists.txt changes to detect AWS-LC * Compile-time branches needed to support AWS-LC * Correctly set OSSL_VERSION and report AWS-LC release number * GitHub Actions script to build with autoconf and cmake against AWS-LC AWS-LC is a BoringSSL/OpenSSL derivative For more information see https://github.com/awslabs/aws-lc/ Closes #10320 Viktor Szakats (30 Mar 2023) - cmake: picky-linker fixes for openssl, ZLIB, H3 and more - fix HTTP/3 support detection with OpenSSL/quictls built with ZLIB. (Requires curl be built with ZLIB option also.) - fix HTTP/3 support detection with OpenSSL/quictls/LibreSSL and `ld` linker on Windows. - fix HTTP/3 support detection with wolfSSL to automatically add `ws2_32` to the lib list on Windows. For all linkers. - reposition ZLIB (and other compression) detection _after_ TLS detection, but before calling HTTP/3-support detection via `CheckQuicSupportInOpenSSL`. May be a regression from ebef55a61df0094b9790710a42f63c48e7de3c13 May fix #10832 (Reported-by: Micah Snyder) This also seems to fix an odd case, where OpenSSL/quictls is correctly detected, but its header path is not set while compiling, breaking build at `src/curl_ntlm_core.c`. Reason for this remains undiscovered. - satisfy "picky" linkers such as `ld` with MinGW, that are highly sensitive to lib order, by also adding brotli to the beginning of the lib list. - satisfy "picky" linkers by adding certain Windows systems libs to the lib list for OpenSSL/LibreSSL. (Might need additional ones for other forks, such as `pthread` for BoringSSL.) Note: It'd make sense to _always_ add `ws2_32`, `crypt32` (except Windows App targets perhaps?), `bcrypt` (except old-mingw!) on Windows at this point. They are almost always required, and if some aren't, they are ignored by the linker with no effect on final binaries. Closes #10857 Stefan Eissing (30 Mar 2023) - vlts: use full buffer size when receiving data if possible SSL backends like OpenSSL/wolfSSL and other return the content of one TLS record on read, but usually there are more available. Change the vtls cfilter recv() function to fill the given buffer until a read would block. Closes #10736 dengjfzh on github (30 Mar 2023) - rtsp: skip malformed RTSP interleaved frame data Some IP cameras send malformed RTSP interleaved frames sometimes, which can cause curl_easy_perform return 1 (CURLE_UNSUPPORTED_PROTOCOL). This change attempts to skip clearly incorrect RTSP interleaving frame data. Closes #10808 Stefan Eissing (30 Mar 2023) - lib: add `bufq` and `dynhds` Adding `bufq`: - at init() time configured to hold up to `n` chunks of `m` bytes each. - various methods for reading from and writing to it. - `peek` support to get access to buffered data without copy - `pass` support to allow buffer flushing on write if it becomes full - use case: IO buffers for dynamic reads and writes that do not blow up - distinct from `dynbuf` in that: - it maintains a read position - writes on a full bufq return CURLE_AGAIN instead of nuking itself - Init options: - SOFT_LIMIT: allow writes into a full bufq - NO_SPARES: free empty chunks right away - a `bufc_pool` that can keep a number of spare chunks to be shared between different `bufq` instances Adding `dynhds`: - a straightforward list of name+value pairs as used for HTTP headers - headers can be appended dynamically - headers can be removed again - headers can be replaced - headers can be looked up - http/1.1 formatting into a `dynbuf` - configured at init() with limits on header counts and total string sizes - use case: pass a HTTP request or response around without being version specific - express a HTTP request without a curl easy handle (used in h2 proxy tunnels) - future extension possibilities: - conversions of `dynhds` to nghttp2/nghttp3 name+value arrays Closes #10720 - pytest: improvements for suitable curl and error output - will check built curl for http and https support and skip all tests if not there - will dump stdout/stderr/trace output on errored responses Closes #10829 Daniel Stenberg (29 Mar 2023) - lib: use correct printf flags for sockets and timediffs Introduces CURL_FORMAT_SOCKET_T for outputting socket numbers. Fixes #10737 Reported-by: Gisle Vanem Closes #10855 - telnet: make MSVC ignore warning for assignment within conditional Follow-up to d92a5007b60e0af7d Closes #10859 - ws: handle reads before EAGAIN better Reported-by: simplerobot on github Fixes #10831 Closes #10856 - test1592: add flaky keyword Closes #10860 Frank Gevaerts (28 Mar 2023) - lib/sha256.c: typo fix in comment (duplicated "is available") Closes #10851 Arne Soete (28 Mar 2023) - tests: update tests/httpd references to tests/http tests/httpd was renamed to tests/http in #10654. This patch updates some references in the README Closes #10854 Kamil Dudka (28 Mar 2023) - telnet: simplify the implementation of str_is_nonascii() There is no need to traverse the string twice. Closes #10852 Frank Gevaerts (28 Mar 2023) - curl_easy_getinfo.3: typo fix (duplicated "from the") Closes #10850 Philip Heiduck (28 Mar 2023) - wolfssl.yml: bump to version 5.6.0 Closes #10843 Daniel Stenberg (28 Mar 2023) - RELEASE-NOTES: synced Ronan Pigott (28 Mar 2023) - docs/cmdline-opts: document the dotless config path The real xdg config path is $XDG_CONFIG_HOME/curlrc, without the dot. The dotless name seems preferable, so let's match the documentation to the behavior. Closes #10849 Daniel Stenberg (28 Mar 2023) - HTTP-COOKIES.md: mention the #HttpOnly_ prefix Fixes #10847 Reported-by: Harry Sintonen Closes #10848 - dynbuf: never allocate larger than "toobig" As dynbufs always have a fixed maximum size which they are not allowed to grow larger than, making sure that it never allocates a larger buffer makes sure the buffer does not allocate memory that will never be used. Closes #10845 - ftplistparser: replace realloc with dynbuf Closes #10844 - ftplistparser: use ISDIGIT() Closes #10844 - ftplistparser: move out private data from public struct The public 'curl_fileinfo' struct contained three fields that are for internal purposes only. This change makes them unused in the public struct. The new private struct fields are also renamed to make this separation more obvious internally. Closes #10844 - openssl: fix indents - white space edits only Closes #10840 - url: remove call to Curl_llist_destroy in Curl_close A list that is created with a NULL "destructor" does not need to be destroyed. Not calling it is faster than calling it. Closes #10846 - multi: remove PENDING + MSGSENT handles from the main linked list As they are not driving transfers or any socket activity, the main loop does not need to iterate over these handles. A performance improvement. They are instead only held in their own separate lists. 'data->multi' is kept a pointer to the multi handle as long as the easy handle is actually part of it even when the handle is moved to the pending/msgsent lists. It needs to know which multi handle it belongs to, if for example curl_easy_cleanup() is called before the handle is removed from the multi handle. Alll 'data->multi' pointers of handles still part of the multi handle gets cleared by curl_multi_cleanup() which "orphans" all previously attached easy handles. This is take 2. The first version was reverted for the 8.0.1 release. Assisted-by: Stefan Eissing Closes #10801 Stefan Eissing (26 Mar 2023) - tests/http: add timeout to running curl in test cases - we had a CI case once where `curl` seemingly did not return and it was hard to guess what happened. - make curl execution in test cases time out after 60 seconds Closes #10783 Daniel Stenberg (26 Mar 2023) - RELEASE-PROCEDURE: update to new schedule Ref: https://curl.se/mail/lib-2023-03/0062.html Assisted-by: Andy Alt Assisted-by: Dan Frandrich Closes #10827 Patrick Monnerat (26 Mar 2023) - doc: curl_mime_init() strong easy handle binding has been relaxed in 7.87.0 Reported-by: Chloe Kudryavtsev Fixes #10834 Closes #10835 Jay Satiro (25 Mar 2023) - CURLOPT_WRITEFUNCTION.3: fix typo Reported-by: Osaila@users.noreply.github.com Fixes https://github.com/curl/curl/issues/10839 Dan Fandrich (24 Mar 2023) - CI: skip some more builds when possible When a commit only contains tests, documentation, or cmake files, skip those builds that aren't affected by those. The file filters available on the CI services don't seem to allow skipping individual jobs, only the entire workflow, so we can't get any more fine-grained than this. - CI: add and adjust labeler match patterns Allow cmdline tool alongside other labels. Kai Pastor (25 Mar 2023) - CMake: make config version 8 compatible with 7 Reviewed-by: Jakub Zakrzewski Closes #10819 Daniel Stenberg (24 Mar 2023) - RELEASE-NOTES: synced Bumped version-in-progress to 8.1.0 - GHA: add a memory-sanitizer job Closes #10815 Dan Fandrich (23 Mar 2023) - CI: fix brew retries on GHA The fix in the previous commit was complete for Cirrus but accidentally left off a part for GHA. Follow-up to c2b7249d - CI: skip Azure for more commits which change only GHA Daniel Stenberg (23 Mar 2023) - cmake: set SONAME for SunOS too Provided-by: Brian Lund Closes #10816 Stefan Eissing (23 Mar 2023) - ngtcp2: adjust config and code checks for ngtcp2 without nghttp3 - make configure show on HTTP3 feature that both ngtcp2 and nghttp3 are in play - define ENABLE_QUIC only when USE_NGTCP2 and USE_NGHTTP3 are defined - add USE_NGHTTP3 in the ngtcp2 implementation Fixes #10793 Closes #10821 Daniel Stenberg (23 Mar 2023) - data.d: emphasize no conversion When asking curl to send a POST, curl does not encode or change the data. Ref: #10820 Closes #10823 - server/getpart: clear the buffer before load Fixes msan warnings: ==54195==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x55ece35e57cb in line_length /home/runner/work/curl/curl/tests/server /getpart.c:111:25 #1 0x55ece35e3b83 in readline /home/runner/work/curl/curl/tests/server/ge tpart.c:164:24 #2 0x55ece35e0269 in getpart /home/runner/work/curl/curl/tests/server/get part.c:347:18 #3 0x55ece36180b6 in parse_servercmd /home/runner/work/curl/curl/tests/se rver/sws.c:283:13 Closes #10822 - ntlm: clear lm and nt response buffers before use To avoid the risk of MemorySanitizer: use-of-uninitialized-value Closes #10814 - digest: clear target buffer Closes #10814 Douglas R. Reno (22 Mar 2023) - cmake: bring in the network library on Haiku. When cross-compiling for Haiku, the networking library needs to be brought in. Without this, an unknown type of "Error" is reported in lib/curl_setup_once.h. This is also needed when using CMake natively on Haiku to build libcurl. Fixes #10296 Closes #10792 Daniel Stenberg (22 Mar 2023) - runtests: die if curl version can be found Closes #10813 Stefan Eissing (22 Mar 2023) - multi: add handle asserts in DEBUG builds For GOOD_EASY_HANDLE and GOOD_MULTI_HANDLE checks - allow NULL pointers to "just" return an error as before - fail hard on nun-NULL pointers that no longer show the MAGICs Closes #10812 Jon Rumsey (22 Mar 2023) - gskit: various compile errors in OS400 Various compile failures in gskit.c; - pipe_ssloverssl() needs Curl_easy data parameter for Curl_conn_cf_get_socket(cf, data) - key_passwd is in ssl_config, not conn_config - close_on() has 2 parameters, not 4 - getsockopt() needs to call Curl_conn_cf_get_socket(), not cxn->sock[FIRSTSOCKET] Fixes #10799 Closes #10800 Daniel Stenberg (22 Mar 2023) - tool_operate: pass a long as CURLOPT_HEADEROPT argument Closes #10798 - GHA: run all linux test jobs with valgrind Closes #10798 - GHA-linux: add an address-sanitizer build Closes #10810 Version 8.0.1 (20 Mar 2023) Daniel Stenberg (20 Mar 2023) - RELEASE-NOTES: synced curl 8.0.1 - Revert "multi: remove PENDING + MSGSENT handles from the main linked list" This reverts commit f6d6f3ce01e377932f1ce7c24ee34d45a36950b8. The commits caused issues in the 8.0.0 release. Needs a retake. Reported-by: Kamil Dudka Closes #10795 - include/curl/curlver.h: bump to 8.0.1 Version 8.0.0 (20 Mar 2023) Daniel Stenberg (20 Mar 2023) - RELEASE-NOTES: synced The curl 8.0.0 release - THANKS: from the 8.0.0 release - scripts/delta: fix "ambiguous argument" when used in branches - SECURITY-PROCESS.md: Busy-loops are not security problems Closes #10790 Stefan Eissing (17 Mar 2023) - tests/http: do not save files for downloads in scorecard testing Closes #10788 Daniel Stenberg (17 Mar 2023) - cf-socket: use port 80 when resolving name for local bind It turns out c-ares returns an error when asked to resolve a host name with ares_getaddrinfo using port number 0. Reported as a c-ares bug here: https://github.com/c-ares/c-ares/issues/517 The work-around is to simply use port 80 instead, as the number typically doe s not make a difference and a non-zero number works for c-ares. Fixes #10759 Reported-by: Matt Jolly Closes #10789 - curl.h: require gcc 12.1 for the deprecation magic Reported-by: kchow-FTNT on github Fixes #10726 Closes #10784 - Revert "rtsp: use dynbuf instead of custom reallocs" This reverts commit 1b9ea3239d22147e00d8 because of OSS-fuzz reports. I'll do another take after the pending release. Closes #10785 - test422: verify --next used without a prior URL Closes #10782 - tool_getparam: error if --next is used without a prior URL Reported-by: 積丹尼 Dan Jacobson Ref: https://github.com/curl/curl/pull/10769#discussion_r1137895629 Closes #10782 - libssh: use dynbuf instead of realloc When building lines to show for SFTP directory listings. Closes #10778 - lib2305: deal with CURLE_AGAIN The test does a slightly ugly busy-loop for this case but should be managable due to it likely being a very short moment. Mention CURLE_AGAIN in curl_ws_recv.3 Fixes #10760 Reported-by: Jay Satiro Closes #10781 - rtsp: use dynbuf instead of custom reallocs For the RTP buffering. Closes #10776 - libssh2: remove unused variable from libssh2's struct Closes #10777 - RELEASE-NOTES: synced - multi: remove PENDING + MSGSENT handles from the main linked list As they are not driving transfers or any socket activity, the main loop does not need to iterate over these handles. A performance improvement. They are instead only held in their own separate lists. Assisted-by: Stefan Eissing Ref: #10743 Closes #10762 - multi: turn link/unlinking easy handles into dedicated functions - http_aws_sigv4: fix scan-build "value stored to 'ret' is never read" Follow-up to 495d09810aa9a Closes #10766 - lib: skip Curl_llist_destroy calls Linked lists themselves do not carry any allocations, so for the lists that do not have have a set destructor we can just skip the Curl_llist_destroy() call and save CPU time. Closes #10764 - lib643: LIB644 is never defined, this is dead code Closes #10765 - libtest/Makefile.inc: remove superfluous variables Rely on the defaults when possible. Closes #10765 - tests/http: remove year ranges from copyrights Closes #10763 Casey Bodley (14 Mar 2023) - aws_sigv4: fall back to UNSIGNED-PAYLOAD for sign_as_s3 all s3 requests default to UNSIGNED-PAYLOAD and add the required x-amz-content-sha256 header. this allows CURLAUTH_AWS_SIGV4 to correctly sign s3 requests to amazon with no additional configuration Signed-off-by: Casey Bodley <cbodley@redhat.com> Closes #9995 Viktor Szakats (14 Mar 2023) - wolfssl: add quic/ngtcp2 detection in cmake, and fix builds - add QUIC/ngtcp2 detection in CMake with wolfSSL. Because wolfSSL uses zlib if available, move compression detection before TLS detection. (OpenSSL might also need this in the future.) - wolfSSL 5.5.0 started using C99 types in its `quic.h` header, but it doesn't #include the necessary C99 header itself, breaking builds (unless another dependency pulled it by chance.) Add local workaround for it. For this to work with all build tools, we had to fix our header detection first. Ref: #10745 Ref: https://github.com/curl/curl-for-win/commit/6ad5f6ecc15620c15625fc4434 76b3a1ecef4f3f Closes #10739 Stefan Eissing (14 Mar 2023) - secure-transport: fix recv return code handling Return code handling of recv calls were not always correct when an error occured or the connection was closed. Closes #10717 - http2: Use KEEP_SEND_HOLD for flow control in HTTP/2 - use the defined, but so far not used, KEEP_SEND_HOLD bit for flow control based suspend of sending in transfers. Prior to this change KEEP_SEND_PAUSE bit was used instead, but that can interfere with pausing streams from the user side via curl_easy_pause. Fixes https://github.com/curl/curl/issues/10751 Closes https://github.com/curl/curl/pull/10753 Dan Fandrich (13 Mar 2023) - tests: fix control code that hid some text in runtests.1 - tests: sync option lists in runtests.pl & its man page Daniel Stenberg (13 Mar 2023) - multi: make multi_perform ignore/unignore signals less often For improved performance Reported-by: Jerome St-Louis Ref: #10743 Closes #10750 Viktor Szakats (13 Mar 2023) - cmake: delete unused HAVE__STRTOI64 Also delete obsolete surrounding comments. Reviewed-by: Daniel Stenberg Closes #10756 - CI: fix copyright header Follow-up to 395b9175b7422d699fa93643973295c106cdf147 Daniel Stenberg (13 Mar 2023) - RELEASE-PROCEDURE.md: update coming release dates Stefan Eissing (13 Mar 2023) - tests/http: add pytest to GHA and improve tests - added to: ngtcp2-quictls, ngtcp2-gnutls and the linux varians quiche, bearssl, libressl, mbedtls, openssl3, rustls - added disabled in ngtcp2-wolfssl due to weird SSL_connect() errors not reproducable locally Improvements on pytest: - handling of systems with nghttpx in $PATH - configure will seach $PATH got nghttpx used in pytest - pytest fixes for managing nghttpx without h3 support - ngtcp2-wolfssl: use a fully enabled wolfssl build - lower parallel count for http/1.1 tests, since we do not want to test excessive connections. - check built curl for HTTPS-proxy support in proxy tests - bearssl does not like one of our critical cert extensions, making it non-critical now - bearssl is too slow for test_12, skipping - making sure we do h3 tests only when curl and server support is there Closes #10699 Marcel Raad (13 Mar 2023) - tool_operate: silence unused parameter warning `global` is only used in the `my_setopt` macro version without `CURL_DISABLE_LIBCURL_OPTION` since commit 4774decf10a. Closes https://github.com/curl/curl/pull/10752 Viktor Szakats (13 Mar 2023) - build: fix stdint/inttypes detection with non-autotools Fix `stdint.h` and `inttypes.h` detection with non-autotools builds on Windows. (autotools already auto-detected them accurately.) `lib/config-win32.h` builds (e.g. `Makefile.mk`): - set `HAVE_STDINT_H` where supported. - set `HAVE_INTTYPES_H` for MinGW. CMake: - auto-detect them on Windows. (They were both force-disabled.) - delete unused `CURL_PULL_STDINT_H`. - delete unused `CURL_PULL_INTTYPES_H`. - stop detecting `HAVE_STDINT_H` twice. Present since the initial CMake commit: 4c5307b45655ba75ab066564afdc0c111a8 b9291 curl doesn't use these C99 headers, we need them now to workaround broken wolfSSL builds. Ref: #10739 Once that clears up, we can delete these detections and macros (unless we want to keep them for future us.) Reviewed-by: Daniel Stenberg Closes #10745 Daniel Stenberg (13 Mar 2023) - RELEASE-NOTES: synced - ftp: add more conditions for connection reuse Reported-by: Harry Sintonen Closes #10730 Dan Fandrich (12 Mar 2023) - tests: make first.c the same for both lib tests and unit tests The only difference used to be global variable used in unittest tests. After cb7ed5a removed individual flag overrides for the unittests, first.c was no longer recompiled for unit tests to include the flag, so whether it worked or gave a link error depended on whether it was compiled in libtest or unittest first. This way also speeds up the build by eliminating 40 identical compile invocations. Fixes #10749 - tests: use AM_CPPFILES to modify flags in unit tests Using CPPFLAGS sometimes caused odd compile issues when building tests with parallel make and AM_CPPFILES is the right flag, anyway. Follow-up to cb7ed5a Ref #10749 Viktor Szakats (13 Mar 2023) - Makefile.mk: fix -g option in debug mode [ci skip] Add it to `CFLAGS` (was: `LDFLAGS`). Closes #10747 Jay Satiro (12 Mar 2023) - tool: improve --stderr handling - freopen stderr with the user-specified file (--stderr file) instead of using a separate 'errors' stream. - In tool_setup.h override stdio.h's stderr macro as global variable tool_stderr. Both freopen and overriding the stderr macro are necessary because if the user-specified filename is "-" then stdout is assigned to tool_stderr and no freopen takes place. See the PR for more information. Ref: https://github.com/curl/curl/issues/10491 Closes https://github.com/curl/curl/pull/10673 Dan Fandrich (11 Mar 2023) - CI: don't run CI jobs if only another CI was changed Also skip builds on non-Windows platforms when only Windows build files have changed. This should reduce the number of useless builds and the associated waiting time and chance of spurious failures, freeing resources for new PRs. Closes #10742 - http: don't send 100-continue for short PUT requests This is already how curl is documented to behave in Everything curl, but in actuality only short POSTs skip this. This should knock 30 seconds off a full run of the test suite since the 100-continue timeout will no longer be hit. Closes #10740 - tests: add DELAY keyword to more tests using waits - tests: hack to build most unit tests under cmake These are only built when a libcurl static library is available, since we're not building a special libcurlu library yet and these tests rely on private symbols that aren't available in the shared library. A few unit tests do require libcurlu, so those are not built. Closes #10722 - tests: fix MSVC unreachable code warnings in unit tests Switch unit1654 to use the proper test macros as well. - tests: make CPPFLAGS common to all unit tests There's no need to specify them individually. - tests: keep cmake unit tests names in sync Put only the test names into Makefile.inc so they can be used by both cmake and automake. This will prevent the list of tests from becoming out of date when they are also built under cmake. Viktor Szakats (11 Mar 2023) - src: silence wmain() warning for all build methods llvm/clang and gcc doesn't recognize the wmain() function in Unicode Windows builds: llvm/clang: ``` ../../src/tool_main.c:239:5: warning: no previous prototype for function 'wma in' [-Wmissing-prototypes] int wmain(int argc, wchar_t *argv[]) ^ 1 warning generated. ``` gcc: ``` ../../src/tool_main.c:239:5: warning: no previous prototype for 'wmain' [-Wmi ssing-prototypes] 239 | int wmain(int argc, wchar_t *argv[]) | ^~~~~ ``` Before this patch, we already silenced it with CMake. This patch moves the silencing to the source, so that it applies to all build tools. Bug: https://github.com/curl/curl/issues/7229#issuecomment-1464806651 Reviewed-by: Marcel Raad Closes #10744 Dan Fandrich (10 Mar 2023) - CI: fix retrying on brew failures The previous attempt didn't consider that the shell would exit immediately after the false statement in the retry case. Follow-up to dc141a37 Stefan Eissing (10 Mar 2023) - http2: fix error handling during parallel operations RST and connection close were not handled correctly during parallel transfers, leading to aborted response bodies being reported complete. Closes #10715 Daniel Stenberg (10 Mar 2023) - url: only reuse connections with same GSS delegation Reported-by: Harry Sintonen Closes #10731 Viktor Szakats (10 Mar 2023) - lib: silence clang/gcc -Wvla warnings in brotli headers brotli v1.0.0 throughout current latest v1.0.9 and latest master [1] trigger this warning. It happened with CMake and GNU Make. autotools builds avoid it with the `convert -I options to -isystem` macro. llvm/clang: ``` In file included from ./curl/lib/content_encoding.c:36: ./brotli/x64-ucrt/usr/include/brotli/decode.h:204:34: warning: variable lengt h array used [-Wvla] const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ./brotli/x64-ucrt/usr/include/brotli/port.h:253:34: note: expanded from macro 'BROTLI_ARRAY_PARAM' ^~~~~~ In file included from ./curl/lib/content_encoding.c:36: ./brotli/x64-ucrt/usr/include/brotli/decode.h:206:48: warning: variable lengt h array used [-Wvla] uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]); ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~ ./brotli/x64-ucrt/usr/include/brotli/port.h:253:35: note: expanded from macro 'BROTLI_ARRAY_PARAM' ~^~~~~ ``` gcc: ``` In file included from ./curl/lib/content_encoding.c:36: ./brotli/x64-ucrt/usr/include/brotli/decode.h:204:5: warning: ISO C90 forbids variable length array 'encoded_buffer' [-Wvla] 204 | const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], | ^~~~~ ./brotli/x64-ucrt/usr/include/brotli/decode.h:206:5: warning: ISO C90 forbids variable length array 'decoded_buffer' [-Wvla] 206 | uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]); | ^~~~~~~ ``` [1] https://github.com/google/brotli/commit/ed1995b6bda19244070ab5d331111f16f 67c8054 Reviewed-by: Daniel Stenberg Reviewed-by: Marcel Raad Closes #10738 Daniel Stenberg (10 Mar 2023) - curl_path: create the new path with dynbuf Closes #10729 - url: remove dummy protocol handler Just two added checks were needed saves a whole handler struct. Closes #10727 Dan Fandrich (10 Mar 2023) - CI: retry a failed brew update too, not just brew install Also, make sure an eventual failure ends up returning a failure code so the job stops. Daniel Stenberg (10 Mar 2023) - url: fix the SSH connection reuse check Reported-by: Harry Sintonen Closes #10735 - CURLOPT_PROXY.3: curl+NSS does not handle HTTPS over unix domain socket It results in error "NSS error -5985 (PR_ADDRESS_NOT_SUPPORTED_ERROR)" Disabled test 1470 for NSS builds and documented the restriction. Reported-by: Dan Fandrich Fixes #10723 Closes #10734 - CURLSHOPT_SHARE.3: HSTS sharing is not thread-safe Reported-by: Hiroki Kurosawa Closes #10732 - telnet: only accept option arguments in ascii To avoid embedded telnet negotiation commands etc. Reported-by: Harry Sintonen Closes #10728 - test1903: test use of COOKIEFILE - reset - COOKIEFILE This also tests for the memory leak bug fixed by parent commit b559ef6f. Ref: #10694 Closes https://github.com/curl/curl/pull/10712 Jay Satiro (10 Mar 2023) - url: fix cookielist memleak when curl_easy_reset - Free set.cookelist in Curl_freeset instead of Curl_close. Prior to this change the cookielist linked list wasn't freed by curl_easy_reset which calls Curl_freeset to free all set. Bug: https://github.com/curl/curl/issues/10694#issuecomment-1458619157 Reported-by: Sergey Ryabinin Closes https://github.com/curl/curl/pull/10709 Dan Fandrich (10 Mar 2023) - tests: fix some keywords and unused sections - tests: fix test1301 to call the right binary It was refactored in commit 480ac6e5 but this step was missed. - tests: add timeout, SLOWDOWN and DELAY keywords to tests These are tests that are testing timing and end up being quite slow. Daniel Stenberg (10 Mar 2023) - RELEASE-NOTES: synced Stefan Eissing (10 Mar 2023) - wolfSSL: ressurect the BIO `io_result` In pytest'ing the situation occored that wolfSSL reported an IO error when the underlying BIO operation was returning an CURLE_AGAIN condition. Readding the `io_result` filter context member to detect such situations. Also, making sure that the returned CURLcode is initialized on all recv operations outcome. Closes #10716 - gssapi: align global `gss_OID_desc` vars to silence ld warnings on macOS vent ura Refs #9975 which first reported this. Closes #10718 Daniel Stenberg (10 Mar 2023) - libssh2: only set the memory callbacks when debugging This makes us debug libssh2 less and libcurl more when for example running torture tests that otherwise will spend a lot of time in libssh2 functions. We leave libssh2 to test libssh2. Closes #10721 - docs/SECURITY-PROCESS.md: updates - allow Low+Medium issues to be managed through plain PRs - update the bug-bounty part to reflect current reality Closes #10719 Dan Fandrich (9 Mar 2023) - tests: fix tag markup issues in some tests Marcel Raad (9 Mar 2023) - tests: add `cookies` features These tests don't work with `--disable-cookies`. Closes https://github.com/curl/curl/pull/10713 - test420: add cookies keyword It fails with `--disable-cookies`. Closes https://github.com/curl/curl/pull/10713 Dan Fandrich (8 Mar 2023) - CI: Add more labeler match patterns Also, add the CI, tests or libcurl API tags in conjunction with any others that might also apply. Andy Alt (9 Mar 2023) - GHA: minor improvements to spellcheck Closes #10640 Daniel Stenberg (9 Mar 2023) - test1671: fix after fix - test421: -w %{header_json} test with multiple same header names To reproduce the issue in #10704 - tool_writeout_json. fix the output for duplicate header names Header entries with index != 0 are handled at the index 0 level so they should then be skipped when iterated over. Reported-by: Boris Okunskiy Fixes #10704 Closes #10707 - headers: make curl_easy_header and nextheader return different buffers By letting curl_easy_header() and curl_easy_nextheader() store the header data in their own struct storage when they return a pointer to it, it makes it possible for applications to use them both in a loop. Like the curl tool does. Reported-by: Boris Okunskiy Fixes #10704 Closes #10707 rcombs (8 Mar 2023) - urlapi: take const args in _dup and _get functions Closes #10708 - urlapi: avoid mutating internals in getter routine This was not intended. Closes #10708 Daniel Stenberg (8 Mar 2023) - urlapi: '%' is illegal in host names Update test 1560 to verify Ref: #10708 Closes #10711 - ftp: make the 'ftpauth' a more normal 'char *'-array Closes #10703 Evgeny Grin (Karlson2k) (8 Mar 2023) - doc: fix compiler warning in libcurl.m4 Current test for curl_free() may produce warnings with strict compiler flags or even with default compiler flags with upcoming versions. These warning could turned into errors by -Werror or similar flags. Such warnings/errors are avoided by this patch. Closes #10710 Viktor Szakats (8 Mar 2023) - misc: fix typos Closes #10706 Stefan Eissing (7 Mar 2023) - ftp: active mode with SSL, add the damn filter - since 7.87.0 we lost adding the SSL filter for an active FTP connection that uses SSL. This leads to hangers and timeouts as reported in #10666. Reported-by: SandakovMM on github Fixes #10666 Closes #10669 Daniel Stenberg (7 Mar 2023) - docs: extend the URL API descriptions Closes #10701 Stefan Eissing (7 Mar 2023) - url: fix logic in connection reuse to deny reuse on "unclean" connections - add parameter to `conn_is_alive()` cfilter method that returns if there is input data waiting on the connection - refrain from re-using connnection from the cache that have input pending - adapt http/2 and http/3 alive checks to digest pending input to check the connection state - remove check_cxn method from openssl as that was just doing what the socket filter now does. - add tests for connection reuse with special server configs Closes #10690 Daniel Stenberg (6 Mar 2023) - x509asn1: use plain %x, not %lx, when the arg is an int Pointed out by Coverity. Closes #10689 Stefan Eissing (6 Mar 2023) - http2: fix handling of RST and GOAWAY to recognize partial transfers - a reset transfer (HTTP/2 RST) did not always lead to the proper error message on receiving its response, leading to wrong reports of a successful transfer - test_05_02 was able to trigger this condition with increased transfer count. The simulated response errors did not carry a 'Content-Length' so only proper RST handling could detect the abort - When doing such transfers in parallel, a connection could enter the state where a) it had been closed (GOAWAY received) b) the RST had not been "seen" for the transfer yet or c) the GOAWAY announced an error and the last successful stream id was not checked against ongoing transfers Closes #10693 - tests: use dynamic ports numbers in pytest suite - necessary ports are bound at start of test suite and then given to server fixtures for use. - this make parallel use of pytest (in separate directories), practically safe for use as OS tend to not reuse such port numbers for a while Closes #10692 - connect: fix time_connect and time_appconnect timer statistics - time_connect was not updated when the overall connection failed, e.g. when SSL verification was unsuccessful, refs #10670 - rework gather those values to interrogate involved filters, also from all eyeballing attempts, to report the maximum of those values. - added 3 test cases in test_06 to check reported values on successful, partially failed and totally failed connections. Reported-by: Master Inspire Fixes #10670 Closes #10671 Daniel Stenberg (6 Mar 2023) - test1905: update output cookie order After the #10685 update - test420: verify expiring cookies Cookies that are loaded fine from a jar but then are expired in headers. - cookie: don't load cookies again when flushing Reported-by: Sergio Mijatovic Fixes #10677 Closes #10685 - RELEASE-NOTES: synced Andy Alt (6 Mar 2023) - docs: note '--data-urlencode' option Closes #10687 Daniel Stenberg (6 Mar 2023) - DEPRECATE: the original legacy mingw version 1 Remove completely in September 2023 Closes #10667 Harry Sintonen (6 Mar 2023) - rand: use arc4random as fallback when available Normally curl uses cryptographically strong random provided by the selected SSL backend. If compiled without SSL support, a naive built-in function was used instead. Generally this was okay, but it will result in some downsides for non- SSL builds, such as predictable temporary file names. This change ensures that arc4random will be used instead, if available. Closes #10672 Grisha Levit (6 Mar 2023) - tool: dump headers even if file is write-only The fixes in #10079 brought a (seemingly unrelated) change of open mode from `wb`/`ab` to `wb+`/`ab+` for the headerfile. This makes it no longer possible to write the header file to e.g. a pipe, like: curl -D >(grep ...) file:///dev/null Which presently results in `Warning: Failed to open /dev/fd/63` See #10079 Closes #10675 Jay Satiro (6 Mar 2023) - tests: fix gnutls-serv check - If gnutls-serv doesn't exist then don't try to execute it. Follow-up to 2fdc1d81. Closes https://github.com/curl/curl/pull/10688 Daniel Stenberg (6 Mar 2023) - lib1560: fix enumerated type mixed with another type Follow-up to c84c0f9aa3bb006 Closes #10684 Viktor Szakats (5 Mar 2023) - cmake: fix enabling LDAPS on Windows Before this patch, enabling LDAPS required a manual C flag: https://github.com/curl/curl-for-win/blob/c1cfc31cfc04f24f7a4f946564d6f0e1b4d 7dd36/curl-cmake.sh#L105 Fix this and enable LDAPS automatically when using `wldap32` (and when not explicitly disabled). This matches autotools and `Makefile.mk` behavior. Also remove issue from KNOWN_BUGS. Add workaround for MSVS 2010 warning triggered by LDAPS now enabled in more CI tests: `ldap.c(360): warning C4306: 'type cast' : conversion from 'int' to 'void *' of greater size` Ref: https://ci.appveyor.com/project/curlorg/curl/builds/46408284/job/v8mwl9y fbmoeqwlr#L312 Reported-by: JackBoosY on github Reviewed-by: Jay Satiro Reviewed-by: Marcel Raad Fixes #6284 Closes #10674 - Makefile.mk: delete redundant `HAVE_LDAP_SSL` macro [ci skip] Since abebb2b8939c6b3e0f951eb2d9ec3729b569aa2c, we set this macro for all Windows `wldap32` builds using `Makefile.mk`. For OpenLDAP builds this macro is not enough to enable LDAPS, and OpenLDAP is not an option in `Makefile.mk`. For Novell LDAP it might have helped, but it's also not an option anymore in `Makefile.mk`. The future for LDAPS is that we should enable it by default without extra build knobs. Reviewed-by: Marcel Raad Closes #10681 - cmake: skip CA-path/bundle auto-detection in cross-builds Also remove issue from KNOWN_BUGS. Reported-by: Cristian Morales Vega Reviewed-by: Marcel Raad Fixes #6178 Closes #10676 Daniel Stenberg (3 Mar 2023) - schannel: loop over the algos to pick the selected one Avoid using the funny macro and the extra buffer copy. Closes #10647 - wildcard: remove files and move functions into ftplistparser.c - ftp: allocate the wildcard struct on demand The feature is rarely used so this frees up data for the vast majority of easy handles that don't use it. Rename "protdata" to "ftpwc" since it is always an FTP wildcard struct pointer. Made the state struct field an unsigned char to save space. Closes #10639 - lib1560: test parsing URLs with ridiculously large fields In the order of 120K. Closes #10665 Brad Spencer (3 Mar 2023) - urlapi: parse IPv6 literals without ENABLE_IPV6 This makes the URL parser API stable and working the same way independently of libcurl supporting IPv6 transfers or not. Closes #10660 Jan Engelhardt (3 Mar 2023) - build: drop the use of XC_AMEND_DISTCLEAN Because automake used to delete depdirs at once (.deps) and there was an issu e with portability, curl's XC_AMEND_DISTCLEAN greps the Makefiles in an attempt to build a list of all depfiles and delete them individually instead. Since commit 08849db866b44510f6b8fd49e313c91a43a3dfd3, automake switched from deleting directories to individual files. curl's custom logic now finds a lot more results with the grep (the filtering of these results isn't great), whic h causes a massive bloating of the Makefile in the order of O(n^2). Also remove now-unused XC_AMEND_DISTCLEAN macro group References: https://github.com/curl/curl/issues/9843 References: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=59288 Reported-by: Ilmari Lauhakangas Fixes #9843 Closes #10661 Balakrishnan Balasubramanian (3 Mar 2023) - test1470: test socks proxy using unix sockets and connect to https Similar to test1468 except using https instead of http Closes #10662 Daniel Stenberg (3 Mar 2023) - test1960: verify CURL_SOCKOPT_ALREADY_CONNECTED When returned from the CURLOPT_SOCKOPTFUNCTION, like when we have a custom socket connected in the app, passed in to libcurl. Verifies the fix in #10648 Closes #10651 Stefan Eissing (2 Mar 2023) - tests: rename tests/tests-httpd to tests/http - httpd is only one server we test with - the suite coveres the HTTP protocol in general where the default test cases need a more beefy environment Closes #10654 - socket: detect "dead" connections better, e.g. not fit for reuse - refs #10646 where reuse was attempted on closed connections in the cache, leading to an exhaustion of retries on a transfer - the mistake was that poll events like POLLHUP, POLLERR, etc were regarded as "not dead". - change cf-socket filter check to regard such events as inidication of corpsiness. - vtls filter checks: fixed interpretation of backend check result when inconclusive to interrogate status further down the filter chain. Reported-by: SendSonS on github Fixes #10646 Closes #10652 - lib: give source files cf-http.* better fitting names Closes #10656 - http2: fix code indent Closes https://github.com/curl/curl/pull/10655 Shankar Jadhavar (1 Mar 2023) - cf-socket: if socket is already connected, return CURLE_OK In 7.87.0, if callback method for CURLOPT_SOCKOPTFUNCTION returns CURL_SOCKOPT_ALREADY_CONNECTED then curl library used to return CURLE_OK. n 7.88.0, now even if callback returns CURL_SOCKOPT_ALREADY_CONNECTED, curl library still tries to connect to socket by invoking method do_connect(). This is regression caused by commit https://github.com/curl/curl/commit/71b7e0161032927cdfb Fix: Check if we are already connected and return CURLE_OK. Fixes #10626 Closes #10648 Jay Satiro (1 Mar 2023) - DYNBUF.md: note Curl_dyn_add* calls Curl_dyn_free on failure This is the existing behavior and it has been widely assumed in the codebase. Closes https://github.com/curl/curl/pull/10645 Stefan Eissing (1 Mar 2023) - http2: fix upload busy loop - Set KEEP_SEND_PAUSE when exhausting remote HTTP/2 window size of a stream. - Clear KEEP_SEND_PAUSE when receiving HTTP/2 window updates on a paused stream. - Also fix http2 send compiler warnings reported in #10449. Prior to this change, starting in 71b7e016 which precedes 7.88.0, libcurl may eat CPU during HTTP/2 upload. Reported-by: Jay Satiro Fixes https://github.com/curl/curl/issues/10449 Fixes https://github.com/curl/curl/issues/10618 Closes https://github.com/curl/curl/pull/10627 Daniel Stenberg (1 Mar 2023) - sectransp: make read_cert() use a dynbuf when loading Closes #10632 Jay Satiro (1 Mar 2023) - transfer: limit Windows SO_SNDBUF updates to once a second - Change readwrite_upload() to call win_update_buffer_size() no more than once a second to update SO_SNDBUF (send buffer limit). Prior to this change during an upload readwrite_upload() could call win_update_buffer_size() anywhere from hundreds of times per second to an extreme test case of 100k per second (which is likely due to a bug, see #10618). In the latter case WPA profiler showed win_update_buffer_size was the highest capture count in readwrite_upload. In any case the calls were excessive and unnecessary. Ref: https://github.com/curl/curl/pull/2762 Closes https://github.com/curl/curl/pull/10611 Daniel Stenberg (28 Feb 2023) - RELEASE-NOTES: synced Stefan Eissing (28 Feb 2023) - http2: fix for http2-prior-knowledge when reusing connections - refs #10634 where errors in the HTTP/2 framing layer are observed. - the bug was that on connection reuse, the code attempted to switch in yet another layer of HTTP/2 handling instead of detecting that this was already in place. - added pytest testcase reproducing the issue. Reported-by: rwmjones on github Fixes #10634 Closes #10643 - cf-socket: fix handling of remote addr for accepted tcp sockets - do not try to determine the remote address of a listen socket. There is none. - Update remote address of an accepted socket by getpeername() if available. Reported-by: Harry Sintonen Fixes #10622 Closes #10642 - http: fix unix domain socket use in https connects - when h2/h3 eyeballing was involved, unix domain socket configurations were not honoured - configuring --unix-socket will disable HTTP/3 as candidate for eyeballing - combinatino of --unix-socket and --http3-only will fail during initialisati on - adding pytest test_11 to reproduce Reported-by: Jelle van der Waa Fixes #10633 Closes #10641 Daniel Stenberg (28 Feb 2023) - setopt: move the CURLOPT_CHUNK_DATA pointer to the set struct To make duphandle work etc Closes #10635 Viktor Szakats (28 Feb 2023) - quic/schannel: fix compiler warnings Fixes #10603 Closes #10616 Daniel Stenberg (28 Feb 2023) - page-footer: add explanation for three missing exit codes Added in 7.73.0, 7.77.0 and 7.84.0 Closes #10630 積丹尼 Dan Jacobson (28 Feb 2023) - rate.c: single URLs make no sense in --rate example Here somehow you need to put more than one URL in these examples, else they will make no sense, as --rate only affects the second and beyond URLs. The first URL will always finish the same time no matter what --rate is given. Closes #10638 Daniel Stenberg (28 Feb 2023) - libcurl-errors.3: add the CURLHcode errors from curl_easy_header.3 Closes #10629 - mqtt: on send error, return error Reported-by: Maciej Domanski Closes #10623 - ws: keep the socket non-blocking Reported-by: marski on github Fixes #10615 Closes #10625 - hostip: avoid sscanf and extra buffer copies Also made create_hostcache_id() return the id length. Closes #10601 - PARALLEL-TRANSFERS.md: not "early days" for this anymore Refresh the language as the support is now over three years old Closes #10624 - easy: remove infof() debug leftover from curl_easy_recv It said "reached [path]/easy.c:1231" Closes #10628 - idn: return error if the conversion ends up with a blank host Some IDN sequences are converted into "" (nothing), which can make this function end up with a zero length host name and we cannot consider that a valid host to continue with. Reported-by: Maciej Domanski Closes #10617 - examples/http3.c: use CURL_HTTP_VERSION_3 and update the comment Closes #10619 - x509asn1.c: use correct format specifier for infof() call Detected by Coverity Closes #10614 - Revert "GHA: add Microsoft C++ Code Analysis" This reverts commit e0db842b2a082dffad4a9fbe31321e9a75c74041. This tool seems very restricted in how often it might be used by a project and thus very quickly start to report fails simply because it refuses to run when "there are more runs than allowed". Closes #10613 Patrick Monnerat (25 Feb 2023) - tests: test secure mail protocols with explicit SSL requests New tests 987, 988 and 989, disabled for rustls (hanging). Closes #10077 - tests: support for imaps/pop3s/smtps protocols Closes #10077 - runtests: use a hash table for server port numbers Closes #10077 Andy Alt (25 Feb 2023) - INTERNALS.md: grammar Closes #10607 Daniel Stenberg (25 Feb 2023) - RELEASE-NOTES: synced Philip Heiduck (25 Feb 2023) - .cirrus.yml: Bump to FreeBSD 13.2 Closes #10270 - ngtcp2-gnutls.yml: bump to gnutls 3.8.0 Closes #10507 - CI: update ngtcp2 and nghttp2 for pytest Follow-up: https://github.com/curl/curl/commit/5c9ee8cef4b351a085b440f8178500 124647f8e6 Closes #10508 Andy Alt (25 Feb 2023) - GHA: use same flags for Slackbuild as Slack package Closes #10526 Daniel Stenberg (24 Feb 2023) - rtsp: avoid sscanf for parsing Closes #10605 - http_proxy: parse the status line without sscanf Closes #10602 - telnet: error correctly for WS set to "x[num]" Follow-up to e4f93be9d587 Reported-by: Harry Sintonen Closes #10606 - krb5: avoid sscanf for parsing Closes #10599 - misc: remove support for curl_off_t < 8 bytes Closes #10597 - telnet: parse NEW_ENVIRON without sscanf Closes #10596 - telnet: parse the WS= argument without sscanf Closes #10596 - telnet: parse telnet options without sscanf Closes #10596 - ftp: replace sscanf for MDTM 213 response parsing Closes #10590 - ftp: replace sscanf for PASV parsing Closes #10590 - ftp: make the EPSV response parser not use sscanf Closes #10590 Stefan Eissing (24 Feb 2023) - ngtcp2: fix unwanted close of file descriptor 0 ... causing macOS to hand out 0 as next socket handle and failing on further operations. Reported-by: Sergey Fionov Fixes #10593 Closes #10595 Daniel Stenberg (23 Feb 2023) - select: stop treating POLLRDBAND as an error POLLRDBAND does not seem to be an general error and on Windows the value for POLLIN is 768 and the value for POLLRDBAND is 512. Fixes #10501 Reported-by: opensslonzos-github on github Closes #10592 - test978: mark file as text mode Follow-up to 4ea5702980cb To fix test failures on Windows Closes #10594 - http: rewrite the status line parser without sscanf Closes #10585 - test978: verify that --stderr works for -w's stderr as well Jay Satiro (23 Feb 2023) - curl: make -w's %{stderr} use the file set with --stderr Reported-by: u20221022 on github Fixes #10491 Closes #10569 - winbuild: fix makefile clean - Fix and move 'clean' code that removes the output and obj directories trees from MakefileBuild.vc to Makefile.vc. Prior to this change the 'clean' code did not work right because the variables containing the directory names were not fully initialized and the rmdir syntax was sometimes incorrect (typos). DIRDIST for example was set to ..\builds\ and not ..\builds\$(CONFIG_NAME_LIB)\ so it would remove the former and not the latter. If WITH_PREFIX was set then that directory was removed instead. Also, DIRDIST (the output directory) even if initialized should not be removed by MakefileBuild.vc because by that time it could be set to a user directory that may contain other files if WITH_PREFIX is set (eg we don't want rmdir /s /q C:\usr\local). Therefore we remove from Makefile.vc before any of that happens. I added a comment in both makefiles explaining this. Closes https://github.com/curl/curl/pull/10576 - sectransp: fix compiler warning c89 mixed code/declaration Since cbf57176 the Cirrus CI 'macOS arm64 SecureTransport http2' has been failing due to c89 warnings mixed code/declaration. That commit is not the cause so I assume something has changed in the CI outside of our configuration. Anyway, we don't mix code/declaration so this is the fix for that. Closes https://github.com/curl/curl/pull/10574 Philipp Engel (22 Feb 2023) - BINDINGS: add Fortran binding Closes #10589 Stefan Eissing (22 Feb 2023) - test2600: detect when ALARM_TIMEOUT is in use and adjust - use higher timeout values > 1s - skip duration checks Assisted-by: Marcel Raad Closes #10513 Daniel Stenberg (22 Feb 2023) - RELEASE-NOTES: synced - test686: verify return code for no URL after --next - tool_operate: propagate error codes for missing URL after --next Fixes #10558 Reported-by: u20221022 on github Closes #10580 - test1278: verify that an extra --no-remote-name cause no warning - tool_getparam: don't add a new node for just --no-remote-name Unless --remote-name-all is used. Fixes #10564 Reported-by: u20221022 on github Closes #10582 - gen.pl: add '%GLOBALS' as a variable for mainpage And use it in page-header to list all global command line options. - docs/cmdline-opts: mark all global options gen.pl now outputs a generic explanations for them for each option Fixes #10566 Reported-by: u20221022 on github Closes #10584 - GHA: add Microsoft C++ Code Analysis Closes #10583 - tool_progress: shut off progress meter for --silent in parallel Reported-by: finkjsc on github Fixes #10573 Closes #10579 - lib1560: add a test using %25 in the userinfo in a URL Closes #10578 Stefan Eissing (21 Feb 2023) - CURLOPT_PIPEWAIT: allow waited reuse also for subsequent connections As tested in test_02_07, when firing off 200 urls with --parallel, 199 wait for the first connection to be established. if that is multiuse, urls are added up to its capacity. The first url over capacity opens another connection. But subsequent urls found the same situation and open a connection too. They should have waited for the second connection to actually connect and make its capacity known. This change fixes that by - setting `connkeep()` early in the HTTP setup handler. as otherwise a new connection is marked as closeit by default and not considered for multiuse at all - checking the "connected" status for a candidate always and continuing to PIPEWAIT if no alternative is found. pytest: - removed "skip" from test_02_07 - added test_02_07b to check that http/1.1 continues to work as before Closes #10456 Daniel Stenberg (21 Feb 2023) - test419: verify --dump-header to file that cannot be created Closes #10571 - tool_operate: avoid fclose(NULL) on bad header dump file Fixes #10570 Reported-by: Jérémy Rabasco Closes #10571 - RELEASE-NOTES: synced Starting the journey towards 8.0.0 - cookie: parse without sscanf() Saves us from using 2*4096 bytes buffers on stack, the extra copies and more. Closes #10550 - lib517: verify time stamps without leading zeroes plus some more - parsedate: replace sscanf( for time stamp parsing Closes #10547 - parsedate: parse strings without using sscanf() - sscanf is slow and complex, avoid it - give up already if the string is 12 bytes or longer as no valid string can be that long - this can now be done without copy Closes #10547 Matt Jolly (20 Feb 2023) - tests: HTTP server fixups - httpserver.pl -> http-server.pl for consistency - add http3-server.pl to EXTRA_DIST; alphabetise for maintainability - nghttpx proxy invocation scripts should not use getcwd Closes #10568 Version 7.88.1 (20 Feb 2023) Daniel Stenberg (20 Feb 2023) - RELEASE-NOTES: synced 7.88.1 release - THANKS: add contributors from 7.88.1 - socketpair: allow EWOULDBLOCK when reading the pair check bytes Reported-by: Gunamoi Software Co-authored-by: Jay Satiro Fixes #10561 Closes #10562 Jay Satiro (18 Feb 2023) - tool_operate: fix scanbuild compiler warning Prior to this change Azure CI scanbuild warned of a potential NULL pointer string passed to strtol when CURLDEBUG enabled, even though the way the code was written it wouldn't have happened. Bug: https://github.com/curl/curl/commit/5479d991#r101159711 Reported-by: Marcel Raad Closes https://github.com/curl/curl/pull/10559 - curl_setup: Suppress OpenSSL 3 deprecation warnings - Define OPENSSL_SUPPRESS_DEPRECATED. OpenSSL 3 has deprecated some of the functions libcurl uses such as those with DES, MD5 and ENGINE prefix. We don't have replacements for those functions so the warnings were disabled in autotools and cmake builds, but still showed in other builds. Closes https://github.com/curl/curl/pull/10543 - build-openssl.bat: keep OpenSSL 3 engine binaries Prior to this change copying the OpenSSL 3 engine binaries failed because 'engines-1_1' (OpenSSL 1.1.x folder name) was erroneously used instead of 'engines-3'. The OpenSSL 3 builds would complete successfully but without the engine binaries. Closes https://github.com/curl/curl/pull/10542 ALittleDruid (18 Feb 2023) - cmake: fix Windows check for CryptAcquireContext Check for CryptAcquireContext in windows.h and wincrypt.h only, since otherwise this check may fail due to third party headers not found. Closes https://github.com/curl/curl/pull/10353 Daniel Stenberg (19 Feb 2023) - remote-header-name.d: mention that filename* is not supported and that you can use --clobber to allow overwriting. Ref: #10533 Closes #10555 Co-authored-by: Jay Satiro <raysatiro@yahoo.com> Pierrick Charron (18 Feb 2023) - CURLOPT_WS_OPTIONS.3: fix the availability version Closes #10557 Jacob Hoffman-Andrews (18 Feb 2023) - GHA: update rustls dependency to 0.9.2 This allows re-enabling test 312 for the rustls backend. Closes #10553 Philip Heiduck (18 Feb 2023) - HTTP3.md: update git branches Closes #10554 Stefan Eissing (17 Feb 2023) - urldata: remove `now` from struct SingleRequest - not needed Closes #10549 Daniel Stenberg (17 Feb 2023) - lib1560: add IPv6 canonicalization tests Closes #10552 - RELEASE-NOTES: synced - urlapi: do the port number extraction without using sscanf() - sscanf() is rather complex and slow, strchr() much simpler - the port number function does not need to fully verify the IPv6 address anyway as it is done later in the hostname_check() function and doing it twice is unnecessary. Closes #10541 Stefan Eissing (17 Feb 2023) - setopt: allow HTTP3 when HTTP2 is not defined Reported-by: Karthikdasari0423 on github Fixes #10538 Closes #10544 Jon Rumsey (17 Feb 2023) - os400: correct Curl_os400_sendto() Add const qualifier to 5th argument of Curl_os400_sendto() Make OS400 wrapper for sendto match the normal prototype of sendto() with a const qualifier. Fixes #10539 Closes #10548 Stefan Eissing (17 Feb 2023) - tests-httpd: add proxy tests for direct and tunneling checks on http: and https: Closes #10519 Daniel Stenberg (17 Feb 2023) - curl: make --silent work stand-alone - renamed the struct field to 'silent' to match the cmdline option - make --show-error toggle independently of --silent - make --silent independent of ->noprogress as well By doing this, the three options --silent, --no-progress-meter and --show-error should work independently of each other and also work with and without '--no-' prefix as documented. Reported-by: u20221022 on github Fixes #10535 Closes #10536 - socks: allow using DoH to resolve host names For SOCKS modes where a local host resolve is done. It was previously disabled in 12d655d4561, but a few local tests seem to indicate that it works fine. Works now because of the SOCKS refactor of 4a4b63daaa01ef59 that made it non-blocking. Reported-by: roughtex on github Fixes #10537 Closes #10540 Stefan Eissing (17 Feb 2023) - test: add test for HTTP/2 corruption as reported in #10525 - adding test_02_20 for reproducing the situation - using recently released mod_h2 Apache module - skipping test if an older version is installed - adding installation of current mod_h2 to github pytest workflow This reproduces the error reliable (for me) on the lib/http2.c version of curl 7.88.0. And passes with the recent curl master. Closes #10534 Daniel Stenberg (16 Feb 2023) - tool_operate: allow debug builds to set buffersize Using the CURL_BUFFERSIZE environment variable. Closes #10532 Stefan Eissing (16 Feb 2023) - connnect: fix timeout handling to use full duration - connect timeout was used at half the configured value, if the destination had 1 ip version 4 and other version 6 addresses (or the other way around) - extended test2600 to reproduce these cases Reported-by: Michael Kaufmann Fixes #10514 Closes #10517 Daniel Stenberg (16 Feb 2023) - tool_getparam: make --get a true boolean To match how it is documented in the man page. Fixes #10527 Reported-by: u20221022 on github Closes #10531 Harry Sintonen (16 Feb 2023) - http:: include stdint.h more readily Closes #10516 Stefan Eissing (16 Feb 2023) - tests: make the telnet server shut down a socket gracefully - test 1452 failed occasionally with ECONNRESET errnos in curl when the server closed the connection in an unclean state. Closes #10509 Harry Sintonen (16 Feb 2023) - http2: set drain on stream end Ensure that on_frame_recv() stream end will trigger a read if there is pending data. Without this it could happen that the pending data is never consumed. This combined with https://github.com/curl/curl/pull/10529 should fix https://github.com/curl/curl/issues/10525 Ref: https://github.com/curl/curl/issues/10525 Closes #10530 Stefan Eissing (16 Feb 2023) - http2: buffer/pausedata and output flush fix. * do not process pending input data when copying pausedata to the caller * return CURLE_AGAIN if the output buffer could not be completely written out. Ref: #10525 Closes #10529 Marcel Raad (16 Feb 2023) - krb5: silence cast-align warning Add an intermediate cast to `void *`, as done everywhere else when casting from `sockaddr *` to `sockaddr_in *`. Closes https://github.com/curl/curl/pull/10528 Daniel Stenberg (15 Feb 2023) - RELEASE-NOTES: synced bumped to 7.88.1 - tests: make sure gnuserv-tls has SRP support before using it Reported-by: fundawang on github Fixes #10522 Closes #10524 - runtests: fix "uninitialized value $port" by using a more appropriate variable Reported-by: fundawang on github Fixes #10518 Closes #10520 Version 7.88.0 (15 Feb 2023) Daniel Stenberg (15 Feb 2023) - RELEASE-NOTES: synced 7.88.0 release - THANKS: added contributors from 7.88.0 - openssl: rename 'errcode_t' to 'sslerr_t' Turns out "/usr/include/et/com_err.h" typedefs this type (without proper variable scoping). comerr is the "common error description library" that apparently might be use d by krb5 code, which then makes this header get used in a curl build. Reported-by: Bruno Henrique Batista Cruz da Silva Fixed #10502 Closes #10500 Dan Fandrich (13 Feb 2023) - CONTRIBUTE: More formally specify the commit description This codifies what people have actually used in git commits over the past 6 years. I've left off some lesser-used headers that appear to duplicate others and tried to describe a consistent use for several others that were used more arbitrarily. This makes it easier for new committers to find out the kinds of things we want to acknowledge, makes it easier to perform statistical analysis on commits, and opens the possibility of performing lint checks on descriptions before submission. Reviewed-by: Daniel Stenberg Reviewed-by: Jay Satiro Closes #10478 Stefan Eissing (13 Feb 2023) - openssl: test and fix for forward proxy handling (non-tunneling). - adding pytest test_10 cases for proxy httpd setup tests - fixing openssl bug in https: proxy hostname verification that used the hostname of the request and not the proxy name. Closes #10498 Daniel Stenberg (13 Feb 2023) - cmdline-opts/Makefile: on error, do not leave a partial And support 'make V=1' to show the full command line Closes #10497 - curl.1: make help, version and manual sections "custom" Instead of using "multi: boolean", as these are slightly special as in they do are not enable/disable ones. Fixes #10490 Reported-by: u20221022 on github Closes #10497 Stefan Eissing (13 Feb 2023) - tests: add tests for HTTP/2 and HTTP/3 to verify the header API Test 2403 and 2503 check "header_json" output and therefore use of header-api Closes #10495 Philip Heiduck (13 Feb 2023) - CI: update wolfssl / wolfssh to 5.5.4 / 1.4.12 Closes #10493 Daniel Stenberg (13 Feb 2023) - KNOW_BUGS: cleanups with some changed to TODOs - remove "Excessive HTTP/2 packets with TCP_NODELAY" This is not a bug. Rather room for improvement. I believe these have been fixed: - 17.4 Connection failures with parallel HTTP/2 - 17.5 HTTP/2 connections through HTTPS proxy frequently stall - remove "FTPS needs session reuse" That is still true, but curl should also do session reuse now. - remove "ASCII FTP" It is documented behavior, and not single user has asked for extended functionality here the last decade or so. - remove "Passive transfer tries only one IP address" add as a TODO - remove "DoH leaks memory after followlocation" With a recipe on how to reproduce, this is pointless to keep around - remove "DoH does not inherit all transfer options" add it as a TODO Closes #10487 Tatsuhiro Tsujikawa (13 Feb 2023) - GHA: bump ngtcp2 workflow dependencies Closes #10494 Patrick Monnerat (13 Feb 2023) - content_encoding: do not reset stage counter for each header Test 418 verifies Closes #10492 Daniel Stenberg (13 Feb 2023) - RELEASE-NOTES: synced Jay Satiro (13 Feb 2023) - multi: stop sending empty HTTP/3 UDP datagrams on Windows - Limit the 0-sized send procedure that is used to reset a SOCKET's FD_WRITE to TCP sockets only. Prior to this change the reset was used on UDP sockets as well, but unlike TCP sockets a 0-sized send actually sends out a datagram. Assisted-by: Marc Hörsken Ref: https://github.com/curl/curl/pull/9203 Fixes https://github.com/curl/curl/issues/9086 Closes https://github.com/curl/curl/pull/10430 Viktor Szakats (12 Feb 2023) - h3: silence compiler warnings Reviewed-by: Daniel Stenberg Fixes #10485 Closes #10486 Daniel Stenberg (12 Feb 2023) - smb: return error on upload without size The protocol needs to know the size ahead of time, this is now a known restriction and not a bug. Also output a clearer error if the URL path does not contain proper share. Ref: #7896 Closes #10484 Viktor Szakats (12 Feb 2023) - windows: always use curl's basename() implementation The `basename()` [1][2] implementation provided by mingw-w64 [3] makes assumptions about input encoding and may break with non-ASCII strings. `basename()` was auto-detected with CMake, autotools and since 68fa9bf3f5d7b4fcbb57619f70cb4aabb79a51f6 (2022-10-13), also in `Makefile.mk` after syncing its behaviour with the mainline build methods. A similar patch for curl-for-win broke official Windows builds earlier, in release 7.83.1_4 (2022-06-15). This patch forces all Windows builds to use curl's internal `basename()` implementation to avoid such problems. [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html [2]: https://www.man7.org/linux/man-pages/man3/basename.3.html [3]: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-c rt/misc/basename.c Reported-by: UnicornZhang on Github Assisted-by: Cherish98 on Github Reviewed-by: Daniel Stenberg Fixes #10261 Closes #10475 Philip Heiduck (12 Feb 2023) - Linux CI: Bump rustls-ffi to v0.9.1 Closes #10476 Daniel Stenberg (12 Feb 2023) - libtest: build lib2305 with multibyte as well Fixes a build regression. Follow-up to 5a9a04d5567 Reported-by: Viktor Szakats Ref: https://github.com/curl/curl/pull/10475#issuecomment-1426831800 Closes #10477 Dmitry Atamanov (12 Feb 2023) - cmake: fix dev warning due to mismatched arg The package name passed to find_package_handle_standard_args (BROTLI) does not match the name of the calling package (Brotli). This can lead to problems in calling code that expects find_package result variables (e.g., _FOUND) to follow a certain pattern. Closes https://github.com/curl/curl/pull/10471 James Keast (11 Feb 2023) - setopt: Address undefined behaviour by checking for null This addresses undefined behaviour found using clang's UBsan: curl/lib/setopt.c:177:14: runtime error: applying non-zero offset 1 to null p ointer SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior curl/lib/setopt.c:177 :14 in Closes #10472 Jacob Hoffman-Andrews (11 Feb 2023) - rustls: improve error messages Changes numeric error codes into verbose error codes in two places. Adds a prefix indicating that the error came from rustls, and in some places which function it came from. Adds special handling for RUSTLS_RESULT_UNEXPECTED_EOF, since the default message of "Unexpected EOF" is insufficiently explanatory. Closes #10463 Daniel Stenberg (11 Feb 2023) - openssl: remove dead code Follow-up to e8b00fcd6a Due to the new 'if(!nonblocking)' check on the block a level above, there is no need to check for it again within the same conditional. Detected by Coverity Closes #10473 - ngtcp2: replace removed define and stop using removed function They were removed upstream. Reported-by: Karthikdasari0423 on github Fixes #10469 Closes #10474 - scripts/delta: show percent of number of files changed since last tag - RELEASE-NOTES: synced Stefan Eissing (10 Feb 2023) - pytest: add a test case for PUSH related things. - checking that "103 Early Hints" are visible in curl's header dump file Closes #10452 Gregory Panakkal (10 Feb 2023) - WEBSOCKET.md: typo Fixing missing slash for ws protocol scheme Closes #10464 Stefan Eissing (10 Feb 2023) - vquic: stabilization and improvements vquic stabilization - udp send code shared between ngtcp2 and quiche - quiche handling of data and events improved ngtcp2 and pytest improvements - fixes handling of "drain" situations, discovered in scorecard tests with the Caddy server. - improvements in handling transfers that have already data or are already closed to make an early return on recv pytest - adding caddy tests when available scorecard improvemnts. - using correct caddy port - allowing tests for only httpd or caddy Closes #10451 Philip Heiduck (10 Feb 2023) - Linux CI: update some dependecies to latest tag Closes #10458 Daniel Stenberg (10 Feb 2023) - test2305: send 3 frames, 4097 bytes each, as one message Receive them using a 256 bytes buffer in a loop. - ws: fix recv of larger frames + remove 'oleft' from the struct + deal with "overflow data" in a separate dynbuf Reported-by: Mike Duglas Fixes #10438 Closes #10447 - curl/websockets.h: extend the websocket frame struct - sws: fix typo, indentation add more ws logging - test2304: remove stdout verification This cripples the test somewhat but the check was bad since depending on timing it could exit before the output was done, making the test flaky. Dan Fandrich (9 Feb 2023) - CI: Add more labeler match patterns - CI: Retry failed downloads to reduce spurious failures A temporary error with a remote server shouldn't cause a CI run to fail. Also, put a cap on the time to download to fail faster on a misbehaving server or connection and use HTTP compression where possible to reduce download times. Daniel Stenberg (9 Feb 2023) - no-clobber.d: only use long form options in man page text ... since they are expanded and the short-form gets mentioned automatically so if the short form is mentioned as well, it gets repeated. Fixes #10461 Closes #10462 Reported-by: Dan Fandrich - GHA: enable websockets in the torture job Closes #10448 - header.d: add a header file example Closes #10455 Stefan Eissing (9 Feb 2023) - HTTP/[23]: continue upload when state.drain is set - as reported in #10433, HTTP/2 uploads may stall when a response is received before the upload is done. This happens when the data->state.drain is set for such a transfer, as the special handling in transfer.c from then on only cared about downloads. - add continuation of uploads, if applicable, in this case. - add pytest case test_07_12_upload_seq_large to reproduce this scenario (although, current nghttp2 implementation is using drain less often) Reported-by: Lucas Pardue Fixes #10433 Closes #10443 - http2: minor buffer and error path fixes - use memory buffer in full available size - fail receive of reset/errored streams early pytest: - make test_05 error cases more reliable Closes #10444 Federico Pellegrin (9 Feb 2023) - openldap: fix missing sasl symbols at build in specific configs If curl is built with openldap support (USE_OPENLDAP=1) but does not have also some other protocol (IMAP/SMTP/POP3) enabled that brings in Curl_sasl_* functions, then the build will fail with undefined references to various symbols: ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_decode_mech' ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_parse_url_auth _option' ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_cleanup' ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_can_authentica te' ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_continue' ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_start' ld: ../lib/.libs/libcurl.so: undefined reference to `Curl_sasl_init' This was tracked down to these functions bein used in openldap.c but defined in curl_sasl.c and then forward in two vauth/ files to have a guard against a set of #define configurations that was now extended to cover also this case. Example configuration targeted that could reproduce the problem: curl 7.87.1-DEV () libcurl/7.87.1-DEV .... OpenLDAP/2.6.3 Protocols: file ftp ftps http https ldap ldaps Closes #10445 Daniel Stenberg (9 Feb 2023) - ws: use %Ou for outputting curl_off_t with info() Reported-by: Mike Duglas Fixes #10439 Closes #10441 Jay Satiro (9 Feb 2023) - curl_setup: Disable by default recv-before-send in Windows Prior to this change a workaround for Windows to recv before every send was enabled by default. The way it works is a recv is called before every send and saves the received data, in case send fails because in Windows apparently that can wipe out the socket's internal received data buffer. This feature has led to several bugs because the way libcurl operates it waits on a socket to read or to write, and may not at all times check for buffered receive data. Two recent significant bugs this workaround caused: - Broken Schannel TLS 1.3 connections (#9431) - HTTP/2 arbitrary hangs (#10253) The actual code remains though it is disabled by default. Though future changes to connection filter buffering could improve the situation IMO it's just not tenable to manage this workaround. Ref: https://github.com/curl/curl/issues/657 Ref: https://github.com/curl/curl/pull/668 Ref: https://github.com/curl/curl/pull/720 Ref: https://github.com/curl/curl/issues/9431 Ref: https://github.com/curl/curl/issues/10253 Closes https://github.com/curl/curl/pull/10409 Stefan Eissing (8 Feb 2023) - http2: aggregate small SETTINGS/PRIO/WIN_UPDATE frames add a small buffer to nghttp2 session sending in order to aggregate small SETTINGS/PRIO/WIN_UPDATE frames that nghttp2 "writes" to the callback individually. Ref: #10389 Closes #10432 - openssl: store the CA after first send (ClientHello) move Curl_ssl_setup_x509_store() call after the first send (ClientHello) this gives time to parse CA anchors while waiting on the server reply Ref: #10389 Closes #10432 Daniel Stenberg (8 Feb 2023) - RELEASE-NOTES: synced Anthony Hu (8 Feb 2023) - wolfssl: remove deprecated post-quantum algorithms Closes #10440 John Bampton (8 Feb 2023) - misc: fix spelling Closes #10437 Daniel Stenberg (7 Feb 2023) - man pages: call the custom user pointer 'clientp' consistently The variable had a few different names. Now try to use 'clientp' consistently for all man pages using a custom pointer set by the application. Reported-by: Gerrit Renker Fixes #10434 Closes #10435 - vtls: infof using %.*s needs to provide the length as int Fixes a Coverity warning. Closes #10436 Stefan Eissing (7 Feb 2023) - vrls: addressing issues reported by coverity I believe the code was secure before this, but limiting the accepted name length to what is used in the structures should help Coverity's analysis. Closes #10431 Daniel Stenberg (7 Feb 2023) - tool_operate: move the 'updated' variable This was already done by Dan Fandrich in the previous PR but somehow I lost that fixup. Follow-up to 349c5391f2121e Dan Fandrich (7 Feb 2023) - tool_operate: Fix error codes during DOS filename sanitize It would return CURLE_URL_MALFORMAT in an OOM condition. Closes #10414 - tool_operate: Fix error codes on bad URL & OOM curl would erroneously report CURLE_OUT_OF_MEMORY in some cases instead of CURLE_URL_MALFORMAT. In other cases, it would erroneously return CURLE_URL_MALFORMAT instead of CURLE_OUT_OF_MEMORY. Add a test case to test the former condition. Fixes #10130 Closes #10414 Daniel Stenberg (6 Feb 2023) - setopt: use >, not >=, when checking if uarg is larger than uint-max Closes #10421 - vtls: fix failf() format argument type for %.*s handling Reported by Coverity Closes #10422 - openssl: fix "Improper use of negative value" By getting the socket first and returning error in case of bad socket. Detected by Coverity. Closes #10423 Dan Fandrich (6 Feb 2023) - packages: Remove Android.mk from makefile This was missed in commit #44141512 Ref: #10418 Daniel Stenberg (6 Feb 2023) - curl_ws_send.3: clarify how to send multi-frame messages Mike Duglas (6 Feb 2023) - ws: fix multiframe send handling Fixes #10413 Closes #10420 Daniel Stenberg (6 Feb 2023) - unit2600: make sure numerical curl_easy_setopt sets long Follow-up to 671158242db3203 Reported-by: Marcel Raad Fixes #10410 Closes #10419 Andy Alt (6 Feb 2023) - GHA: move Slackware test into matrix Closes #10412 Pronyushkin Petr (6 Feb 2023) - urlapi: fix part of conditional expression is always true: qlen Closes #10408 - url: fix part of conditional expression is always true Closes #10407 Daniel Stenberg (6 Feb 2023) - RELEASE-NOTES: synced Philip Heiduck (6 Feb 2023) - GHA/macos.yml: bump to gcc-12 Closes #10415 Daniel Stenberg (6 Feb 2023) - packages: remove Android, update README - Nobody builds curl for Android using this anymore - Refreshed the README and converted to markdown Reported-by: John Porter Fixes #10416 Closes #10418 Kvarec Lezki (5 Feb 2023) - fopen: remove unnecessary assignment [CWE-1164] V1048: The '* tempname' variable was assigned the same value. Ref: https://pvs-studio.com/en/docs/warnings/v1048/ Closes https://github.com/curl/curl/pull/10398 Gisle Vanem (5 Feb 2023) - libtest: add a sleep macro for Windows .. because sleep() is used in some libtests. Closes https://github.com/curl/curl/pull/10295 Kvarec Lezki (3 Feb 2023) - http_aws_sigv4: remove typecasts from HMAC_SHA256 macro V220: Suspicious sequence of types castings: memsize -> 32-bit integer -> mem size. https://pvs-studio.com/en/docs/warnings/v220/ Closes #10400 Daniel Stenberg (3 Feb 2023) - mailmap: Thomas1664 on github Thomas1664 on github (3 Feb 2023) - CURLOPT_WRITEFUNCTION.3: fix memory leak in example Closes #10390 Kvarec Lezki (3 Feb 2023) - doh: ifdef IPv6 code For disabled IPv6 a condition (conn->ip_version != CURL_IPRESOLVE_V4) is always false. https://pvs-studio.com/en/docs/warnings/v560/ Closes #10397 Daniel Stenberg (3 Feb 2023) - urlapi: remove pathlen assignment "Value stored to 'pathlen' is never read" Follow-up to 804d5293f89 Reported-by: Kvarec Lezki Closes #10405 Kvarec Lezki (3 Feb 2023) - http: fix "part of conditional expression is always false" [CWE-570] V560: A part of conditional expression is always false: conn->bits. authneg. [CWE-570] V560: A part of conditional expression is always false: conn->handl er->protocol & (0 | 0). https://pvs-studio.com/en/docs/warnings/v560/ Closes #10399 Daniel Stenberg (2 Feb 2023) - urlapi: skip the extra dedotdot alloc if no dot in path Saves an allocation for many/most URLs. Updates test 1395 accordingly Closes #10403 Stefan Eissing (2 Feb 2023) - connections: introduce http/3 happy eyeballs New cfilter HTTP-CONNECT for h3/h2/http1.1 eyeballing. - filter is installed when `--http3` in the tool is used (or the equivalent CURLOPT_ done in the library) - starts a QUIC/HTTP/3 connect right away. Should that not succeed after 100ms (subject to change), a parallel attempt is started for HTTP/2 and HTTP/1.1 via TCP - both attempts are subject to IPv6/IPv4 eyeballing, same as happens for other connections - tie timeout to the ip-version HAPPY_EYEBALLS_TIMEOUT - use a `soft` timeout at half the value. When the soft timeout expires, the HTTPS-CONNECT filter checks if the QUIC filter has received any data from the server. If not, it will start the HTTP/2 attempt. HTTP/3(ngtcp2) improvements. - setting call_data in all cfilter calls similar to http/2 and vtls filters for use in callback where no stream data is available. - returning CURLE_PARTIAL_FILE for prematurely terminated transfers - enabling pytest test_05 for h3 - shifting functionality to "connect" UDP sockets from ngtcp2 implementation into the udp socket cfilter. Because unconnected UDP sockets are weird. For example they error when adding to a pollset. HTTP/3(quiche) improvements. - fixed upload bug in quiche implementation, now passes 251 and pytest - error codes on stream RESET - improved debug logs - handling of DRAIN during connect - limiting pending event queue HTTP/2 cfilter improvements. - use LOG_CF macros for dynamic logging in debug build - fix CURLcode on RST streams to be CURLE_PARTIAL_FILE - enable pytest test_05 for h2 - fix upload pytests and improve parallel transfer performance. GOAWAY handling for ngtcp2/quiche - during connect, when the remote server refuses to accept new connections and closes immediately (so the local conn goes into DRAIN phase), the connection is torn down and a another attempt is made after a short grace period. This is the behaviour observed with nghttpx when we tell it to shut down gracefully. Tested in pytest test_03_02. TLS improvements - ALPN selection for SSL/SSL-PROXY filters in one vtls set of functions, repl aces copy of logic in all tls backends. - standardized the infof logging of offered ALPNs - ALPN negotiated: have common function for all backends that sets alpn propr ty and connection related things based on the negotiated protocol (or lack the reof). - new tests/tests-httpd/scorecard.py for testing h3/h2 protocol implementatio n. Invoke: python3 tests/tests-httpd/scorecard.py --help for usage. Improvements on gathering connect statistics and socket access. - new CF_CTRL_CONN_REPORT_STATS cfilter control for having cfilters report connection statistics. This is triggered when the connection has completely connected. - new void Curl_pgrsTimeWas(..) method to report a timer update with a timestamp of when it happend. This allows for updating timers "later", e.g. a connect statistic after full connectivity has been reached. - in case of HTTP eyeballing, the previous changes will update statistics only from the filter chain that "won" the eyeballing. - new cfilter query CF_QUERY_SOCKET for retrieving the socket used by a filter chain. Added methods Curl_conn_cf_get_socket() and Curl_conn_get_socket() for convenient use of this query. - Change VTLS backend to query their sub-filters for the socket when checks during the handshake are made. HTTP/3 documentation on how https eyeballing works. TLS improvements - ALPN selection for SSL/SSL-PROXY filters in one vtls set of functions, repl aces copy of logic in all tls backends. - standardized the infof logging of offered ALPNs - ALPN negotiated: have common function for all backends that sets alpn propr ty and connection related things based on the negotiated protocol (or lack the reof). Scorecard with Caddy. - configure can be run with `--with-test-caddy=path` to specify which caddy t o use for testing - tests/tests-httpd/scorecard.py now measures download speeds with caddy pytest improvements - adding Makfile to clean gen dir - adding nghttpx rundir creation on start - checking httpd version 2.4.55 for test_05 cases where it is needed. Skippin g with message if too old. - catch exception when checking for caddy existance on system. Closes #10349 Daniel Stenberg (2 Feb 2023) - CODEOWNERS: remove the peeps mentioned as CI owners These owners do not have the bandwidth/energy to do the reviews which makes PRs stall and this ownership claim flawed. We can bring people back when the situation is different. Follow-up to c04c78ac87c4d46737934345a Closes #10386 Martin D'Aloia (2 Feb 2023) - write-out.d: add 'since version' to %{header_json} documentation The documentation of `%{header_json}` missed to mention since which version this variable for `--write-out` is present. Based on commit https://github.com/curl/curl/commit/4133a69f2daa476bb we can determine from the tags were this commit is present that the first version to include it was `7.83.0`. This could be also checked with: `git tag --contains 4133a69f2daa476bb6d902687f1dd6660ea9c3c5` Closes #10395 Daniel Stenberg (1 Feb 2023) - urlapi: avoid Curl_dyn_addf() for hex outputs Inspired by the recent fixes to escape.c, we should avoid calling Curl_dyn_addf() in loops, perhaps in particular when adding something so simple as %HH codes - for performance reasons. This change makes the same thing for the URL parser's two URL-encoding loops. Closes #10384 - urlapi: skip path checks if path is just "/" As a miniscule optimization, treat a path of the length 1 as the same as non-existing, as it can only be a single leading slash, and that's what we do for no paths as well. Closes #10385 Philip Heiduck (1 Feb 2023) - GHA/macos: use Xcode_14.0.1 for cmake builds Fixes #10356 Closes #10381 Viktor Szakats (1 Feb 2023) - tls: fixes for wolfssl + openssl combo builds 1. Add `USE_WOLFSSL` to the TLS backend priority list in `lib/curl_ntlm_core.c`. 2. Fix `lib/curl_ntlm_core.h` to respect TLS backend priority, bringing it in sync with the above list and `lib/curl_ntlm_core.c` itself. Reported-by: Mark Roszko Ref: https://github.com/curl/curl/issues/10321 3. Allow enabling both wolfSSL and OpenSSL at the same time in `lib/Makefile.mk` bringing this in line with cmake/autotools builds. Update logic to select the crypto-specific lib for `ngtcp2`, which supports a single TLS backend at the same time. Closes #10322 Daniel Stenberg (1 Feb 2023) - RELEASE-NOTES: synced - docs/INSTALL: document how to use multiple TLS backends And document how OpenSSL forks and wolfSSL cannot be used at the same time. Reported-by: Mark Roszko Fixes #10321 Closes #10382 Kvarec Lezki (1 Feb 2023) - cookies: fp is always not NULL Closes #10383 Daniel Stenberg (31 Jan 2023) - escape: use table lookup when adding %-codes to output On my dev host, this code runs 7.8 times faster. Closes #10377 - unit2600: avoid error: ‘TEST_CASES’ defined but not used Follow-up to d55de24dce9d51 Closes #10379 - escape: hex decode with a lookup-table Makes the decoding 2.8 times faster in my tests. Closes #10376 - cf-socket: fix build error wo TCP_FASTOPEN_CONNECT Follow-up to 5651a36d1a Closes #10378 Reviewed-by: Stefan Eissing Stefan Eissing (31 Jan 2023) - CI: add pytest github workflow to CI test/tests-httpd on a HTTP/3 setup Closes #10317 - connect: fix strategy testing for attempts, timeouts and happy-eyeball - add test2600 as a unit test that triggers various connect conditions and monitors behaviour, available in a debug build only. - this exposed edge cases in connect.c that have been fixed Closes #10312 - cf-socket: improvements in socket I/O handling - Curl_write_plain/Curl_read_plain have been eliminated. Last code use now uses Curl_conn_send/recv so that requests use conn->send/revc callbacks which defaults to cfilters use. - Curl_recv_plain/Curl_send_plain have been internalized in cf-socket.c. - USE_RECV_BEFORE_SEND_WORKAROUND (active on Windows) has been moved into cf-socket.c. The pre_recv buffer is held at the socket filter context. `postponed_data` structures have been removed from `connectdata`. - the hanger in HTTP/2 request handling was a result of read buffering on all sends and the multi handling is not prepared for this. The following happens: - multi preforms on a HTTP/2 easy handle - h2 reads and processes data - this leads to a send of h2 data - which receives and buffers before the send - h2 returns - multi selects on the socket, but no data arrives (its in the buffer alre ady) the workaround now receives data in a loop as long as there is something i n the buffer. The real fix would be for multi to change, so that `data_pendi ng` is evaluated before deciding to wait on the socket. io_buffer, optional, in cf-socket.c, http/2 sets state.drain if lower filter have pending data. This io_buffer is only available/used when the -DUSE_RECV_BEFORE_SEND_WORKAROUND is active, e.g. on Windows configurations. It also maintains the original checks on protocol handler being HTTP and conn->send/recv not being replaced. The HTTP/2 (nghttp2) cfilter now sets data->state.drain when it finds out that the "lower" filter chain has still pending data at the end of its IO operation. This prevents the processing from becoming stalled. Closes #10280 Daniel Stenberg (31 Jan 2023) - openssl: only use CA_BLOB if verifying peer Reported-by: Paul Groke Bug: https://curl.se/mail/lib-2023-01/0070.html Fixes #10351 Closes #10359 Thomas1664 on github (31 Jan 2023) - curl_free.3: fix return type of `curl_free` Fixes #10373 Closes #10374 Daniel Stenberg (30 Jan 2023) - zuul: stop using this CI service The important jobs have already transitioned. The remaining ones we can skip for now. Closes #10368 - copyright: remove "m4/ax_compile_check_sizeof.m4" from skips and report if skipped files do not exist. Follow-up to 9e11c2791fb960758 which removed the file. Closes #10369 - ws: unstick connect-only shutdown As this mode uses blocking sockets, it must set them back to non-blocking in disconnect to avoid the risk of getting stuck. Closes #10366 - ws: remove bad assert Reported-by: Stanley Wucw Fixes #10347 Closes #10366 - openssl: adapt to boringssl's error code type BoringSSL uses uint32_t, OpenSSL uses 'unsigned 'long' Closes #10360 - tool_operate: repair --rate Regression from a55256cfb242 (7.87.0) Reported-by: highmtworks on github Fixes #10357 Closes #10358 - dict: URL decode the entire path always Reported-by: dekerser on github Fixes #10298 Closes #10354 Stefan Eissing (29 Jan 2023) - vtls: do not null-check when we already assume cf-ctx exists Fixes #10361 Closes #10362 Daniel Stenberg (29 Jan 2023) - RELEASE-NOTES: synced - CURLOPT_READFUNCTION.3: the callback 'size' arg is always 1 Reported-by: Brian Green Fixes #10328 Closes #10355 - copyright.pl: cease doing year verifications As we have (mostly) removed the copyright year ranges. Reported-by: Ryan Schmidt Fixes #10345 Closes #10352 Dan Fandrich (28 Jan 2023) - CI: Work around a labeler bug that removes labels Jay Satiro (26 Jan 2023) - write-out.d: clarify Windows % symbol escaping - Clarify that in Windows batch files the % must be escaped as %%, and at the command prompt it cannot be escaped which could lead to incorrect expansion. Prior to this change the doc implied % must be escaped as %% in win32 always. --- Examples showing how a write-out argument is received by curl: If curl --write-out "%{http_code}" is executed in a batch file: {http_code} If curl --write-out "%%{http_code}" is executed in a batch file: %{http_code} If curl --write-out "%{http_code}" is executed from the command prompt: %{http_code} If curl --write-out "%%{http_code}" is executed from the command prompt: %%{http_code} At the command prompt something like "%{speed_download}%{http_code}" would first be parsed by the command interpreter as %{speed_download}% and would be expanded as environment variable {speed_download} if it existed, though that's highly unlikely since Windows environment names don't use braces. --- Reported-by: Muhammad Hussein Ammari Ref: https://github.com/bagder/everything-curl/pull/279 Fixes https://github.com/curl/curl/issues/10323 Closes https://github.com/curl/curl/pull/10337 Ryan Schmidt (26 Jan 2023) - connect: Fix build when not ENABLE_IPV6 Check for ENABLE_IPV6 before accessing AF_INET6. Fixes build failure introduced in 1c5d8ac. Closes https://github.com/curl/curl/pull/10344 - cf-socket: Fix build when not HAVE_GETPEERNAME Remove remaining references to conn and sockfd, which were removed from the function signature when conninfo_remote was renamed to conn_set_primary_ip in 6a8d7ef. Closes https://github.com/curl/curl/pull/10343 Stefan Eissing (26 Jan 2023) - vtls: Manage current easy handle in nested cfilter calls The previous implementation cleared `data` so the outer invocation lost its data, which could lead to a crash. Bug: https://github.com/curl/curl/issues/10336 Reported-by: Fujii Hironori Closes https://github.com/curl/curl/pull/10340 Dan Fandrich (25 Jan 2023) - CI: Add even more paths to the labeler config (#10326) - scripts: Fix Appveyor job detection in cijobs.pl The reorganization in #9769 broke the script. This should probably be rewritten to use a YAML parser for better upward compatibility. - CI: Add a few more paths to the labeler config (#10326) - CI: Switch the labeler event to pull_request_target Otherwise, the action won't work on PRs from forked repositories (#10326). Viktor Szakats (25 Jan 2023) - cmake: delete redundant macro definition `SECURITY_WIN32` Stop explicitly defining `SECURITY_WIN32` in CMake builds. No other build systems define this macro, because it's unconditionally defined in `lib/curl_sspi.h` already. This is the only curl source using the `sspi.h` and `security.h` Win32 headers, and no other Win32 headers need this macro. Reviewed-by: Jay Satiro Closes #10341 Fredrik (24 Jan 2023) - winbuild: document that arm64 is supported Building an arm64 version works flawlessly with the VS arm64 toolset. Closes https://github.com/curl/curl/pull/10332 Cherish98 (24 Jan 2023) - openssl: don't log raw record headers - Skip content type SSL3_RT_HEADER in verbose TLS output. This commit prevents bogus and misleading verbose TLS header messages as discussed in #10299. Assisted-by: Peter Wu Closes https://github.com/curl/curl/pull/10299 Marc Aldorasi (24 Jan 2023) - cmake: use list APPEND syntax for CMAKE_REQUIRED_DEFINITIONS - Use list() instead of set() for CMAKE_REQUIRED_DEFINITIONS list since the former is clearer. Closes https://github.com/curl/curl/pull/10272 Dan Fandrich (23 Jan 2023) - CI: Add a workflow to automatically label pull requests The labeler language is quite restrictive right now so labels are added quite conservatively, meaning that many PRs won't get labels when it's "obvious" they should. It will still save some manual work on those that it can label. Jay Satiro (21 Jan 2023) - system.h: assume OS400 is always built with ILEC compiler Prior to this change the OS400 types were only defined when __ILEC400__. That symbol is only defined by IBM's C compiler and not their C++ compiler, which led to missing types when users on OS400 would compile a C++ application that included curl. The IBM C and C++ compilers are the only native compilers on the platform. Assisted-by: Jon Rumsey Reported-by: John Sherrill Fixes https://github.com/curl/curl/issues/10305 Closes https://github.com/curl/curl/pull/10329 xgladius (20 Jan 2023) - cmake: Remove deprecated symbols check curl stopped use of CMAKE_USE_ as a prefix for its own build symbols in 2021 and added a check, meant to last 1 year, to fatally error on those symbols. This commit removes that check. Closes https://github.com/curl/curl/pull/10314 Dan Fandrich (20 Jan 2023) - docs: POSTFIELDSIZE must be set to -1 with read function Reported-by: RanBarLavie on github Closes #10313 Stefan Eissing (20 Jan 2023) - vtls: fix hostname handling in filters - Copy the hostname and dispname to ssl_connect_data. Use a copy instead of referencing the `connectdata` instance since this may get free'ed on connection reuse. Reported-by: Stefan Talpalaru Reported-by: sergio-nsk@users.noreply.github.com Fixes https://github.com/curl/curl/issues/10273 Fixes https://github.com/curl/curl/issues/10309 Closes https://github.com/curl/curl/pull/10310 Sergey Bronnikov (17 Jan 2023) - lib: fix typos Closes https://github.com/curl/curl/pull/10307 - curl_version_info.3: fix typo Closes https://github.com/curl/curl/pull/10306 Jay Satiro (17 Jan 2023) - openssl: Don't ignore CA paths when using Windows CA store (redux) .. and remove 'experimental' designation from CURLSSLOPT_NATIVE_CA. This commit restores the behavior of CURLSSLOPT_NATIVE_CA so that it does not override CURLOPT_CAINFO / CURLOPT_CAPATH, or the hardcoded default locations. Instead the native Windows CA store can be used at the same time. --- This behavior was originally added over two years ago in abbc5d60 (#5585) but then 83393b1a (#7892) broke it over a year ago, I assume inadvertently. The CURLSSLOPT_NATIVE_CA feature was marked experimental and likely rarely used. Ref: https://github.com/curl/curl/pull/5585 Ref: https://github.com/curl/curl/pull/7892 Ref: https://curl.se/mail/lib-2023-01/0019.html Closes https://github.com/curl/curl/pull/10244 Daniel Stenberg (13 Jan 2023) - RELEASE-NOTES: synced - ws: fix autoping handling Reported-by: Alexey Savchuk Fixes #10289 Closes #10294 - curl_log: avoid printf() format checking with mingw Since it does not seem to like %zu and more Follow-up to db91dbbf2 Fixes #10291 Closes #10292 - tool_getparam: fix compiler warning when !HAVE_WRITABLE_ARGV Follow-up to 2ed0e1f70ee176edf3d2 Closes #10286 Stefan Eissing (12 Jan 2023) - openssl: make the BIO_METHOD a local variable in the connection filter This avoids UAF issues when `curl_global_cleanup()` is called before all transfers have been completely handled. Unfortunately this seems to be a more common pattern than we like. Closes #10285 Daniel Stenberg (12 Jan 2023) - curl: output warning at --verbose output for debug-enabled version + a libcurl warning in the debug output Assisted-by: Jay Satiro Ref: https://curl.se/mail/lib-2023-01/0039.html Closes #10278 - src: add --http3-only Warning: --http3 and --http3-only are subject to change again (or be removed) before HTTP/3 support goes non-experimental. Closes #10264 - curl.h: add CURL_HTTP_VERSION_3ONLY As the previous CURL_HTTP_VERSION_3 option gets a slightly altered meaning. Closes #10264 - connect: fix access of pointer before NULL check Detected by Coverity CID 1518992 Closes #10284 Daniel Gustafsson (12 Jan 2023) - easyoptions: Fix header printing in generation script The optiontable.pl script prints the header comment when generating easyoptions.c, but it wasn't escaping all characters which jumbled the curl ascii logo. Fix by escaping. Cloes #10275 Harry Sintonen (12 Jan 2023) - tool_getparam: fix hiding of command line secrets Closes #10276 Stefan Eissing (12 Jan 2023) - tests: document the cfilter debug logging options Closes #10283 - curl_log: for failf/infof and debug logging implementations - new functions and macros for cfilter debugging - set CURL_DEBUG with names of cfilters where debug logging should be enabled - use GNUC __attribute__ to enable printf format checks during compile Closes #10271 Daniel Stenberg (10 Jan 2023) - RELEASE-NOTES: synced Nick Banks (10 Jan 2023) - msh3: update to v0.6 Closes #10192 Stefan Eissing (10 Jan 2023) - ngtcp2: add CURLOPT_SSL_CTX_FUNCTION support for openssl+wolfssl Using common method for SSL_CTX initialization of verfiy peer and CA settings. This also provides X509_STORE sharing to become available for ngtcp2+openssl HTTP/3. Reported-by: violetlige on github Fixes #10222 Closes #10239 Daniel Stenberg (10 Jan 2023) - cf-socket: make infof() call use %zu for size_t output Detected by Coverity CID 1518986 and CID 1518984 Closes #10268 Jon Rumsey (10 Jan 2023) - os400: fixes to make-lib.sh and initscript.sh Adjust how exports list is generated from header files to account for declarations across multiple lines and CURL_DEPRECATED(...) tags. Update initscript.sh Specify qadrt_use_inline to prevent unistd.h in ASCII runtime defining close(a) -> close_a(a) Fixes #10266 Closes #10267 Stefan Eissing (9 Jan 2023) - tests-httpd: basic infra to run curl against an apache httpd plus nghttpx for h3 - adding '--with-test-httpd=<path>' to configure non-standard apache2 install - python env and base classes for running httpd - basic tests for connectivity with h1/h2/h3 - adding test cases for truncated responses in http versions. - adding goaway test for HTTP/3. - adding "stuttering" tests with parallel downloads in chunks with varying delays between chunks. - adding a curltest module to the httpd server, adding GOAWAY test. - mod_curltest now installs 2 handlers - 'echo': writing as response body what came as request body - 'tweak': with query parameters to tweak response behaviour - marked known fails as skip for now Closes #10175 - quic: improve connect error message, debugging info, fix false connect report - ECONNECTREFUSED has not its own fail message in quic filters - Debug logging in connect eyballing improved - Fix bug in ngtcp2/quiche that could lead to false success reporting. Reported-by: Divy Le Ray Fixes #10245 Closes #10248 - quiche: fix build without any HTTP/2 implementation Fixes #10260 Closes #10263 Daniel Stenberg (9 Jan 2023) - .github/workflows/linux.yml: add a quiche CI job Move over from zuul Closes #10241 - curl.h: allow up to 10M buffer size Bump the limit from 512K. There might be reasons for applications using h3 to set larger buffers and there is no strong reason for curl to have a very small maximum. Ref: https://curl.se/mail/lib-2023-01/0026.html Closes #10256 Tatsuhiro Tsujikawa (8 Jan 2023) - GHA: use designated ngtcp2 and its dependencies versions Designate ngtcp2 and its dependency versions so that the CI build does not fail without our control. Closes #10257 Daniel Stenberg (8 Jan 2023) - docs/cmdline-opts/hsts.d: explain hsts more Closes #10258 Stefan Eissing (8 Jan 2023) - msh3: run again in its cfilter - test 2500, single GET works - test 2501, single POST stalls - test 2502, multiple, sequential GETs each use a new connection since MsH3ConnectionGetState(qconn) no longer reports CONNECTED after one GET. Closes #10204 Jay Satiro (8 Jan 2023) - sendf: fix build for Linux TCP fastopen - Fix the remote addr struct dereference. - Include cf-socket.h in urldata.h. Follow-up to 6a8d7ef9 which changed conn->ipaddr (Curl_addrinfo* ) member to conn->remote_addr (Curl_sockaddr_ex *) several days ago. Reported-by: Stephan Guilloux Fixes https://github.com/curl/curl/issues/10249 Closes https://github.com/curl/curl/pull/10250 Daniel Stenberg (7 Jan 2023) - RELEASE-NOTES: synced - setopt: move the SHA256 opt within #ifdef libssh2 Because only the libssh2 backend not supports it and thus this should return error if this option is used other backends. Reported-by: Harry Sintonen Closes #10255 Patrick Monnerat (7 Jan 2023) - nss: implement data_pending method NSS currently uses the default Curl_none_data_pending() method which always returns false, causing TLS buffered input data to be missed. The current commit implements the nss_data_pending() method that properly monitors the presence of available TLS data. Ref:#10077 Closes #10225 Jay Satiro (6 Jan 2023) - CURLOPT_HEADERDATA.3: warn DLL users must set write function - Warn that in Windows if libcurl is running from a DLL and if CURLOPT_HEADERDATA is set then CURLOPT_WRITEFUNCTION or CURLOPT_HEADERFUNCTION must be set as well, otherwise the user may experience crashes. We already have a similar warning in CURLOPT_WRITEDATA. Basically, in Windows libcurl could crash writing a FILE pointer that was created by a different C runtime. In Windows each DLL that is part of a program may or may not have its own C runtime. Ref: https://github.com/curl/curl/issues/10231 Closes https://github.com/curl/curl/pull/10233 Jon Rumsey (5 Jan 2023) - x509asn1: fix compile errors and warnings Various small issues when built for GSKit Closes #10238 Patrick Monnerat (5 Jan 2023) - runtests: fix detection of TLS backends Built-in TLS backends are detected at test time by scanning for their names in the version string line returned by the cli tool: as this line may also list the libssh configuration that mentions its own backend, the curl backend may be wrongly determined. In example, if the version line contains "libssh/0.10.4/openssl/zlib", OpenSSL is detected as a curl-configured backend even if not. This fix requires the backend names to appear as full words preceded by spacing in the version line to be recognized as curl TLS backends. Closes #10236 Andy Alt (5 Jan 2023) - GHA: add job on Slackware 15.0 Closes #10230 Daniel Stenberg (5 Jan 2023) - test363: make even smaller writes to loop more - http_proxy: do not assign data->req.p.http use local copy Avoid the tricky reusing of the data->req.p.http pointer for http proxy tunneling. Fixes #10194 Closes #10234 Stefan Eissing (5 Jan 2023) - quic: rename vquic implementations, fix for quiche build. - quiche in debug mode did not build, fixed. - moved all vquic implementation files to prefix curl_* to avoid the potential mixups between provided .h files and our own. - quich passes test 2500 and 2502. 2501, the POST, fail with the body being rejected. Quich bug? Closes #10242 - sectransp: fix for incomplete read/writes SecureTransport expects result code errSSLWouldBlock when the requested length could not be sent/recieved in full. The previous code returned noErr, which let SecureTransport to believe that the IO had terminated prematurely. Fixes #10227 Closes #10235 Andy Alt (5 Jan 2023) - GHA: Hacktoberfest CI: Update deprecated 'set-output' command Closes #10221 Jay Satiro (5 Jan 2023) - scripts: set file mode +x on all perl and shell scripts - Set all scripts +x, ie 644 => 755. Prior to this change some scripts were not executable and therefore could not be called directly. ~~~ git ls-files -s \*.{sh,pl,py} | grep -v 100755 ~~~ Closes https://github.com/curl/curl/pull/10219 Stefan Eissing (4 Jan 2023) - tool_operate: fix headerfile writing Do not rely on the first transfer started to be the first to get a response (remember -Z). All transfers now write the headefile (-D) in append mode, making sure that the order of transfer responses does not lead to overwrites of previous data. Closes #10224 Daniel Stenberg (4 Jan 2023) - misc: reduce struct and struct field sizes - by using BIT() instead of bool - imap: shrink struct - ftp: make state 'unsigned char' - ftp: sort ftp_conn struct entries on size - urldata: use smaller fields for SSL version info storage - pop3: reduce the pop3_conn struct size - smtp: reduce the size of the smtp structs Closes #10186 - noproxy: support for space-separated names is deprecated To be removed in July 2024. Assisted-by: Michael Osipov Fixes #10209 Closes #10215 Andrei Rybak (4 Jan 2023) - lib: fix typos in comments which repeat a word Remove erroneously duplicated words in code comments of files `lib.connect.c` and `lib/url.c`. Closes #10220 Radek Brich (3 Jan 2023) - cmake: set SOVERSION also for macOS Closes #10214 Jay Satiro (3 Jan 2023) - http2: fix compiler warning due to uninitialized variable Prior to this change http2_cfilter_add could return an uninitialized cfilter pointer in an OOM condition. In this case though, the pointer is discarded and not dereferenced so there was no risk of a crash. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/FEATURES.md��������������������������������������������������������������������������0000644�����������������00000013253�15253042577�0011106 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Features -- what curl can do ## curl tool - config file support - multiple URLs in a single command line - range "globbing" support: [0-13], {one,two,three} - multiple file upload on a single command line - custom maximum transfer rate - redirect stderr - parallel transfers ## libcurl - full URL syntax with no length limit - custom maximum download time - custom least download speed acceptable - custom output result after completion - guesses protocol from host name unless specified - uses .netrc - progress bar with time statistics while downloading - "standard" proxy environment variables support - compiles on win32 (reported builds on 70+ operating systems) - selectable network interface for outgoing traffic - IPv6 support on Unix and Windows - happy eyeballs dual-stack connects - persistent connections - SOCKS 4 + 5 support, with or without local name resolving - supports user name and password in proxy environment variables - operations through HTTP proxy "tunnel" (using CONNECT) - replaceable memory functions (malloc, free, realloc, etc) - asynchronous name resolving (6) - both a push and a pull style interface - international domain names (10) ## HTTP - HTTP/0.9 responses are optionally accepted - HTTP/1.0 - HTTP/1.1 - HTTP/2, including multiplexing and server push (5) - GET - PUT - HEAD - POST - multipart formpost (RFC 1867-style) - authentication: Basic, Digest, NTLM (9) and Negotiate (SPNEGO) (3) to server and proxy - resume (both GET and PUT) - follow redirects - maximum amount of redirects to follow - custom HTTP request - cookie get/send fully parsed - reads/writes the Netscape cookie file format - custom headers (replace/remove internally generated headers) - custom user-agent string - custom referrer string - range - proxy authentication - time conditions - via HTTP proxy, HTTPS proxy or SOCKS proxy - retrieve file modification date - Content-Encoding support for deflate and gzip - "Transfer-Encoding: chunked" support in uploads - automatic data compression (11) ## HTTPS (1) - (all the HTTP features) - HTTP/3 experimental support - using client certificates - verify server certificate - via HTTP proxy, HTTPS proxy or SOCKS proxy - select desired encryption - select usage of a specific SSL version ## FTP - download - authentication - Kerberos 5 (12) - active/passive using PORT, EPRT, PASV or EPSV - single file size information (compare to HTTP HEAD) - 'type=' URL support - dir listing - dir listing names-only - upload - upload append - upload via http-proxy as HTTP PUT - download resume - upload resume - custom ftp commands (before and/or after the transfer) - simple "range" support - via HTTP proxy, HTTPS proxy or SOCKS proxy - all operations can be tunneled through proxy - customizable to retrieve file modification date - no dir depth limit ## FTPS (1) - implicit `ftps://` support that use SSL on both connections - explicit "AUTH TLS" and "AUTH SSL" usage to "upgrade" plain `ftp://` connection to use SSL for both or one of the connections ## SCP (8) - both password and public key auth ## SFTP (7) - both password and public key auth - with custom commands sent before/after the transfer ## TFTP - download - upload ## TELNET - connection negotiation - custom telnet options - stdin/stdout I/O ## LDAP (2) - full LDAP URL support ## DICT - extended DICT URL support ## FILE - URL support - upload - resume ## SMB - SMBv1 over TCP and SSL - download - upload - authentication with NTLMv1 ## SMTP - authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (9), Kerberos 5 (4) and External. - send emails - mail from support - mail size support - mail auth support for trusted server-to-server relaying - multiple recipients - via http-proxy ## SMTPS (1) - implicit `smtps://` support - explicit "STARTTLS" usage to "upgrade" plain `smtp://` connections to use SSL - via http-proxy ## POP3 - authentication: Clear Text, APOP and SASL - SASL based authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (9), Kerberos 5 (4) and External. - list emails - retrieve emails - enhanced command support for: CAPA, DELE, TOP, STAT, UIDL and NOOP via custom requests - via http-proxy ## POP3S (1) - implicit `pop3s://` support - explicit `STLS` usage to "upgrade" plain `pop3://` connections to use SSL - via http-proxy ## IMAP - authentication: Clear Text and SASL - SASL based authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM (9), Kerberos 5 (4) and External. - list the folders of a mailbox - select a mailbox with support for verifying the `UIDVALIDITY` - fetch emails with support for specifying the UID and SECTION - upload emails via the append command - enhanced command support for: EXAMINE, CREATE, DELETE, RENAME, STATUS, STORE, COPY and UID via custom requests - via http-proxy ## IMAPS (1) - implicit `imaps://` support - explicit "STARTTLS" usage to "upgrade" plain `imap://` connections to use SSL - via http-proxy ## MQTT - Subscribe to and publish topics using URL scheme `mqtt://broker/topic` ## Footnotes 1. requires a TLS library 2. requires OpenLDAP or WinLDAP 3. requires a GSS-API implementation (such as Heimdal or MIT Kerberos) or SSPI (native Windows) 4. requires a GSS-API implementation, however, only Windows SSPI is currently supported 5. requires nghttp2 6. requires c-ares 7. requires libssh2, libssh or wolfSSH 8. requires libssh2 or libssh 9. requires OpenSSL, GnuTLS, mbedTLS, NSS, Secure Transport or SSPI (native Windows) 10. requires libidn2 or Windows 11. requires libz, brotli and/or zstd 12. requires a GSS-API implementation (such as Heimdal or MIT Kerberos) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc/ea-libcurl/FAQ����������������������������������������������������������������������������������0000644�����������������00000203155�15253042577�0007702 0����������������������������������������������������������������������������������������������������ustar�00������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | | (__| |_| | _ <| |___ \___|\___/|_| \_\_____| FAQ 1. Philosophy 1.1 What is cURL? 1.2 What is libcurl? 1.3 What is curl not? 1.4 When will you make curl do XXXX ? 1.5 Who makes curl? 1.6 What do you get for making curl? 1.7 What about CURL from curl.com? 1.8 I have a problem, who do I mail? 1.9 Where do I buy commercial support for curl? 1.10 How many are using curl? 1.11 Why do you not update ca-bundle.crt 1.12 I have a problem, who can I chat with? 1.13 curl's ECCN number? 1.14 How do I submit my patch? 1.15 How do I port libcurl to my OS? 2. Install Related Problems 2.1 configure fails when using static libraries 2.2 Does curl work/build with other SSL libraries? 2.4 Does curl support SOCKS (RFC 1928) ? 3. Usage Problems 3.1 curl: (1) SSL is disabled, https: not supported 3.2 How do I tell curl to resume a transfer? 3.3 Why does my posting using -F not work? 3.4 How do I tell curl to run custom FTP commands? 3.5 How can I disable the Accept: */* header? 3.6 Does curl support ASP, XML, XHTML or HTML version Y? 3.7 Can I use curl to delete/rename a file through FTP? 3.8 How do I tell curl to follow HTTP redirects? 3.9 How do I use curl in my favorite programming language? 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? 3.11 How do I POST with a different Content-Type? 3.12 Why do FTP-specific features over HTTP proxy fail? 3.13 Why do my single/double quotes fail? 3.14 Does curl support JavaScript or PAC (automated proxy config)? 3.15 Can I do recursive fetches with curl? 3.16 What certificates do I need when I use SSL? 3.17 How do I list the root directory of an FTP server? 3.18 Can I use curl to send a POST/PUT and not wait for a response? 3.19 How do I get HTTP from a host using a specific IP address? 3.20 How to SFTP from my user's home directory? 3.21 Protocol xxx not supported or disabled in libcurl 3.22 curl -X gives me HTTP problems 4. Running Problems 4.2 Why do I get problems when I use & or % in the URL? 4.3 How can I use {, }, [ or ] to specify multiple URLs? 4.4 Why do I get downloaded data even though the web page does not exist? 4.5 Why do I get return code XXX from an HTTP server? 4.5.1 "400 Bad Request" 4.5.2 "401 Unauthorized" 4.5.3 "403 Forbidden" 4.5.4 "404 Not Found" 4.5.5 "405 Method Not Allowed" 4.5.6 "301 Moved Permanently" 4.6 Can you tell me what error code 142 means? 4.7 How do I keep user names and passwords secret in curl command lines? 4.8 I found a bug 4.9 curl cannot authenticate to a server that requires NTLM? 4.10 My HTTP request using HEAD, PUT or DELETE does not work 4.11 Why do my HTTP range requests return the full document? 4.12 Why do I get "certificate verify failed" ? 4.13 Why is curl -R on Windows one hour off? 4.14 Redirects work in browser but not with curl 4.15 FTPS does not work 4.16 My HTTP POST or PUT requests are slow 4.17 Non-functional connect timeouts on Windows 4.18 file:// URLs containing drive letters (Windows, NetWare) 4.19 Why does not curl return an error when the network cable is unplugged? 4.20 curl does not return error for HTTP non-200 responses 5. libcurl Issues 5.1 Is libcurl thread-safe? 5.2 How can I receive all data into a large memory chunk? 5.3 How do I fetch multiple files with libcurl? 5.4 Does libcurl do Winsock initialization on win32 systems? 5.5 Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on win32 ? 5.6 What about Keep-Alive or persistent connections? 5.7 Link errors when building libcurl on Windows 5.8 libcurl.so.X: open failed: No such file or directory 5.9 How does libcurl resolve host names? 5.10 How do I prevent libcurl from writing the response to stdout? 5.11 How do I make libcurl not receive the whole HTTP response? 5.12 Can I make libcurl fake or hide my real IP address? 5.13 How do I stop an ongoing transfer? 5.14 Using C++ non-static functions for callbacks? 5.15 How do I get an FTP directory listing? 5.16 I want a different time-out 5.17 Can I write a server with libcurl? 5.18 Does libcurl use threads? 6. License Issues 6.1 I have a GPL program, can I use the libcurl library? 6.2 I have a closed-source program, can I use the libcurl library? 6.3 I have a BSD licensed program, can I use the libcurl library? 6.4 I have a program that uses LGPL libraries, can I use libcurl? 6.5 Can I modify curl/libcurl for my program and keep the changes secret? 6.6 Can you please change the curl/libcurl license to XXXX? 6.7 What are my obligations when using libcurl in my commercial apps? 7. PHP/CURL Issues 7.1 What is PHP/CURL? 7.2 Who wrote PHP/CURL? 7.3 Can I perform multiple requests using the same handle? 7.4 Does PHP/CURL have dependencies? 8. Development 8.1 Why does curl use C89? 8.2 Will curl be rewritten? ============================================================================== 1. Philosophy 1.1 What is cURL? cURL is the name of the project. The name is a play on 'Client for URLs', originally with URL spelled in uppercase to make it obvious it deals with URLs. The fact it can also be read as 'see URL' also helped, it works as an abbreviation for "Client URL Request Library" or why not the recursive version: "curl URL Request Library". The cURL project produces two products: libcurl A client-side URL transfer library, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password authentication, file transfer resume, http proxy tunneling and more. libcurl is highly portable, it builds and works identically on numerous platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HP-UX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, macOS, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS, Symbian, OSF, Android, Minix, IBM TPF and more... libcurl is free, thread-safe, IPv6 compatible, feature rich, well supported and fast. curl A command line tool for getting or sending data using URL syntax. Since curl uses libcurl, curl supports the same wide range of common Internet protocols that libcurl does. We pronounce curl with an initial k sound. It rhymes with words like girl and earl. This is a short WAV file to help you: https://media.merriam-webster.com/soundc11/c/curl0001.wav There are numerous sub-projects and related projects that also use the word curl in the project names in various combinations, but you should take notice that this FAQ is directed at the command-line tool named curl (and libcurl the library), and may therefore not be valid for other curl-related projects. (There is however a small section for the PHP/CURL in this FAQ.) 1.2 What is libcurl? libcurl is a reliable and portable library for doing Internet data transfers using one or more of its supported Internet protocols. You can use libcurl freely in your application, be it open source, commercial or closed-source. libcurl is most probably the most portable, most powerful and most often used C-based multi-platform file transfer library on this planet - be it open source or commercial. 1.3 What is curl not? curl is not a wget clone. That is a common misconception. Never, during curl's development, have we intended curl to replace wget or compete on its market. curl is targeted at single-shot file transfers. curl is not a website mirroring program. If you want to use curl to mirror something: fine, go ahead and write a script that wraps around curl or use libcurl to make it reality. curl is not an FTP site mirroring program. Sure, get and send FTP with curl but if you want systematic and sequential behavior you should write a script (or write a new program that interfaces libcurl) and do it. curl is not a PHP tool, even though it works perfectly well when used from or with PHP (when using the PHP/CURL module). curl is not a program for a single operating system. curl exists, compiles, builds and runs under a wide range of operating systems, including all modern Unixes (and a bunch of older ones too), Windows, Amiga, OS/2, macOS, QNX etc. 1.4 When will you make curl do XXXX ? We love suggestions of what to change in order to make curl and libcurl better. We do however believe in a few rules when it comes to the future of curl: curl -- the command line tool -- is to remain a non-graphical command line tool. If you want GUIs or fancy scripting capabilities, you should look for another tool that uses libcurl. We do not add things to curl that other small and available tools already do well at the side. curl's output can be piped into another program or redirected to another file for the next program to interpret. We focus on protocol related issues and improvements. If you want to do more magic with the supported protocols than curl currently does, chances are good we will agree. If you want to add more protocols, we may agree. If you want someone else to do all the work while you wait for us to implement it for you, that is not a friendly attitude. We spend a considerable time already on maintaining and developing curl. In order to get more out of us, you should consider trading in some of your time and effort in return. Simply go to the GitHub repository which resides at https://github.com/curl/curl, fork the project, and create pull requests with your proposed changes. If you write the code, chances are better that it will get into curl faster. 1.5 Who makes curl? curl and libcurl are not made by any single individual. Daniel Stenberg is project leader and main developer, but other persons' submissions are important and crucial. Anyone can contribute and post their changes and improvements and have them inserted in the main sources (of course on the condition that developers agree that the fixes are good). The full list of all contributors is found in the docs/THANKS file. curl is developed by a community, with Daniel at the wheel. 1.6 What do you get for making curl? Project cURL is entirely free and open. We do this voluntarily, mostly in our spare time. Companies may pay individual developers to work on curl. This is not controlled by nor supervised in any way by the curl project. We get help from companies. Haxx provides website, bandwidth, mailing lists etc, GitHub hosts the primary git repository and other services like the bug tracker at https://github.com/curl/curl. Also again, some companies have sponsored certain parts of the development in the past and I hope some will continue to do so in the future. If you want to support our project, consider a donation or a banner-program or even better: by helping us with coding, documenting or testing etc. See also: https://curl.se/sponsors.html 1.7 What about CURL from curl.com? During the summer of 2001, curl.com was busy advertising their client-side programming language for the web, named CURL. We are in no way associated with curl.com or their CURL programming language. Our project name curl has been in effective use since 1998. We were not the first computer related project to use the name "curl" and do not claim any rights to the name. We recognize that we will be living in parallel with curl.com and wish them every success. 1.8 I have a problem, who do I mail? Please do not mail any single individual unless you really need to. Keep curl-related questions on a suitable mailing list. All available mailing lists are listed in the MANUAL document and online at https://curl.se/mail/ Keeping curl-related questions and discussions on mailing lists allows others to join in and help, to share their ideas, to contribute their suggestions and to spread their wisdom. Keeping discussions on public mailing lists also allows for others to learn from this (both current and future users thanks to the web based archives of the mailing lists), thus saving us from having to repeat ourselves even more. Thanks for respecting this. If you have found or simply suspect a security problem in curl or libcurl, submit all the details at https://hackerone.one/curl. On there we keep the issue private while we investigate, confirm it, work and validate a fix and agree on a time schedule for publication etc. That way we produce a fix in a timely manner before the flaw is announced to the world, reducing the impact the problem risks having on existing users. Security issues can also be taking to the curl security team by emailing security at curl.se (closed list of receivers, mails are not disclosed). 1.9 Where do I buy commercial support for curl? curl is fully open source. It means you can hire any skilled engineer to fix your curl-related problems. We list available alternatives on the curl website: https://curl.se/support.html 1.10 How many are using curl? It is impossible to tell. We do not know how many users that knowingly have installed and use curl. We do not know how many users that use curl without knowing that they are in fact using it. We do not know how many users that downloaded or installed curl and then never use it. In 2020, we estimate that curl runs in roughly ten billion installations world wide. 1.11 Why do you not update ca-bundle.crt In the cURL project we have decided not to attempt to keep this file updated (or even present) since deciding what to add to a ca cert bundle is an undertaking we have not been ready to accept, and the one we can get from Mozilla is perfectly fine so there is no need to duplicate that work. Today, with many services performed over HTTPS, every operating system should come with a default ca cert bundle that can be deemed somewhat trustworthy and that collection (if reasonably updated) should be deemed to be a lot better than a private curl version. If you want the most recent collection of ca certs that Mozilla Firefox uses, we recommend that you extract the collection yourself from Mozilla Firefox (by running 'make ca-bundle), or by using our online service setup for this purpose: https://curl.se/docs/caextract.html 1.12 I have a problem who, can I chat with? There is a bunch of friendly people hanging out in the #curl channel on the IRC network libera.chat. If you are polite and nice, chances are good that you can get -- or provide -- help instantly. 1.13 curl's ECCN number? The US government restricts exports of software that contains or uses cryptography. When doing so, the Export Control Classification Number (ECCN) is used to identify the level of export control etc. Apache Software Foundation gives a good explanation of ECCNs at https://www.apache.org/dev/crypto.html We believe curl's number might be ECCN 5D002, another possibility is 5D992. It seems necessary to write them (the authority that administers ECCN numbers), asking to confirm. Comprehensible explanations of the meaning of such numbers and how to obtain them (resp.) are here https://www.bis.doc.gov/licensing/exportingbasics.htm https://www.bis.doc.gov/licensing/do_i_needaneccn.html An incomprehensible description of the two numbers above is here https://www.bis.doc.gov/index.php/documents/new-encryption/1653-ccl5-pt2-3 1.14 How do I submit my patch? We strongly encourage you to submit changes and improvements directly as "pull requests" on GitHub: https://github.com/curl/curl/pulls If you for any reason cannot or will not deal with GitHub, send your patch to the curl-library mailing list. We are many subscribers there and there are lots of people who can review patches, comment on them and "receive" them properly. Lots of more details are found in the CONTRIBUTE.md and INTERNALS.md documents. 1.15 How do I port libcurl to my OS? Here's a rough step-by-step: 1. copy a suitable lib/config-*.h file as a start to lib/config-[youros].h 2. edit lib/config-[youros].h to match your OS and setup 3. edit lib/curl_setup.h to include config-[youros].h when your OS is detected by the preprocessor, in the style others already exist 4. compile lib/*.c and make them into a library 2. Install Related Problems 2.1 configure fails when using static libraries You may find that configure fails to properly detect the entire dependency chain of libraries when you provide static versions of the libraries that configure checks for. The reason why static libraries is much harder to deal with is that for them we do not get any help but the script itself must know or check what more libraries that are needed (with shared libraries, that dependency "chain" is handled automatically). This is a error-prone process and one that also tends to vary over time depending on the release versions of the involved components and may also differ between operating systems. For that reason, configure does few attempts to actually figure this out and you are instead encouraged to set LIBS and LDFLAGS accordingly when you invoke configure, and point out the needed libraries and set the necessary flags yourself. 2.2 Does curl work with other SSL libraries? curl has been written to use a generic SSL function layer internally, and that SSL functionality can then be provided by one out of many different SSL backends. curl can be built to use one of the following SSL alternatives: OpenSSL, libressl, BoringSSL, AWS-LC, GnuTLS, wolfSSL, NSS, mbedTLS, Secure Transport (native iOS/OS X), Schannel (native Windows), GSKit (native IBM i), BearSSL, or Rustls. They all have their pros and cons, and we try to maintain a comparison of them here: https://curl.se/docs/ssl-compared.html 2.4 Does curl support SOCKS (RFC 1928) ? Yes, SOCKS 4 and 5 are supported. 3. Usage problems 3.1 curl: (1) SSL is disabled, https: not supported If you get this output when trying to get anything from an https:// server, it means that the instance of curl/libcurl that you are using was built without support for this protocol. This could have happened if the configure script that was run at build time could not find all libs and include files curl requires for SSL to work. If the configure script fails to find them, curl is simply built without SSL support. To get the https:// support into a curl that was previously built but that reports that https:// is not supported, you should dig through the document and logs and check out why the configure script does not find the SSL libs and/or include files. Also, check out the other paragraph in this FAQ labeled "configure does not find OpenSSL even when it is installed". 3.2 How do I tell curl to resume a transfer? curl supports resumed transfers both ways on both FTP and HTTP. Try the -C option. 3.3 Why does my posting using -F not work? You cannot arbitrarily use -F or -d, the choice between -F or -d depends on the HTTP operation you need curl to do and what the web server that will receive your post expects. If the form you are trying to submit uses the type 'multipart/form-data', then and only then you must use the -F type. In all the most common cases, you should use -d which then causes a posting with the type 'application/x-www-form-urlencoded'. This is described in some detail in the MANUAL and TheArtOfHttpScripting documents, and if you do not understand it the first time, read it again before you post questions about this to the mailing list. Also, try reading through the mailing list archives for old postings and questions regarding this. 3.4 How do I tell curl to run custom FTP commands? You can tell curl to perform optional commands both before and/or after a file transfer. Study the -Q/--quote option. Since curl is used for file transfers, you do not normally use curl to perform FTP commands without transferring anything. Therefore you must always specify a URL to transfer to/from even when doing custom FTP commands, or use -I which implies the "no body" option sent to libcurl. 3.5 How can I disable the Accept: */* header? You can change all internally generated headers by adding a replacement with the -H/--header option. By adding a header with empty contents you safely disable that one. Use -H "Accept:" to disable that specific header. 3.6 Does curl support ASP, XML, XHTML or HTML version Y? To curl, all contents are alike. It does not matter how the page was generated. It may be ASP, PHP, Perl, shell-script, SSI or plain HTML files. There is no difference to curl and it does not even know what kind of language that generated the page. See also item 3.14 regarding JavaScript. 3.7 Can I use curl to delete/rename a file through FTP? Yes. You specify custom FTP commands with -Q/--quote. One example would be to delete a file after you have downloaded it: curl -O ftp://download.com/coolfile -Q '-DELE coolfile' or rename a file after upload: curl -T infile ftp://upload.com/dir/ -Q "-RNFR infile" -Q "-RNTO newname" 3.8 How do I tell curl to follow HTTP redirects? curl does not follow so-called redirects by default. The Location: header that informs the client about this is only interpreted if you are using the -L/--location option. As in: curl -L http://redirector.com Not all redirects are HTTP ones, see 4.14 3.9 How do I use curl in my favorite programming language? Many programming languages have interfaces/bindings that allow you to use curl without having to use the command line tool. If you are fluent in such a language, you may prefer to use one of these interfaces instead. Find out more about which languages that support curl directly, and how to install and use them, in the libcurl section of the curl website: https://curl.se/libcurl/ All the various bindings to libcurl are made by other projects and people, outside of the cURL project. The cURL project itself only produces libcurl with its plain C API. If you do not find anywhere else to ask you can ask about bindings on the curl-library list too, but be prepared that people on that list may not know anything about bindings. In December 2021, there were interfaces available for the following languages: Ada95, Basic, C, C++, Ch, Cocoa, D, Delphi, Dylan, Eiffel, Euphoria, Falcon, Ferite, Gambas, glib/GTK+, Go, Guile, Harbour, Haskell, Java, Julia, Lisp, Lua, Mono, .NET, node.js, Object-Pascal, OCaml, Pascal, Perl, PHP, PostgreSQL, Python, R, Rexx, Ring, RPG, Ruby, Rust, Scheme, Scilab, S-Lang, Smalltalk, SP-Forth, SPL, Tcl, Visual Basic, Visual FoxPro, Q, wxwidgets, XBLite and Xoho. By the time you read this, additional ones may have appeared. 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? curl adheres to the HTTP spec, which basically means you can play with *any* protocol that is built on top of HTTP. Protocols such as SOAP, WEBDAV and XML-RPC are all such ones. You can use -X to set custom requests and -H to set custom headers (or replace internally generated ones). Using libcurl is of course just as good and you would just use the proper library options to do the same. 3.11 How do I POST with a different Content-Type? You can always replace the internally generated headers with -H/--header. To make a simple HTTP POST with text/xml as content-type, do something like: curl -d "datatopost" -H "Content-Type: text/xml" [URL] 3.12 Why do FTP-specific features over HTTP proxy fail? Because when you use an HTTP proxy, the protocol spoken on the network will be HTTP, even if you specify an FTP URL. This effectively means that you normally cannot use FTP-specific features such as FTP upload and FTP quote etc. There is one exception to this rule, and that is if you can "tunnel through" the given HTTP proxy. Proxy tunneling is enabled with a special option (-p) and is generally not available as proxy admins usually disable tunneling to ports other than 443 (which is used for HTTPS access through proxies). 3.13 Why do my single/double quotes fail? To specify a command line option that includes spaces, you might need to put the entire option within quotes. Like in: curl -d " with spaces " url.com or perhaps curl -d ' with spaces ' url.com Exactly what kind of quotes and how to do this is entirely up to the shell or command line interpreter that you are using. For most unix shells, you can more or less pick either single (') or double (") quotes. For Windows/DOS command prompts you must use double (") quotes, and if the option string contains inner double quotes you can escape them with a backslash. For Windows powershell the arguments are not always passed on as expected because curl is not a powershell script. You may or may not be able to use single quotes. To escape inner double quotes seems to require a backslash-backtick escape sequence and the outer quotes as double quotes. Please study the documentation for your particular environment. Examples in the curl docs will use a mix of both of these as shown above. You must adjust them to work in your environment. Remember that curl works and runs on more operating systems than most single individuals have ever tried. 3.14 Does curl support JavaScript or PAC (automated proxy config)? Many web pages do magic stuff using embedded JavaScript. curl and libcurl have no built-in support for that, so it will be treated just like any other contents. .pac files are a Netscape invention and are sometimes used by organizations to allow them to differentiate which proxies to use. The .pac contents is just a JavaScript program that gets invoked by the browser and that returns the name of the proxy to connect to. Since curl does not support JavaScript, it cannot support .pac proxy configuration either. Some workarounds usually suggested to overcome this JavaScript dependency: Depending on the JavaScript complexity, write up a script that translates it to another language and execute that. Read the JavaScript code and rewrite the same logic in another language. Implement a JavaScript interpreter, people have successfully used the Mozilla JavaScript engine in the past. Ask your admins to stop this, for a static proxy setup or similar. 3.15 Can I do recursive fetches with curl? No. curl itself has no code that performs recursive operations, such as those performed by wget and similar tools. There exists wrapper scripts with that functionality (for example the curlmirror perl script), and you can write programs based on libcurl to do it, but the command line tool curl itself cannot. 3.16 What certificates do I need when I use SSL? There are three different kinds of "certificates" to keep track of when we talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl. CLIENT CERTIFICATE The server you communicate with may require that you can provide this in order to prove that you actually are who you claim to be. If the server does not require this, you do not need a client certificate. A client certificate is always used together with a private key, and the private key has a pass phrase that protects it. SERVER CERTIFICATE The server you communicate with has a server certificate. You can and should verify this certificate to make sure that you are truly talking to the real server and not a server impersonating it. CERTIFICATE AUTHORITY CERTIFICATE ("CA cert") You often have several CA certs in a CA cert bundle that can be used to verify a server certificate that was signed by one of the authorities in the bundle. curl does not come with a CA cert bundle but most curl installs provide one. You can also override the default. The server certificate verification process is made by using a Certificate Authority certificate ("CA cert") that was used to sign the server certificate. Server certificate verification is enabled by default in curl and libcurl and is often the reason for problems as explained in FAQ entry 4.12 and the SSLCERTS document (https://curl.se/docs/sslcerts.html). Server certificates that are "self-signed" or otherwise signed by a CA that you do not have a CA cert for, cannot be verified. If the verification during a connect fails, you are refused access. You then need to explicitly disable the verification to connect to the server. 3.17 How do I list the root directory of an FTP server? There are two ways. The way defined in the RFC is to use an encoded slash in the first path part. List the "/tmp" directory like this: curl ftp://ftp.sunet.se/%2ftmp/ or the not-quite-kosher-but-more-readable way, by simply starting the path section of the URL with a slash: curl ftp://ftp.sunet.se//tmp/ 3.18 Can I use curl to send a POST/PUT and not wait for a response? No. You can easily write your own program using libcurl to do such stunts. 3.19 How do I get HTTP from a host using a specific IP address? For example, you may be trying out a website installation that is not yet in the DNS. Or you have a site using multiple IP addresses for a given host name and you want to address a specific one out of the set. Set a custom Host: header that identifies the server name you want to reach but use the target IP address in the URL: curl --header "Host: www.example.com" http://127.0.0.1/ You can also opt to add faked host name entries to curl with the --resolve option. That has the added benefit that things like redirects will also work properly. The above operation would instead be done as: curl --resolve www.example.com:80:127.0.0.1 http://www.example.com/ 3.20 How to SFTP from my user's home directory? Contrary to how FTP works, SFTP and SCP URLs specify the exact directory to work with. It means that if you do not specify that you want the user's home directory, you get the actual root directory. To specify a file in your user's home directory, you need to use the correct URL syntax which for SFTP might look similar to: curl -O -u user:password sftp://example.com/~/file.txt and for SCP it is just a different protocol prefix: curl -O -u user:password scp://example.com/~/file.txt 3.21 Protocol xxx not supported or disabled in libcurl When passing on a URL to curl to use, it may respond that the particular protocol is not supported or disabled. The particular way this error message is phrased is because curl does not make a distinction internally of whether a particular protocol is not supported (i.e. never got any code added that knows how to speak that protocol) or if it was explicitly disabled. curl can be built to only support a given set of protocols, and the rest would then be disabled or not supported. Note that this error will also occur if you pass a wrongly spelled protocol part as in "htpt://example.com" or as in the less evident case if you prefix the protocol part with a space as in " http://example.com/". 3.22 curl -X gives me HTTP problems In normal circumstances, -X should hardly ever be used. By default you use curl without explicitly saying which request method to use when the URL identifies an HTTP transfer. If you just pass in a URL like "curl http://example.com" it will use GET. If you use -d or -F curl will use POST, -I will cause a HEAD and -T will make it a PUT. If for whatever reason you are not happy with these default choices that curl does for you, you can override those request methods by specifying -X [WHATEVER]. This way you can for example send a DELETE by doing "curl -X DELETE [URL]". It is thus pointless to do "curl -XGET [URL]" as GET would be used anyway. In the same vein it is pointless to do "curl -X POST -d data [URL]"... But you can make a fun and somewhat rare request that sends a request-body in a GET request with something like "curl -X GET -d data [URL]" Note that -X does not actually change curl's behavior as it only modifies the actual string sent in the request, but that may of course trigger a different set of events. Accordingly, by using -XPOST on a command line that for example would follow a 303 redirect, you will effectively prevent curl from behaving correctly. Be aware. 4. Running Problems 4.2 Why do I get problems when I use & or % in the URL? In general Unix shells, the & symbol is treated specially and when used, it runs the specified command in the background. To safely send the & as a part of a URL, you should quote the entire URL by using single (') or double (") quotes around it. Similar problems can also occur on some shells with other characters, including ?*!$~(){}<>\|;`. When in doubt, quote the URL. An example that would invoke a remote CGI that uses &-symbols could be: curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl' In Windows, the standard DOS shell treats the percent sign specially and you need to use TWO percent signs for each single one you want to use in the URL. If you want a literal percent sign to be part of the data you pass in a POST using -d/--data you must encode it as '%25' (which then also needs the percent sign doubled on Windows machines). 4.3 How can I use {, }, [ or ] to specify multiple URLs? Because those letters have a special meaning to the shell, to be used in a URL specified to curl you must quote them. An example that downloads two URLs (sequentially) would be: curl '{curl,www}.haxx.se' To be able to use those characters as actual parts of the URL (without using them for the curl URL "globbing" system), use the -g/--globoff option: curl -g 'www.site.com/weirdname[].html' 4.4 Why do I get downloaded data even though the web page does not exist? curl asks remote servers for the page you specify. If the page does not exist at the server, the HTTP protocol defines how the server should respond and that means that headers and a "page" will be returned. That is simply how HTTP works. By using the --fail option you can tell curl explicitly to not get any data if the HTTP return code does not say success. 4.5 Why do I get return code XXX from an HTTP server? RFC 2616 clearly explains the return codes. This is a short transcript. Go read the RFC for exact details: 4.5.1 "400 Bad Request" The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. 4.5.2 "401 Unauthorized" The request requires user authentication. 4.5.3 "403 Forbidden" The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. 4.5.4 "404 Not Found" The server has not found anything matching the Request-URI. No indication is given as to whether the condition is temporary or permanent. 4.5.5 "405 Method Not Allowed" The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource. 4.5.6 "301 Moved Permanently" If you get this return code and an HTML output similar to this: <H1>Moved Permanently</H1> The document has moved <A HREF="http://same_url_now_with_a_trailing_slash/">here</A>. it might be because you requested a directory URL but without the trailing slash. Try the same operation again _with_ the trailing URL, or use the -L/--location option to follow the redirection. 4.6 Can you tell me what error code 142 means? All curl error codes are described at the end of the man page, in the section called "EXIT CODES". Error codes that are larger than the highest documented error code means that curl has exited due to a crash. This is a serious error, and we appreciate a detailed bug report from you that describes how we could go ahead and repeat this. 4.7 How do I keep user names and passwords secret in curl command lines? This problem has two sides: The first part is to avoid having clear-text passwords in the command line so that they do not appear in 'ps' outputs and similar. That is easily avoided by using the "-K" option to tell curl to read parameters from a file or stdin to which you can pass the secret info. curl itself will also attempt to "hide" the given password by blanking out the option - this does not work on all platforms. To keep the passwords in your account secret from the rest of the world is not a task that curl addresses. You could of course encrypt them somehow to at least hide them from being read by human eyes, but that is not what anyone would call security. Also note that regular HTTP (using Basic authentication) and FTP passwords are sent as cleartext across the network. All it takes for anyone to fetch them is to listen on the network. Eavesdropping is easy. Use more secure authentication methods (like Digest, Negotiate or even NTLM) or consider the SSL-based alternatives HTTPS and FTPS. 4.8 I found a bug It is not a bug if the behavior is documented. Read the docs first. Especially check out the KNOWN_BUGS file, it may be a documented bug. If it is a problem with a binary you have downloaded or a package for your particular platform, try contacting the person who built the package/archive you have. If there is a bug, read the BUGS document first. Then report it as described in there. 4.9 curl cannot authenticate to a server that requires NTLM? NTLM support requires OpenSSL, GnuTLS, mbedTLS, NSS, Secure Transport, or Microsoft Windows libraries at build-time to provide this functionality. 4.10 My HTTP request using HEAD, PUT or DELETE does not work Many web servers allow or demand that the administrator configures the server properly for these requests to work on the web server. Some servers seem to support HEAD only on certain kinds of URLs. To fully grasp this, try the documentation for the particular server software you are trying to interact with. This is not anything curl can do anything about. 4.11 Why do my HTTP range requests return the full document? Because the range may not be supported by the server, or the server may choose to ignore it and return the full document anyway. 4.12 Why do I get "certificate verify failed" ? When you invoke curl and get an error 60 error back it means that curl could not verify that the server's certificate was good. curl verifies the certificate using the CA cert bundle and verifying for which names the certificate has been granted. To completely disable the certificate verification, use -k. This does however enable man-in-the-middle attacks and makes the transfer INSECURE. We strongly advise against doing this for more than experiments. If you get this failure with a CA cert bundle installed and used, the server's certificate might not be signed by one of the CA's in your CA store. It might for example be self-signed. You then correct this problem by obtaining a valid CA cert for the server. Or again, decrease the security by disabling this check. At times, you find that the verification works in your favorite browser but fails in curl. When this happens, the reason is usually that the server sends an incomplete cert chain. The server is mandated to send all "intermediate certificates" but does not. This typically works with browsers anyway since they A) cache such certs and B) supports AIA which downloads such missing certificates on demand. This is a server misconfiguration. A good way to figure out if this is the case it to use the SSL Labs server test and check the certificate chain: https://www.ssllabs.com/ssltest/ Details are also in the SSLCERTS.md document, found online here: https://curl.se/docs/sslcerts.html 4.13 Why is curl -R on Windows one hour off? Since curl 7.53.0 this issue should be fixed as long as curl was built with any modern compiler that allows for a 64-bit curl_off_t type. For older compilers or prior curl versions it may set a time that appears one hour off. This happens due to a flaw in how Windows stores and uses file modification times and it is not easily worked around. For more details read this: https://www.codeproject.com/Articles/1144/Beating-the-Daylight-Savings-Time-bug-and-getting 4.14 Redirects work in browser but not with curl curl supports HTTP redirects well (see item 3.8). Browsers generally support at least two other ways to perform redirects that curl does not: Meta tags. You can write an HTML tag that will cause the browser to redirect to another given URL after a certain time. JavaScript. You can write a JavaScript program embedded in an HTML page that redirects the browser to another given URL. There is no way to make curl follow these redirects. You must either manually figure out what the page is set to do, or write a script that parses the results and fetches the new URL. 4.15 FTPS does not work curl supports FTPS (sometimes known as FTP-SSL) both implicit and explicit mode. When a URL is used that starts with FTPS://, curl assumes implicit SSL on the control connection and will therefore immediately connect and try to speak SSL. FTPS:// connections default to port 990. To use explicit FTPS, you use an FTP:// URL and the --ftp-ssl option (or one of its related flavors). This is the most common method, and the one mandated by RFC 4217. This kind of connection will then of course use the standard FTP port 21 by default. 4.16 My HTTP POST or PUT requests are slow libcurl makes all POST and PUT requests (except for requests with a small request body) use the "Expect: 100-continue" header. This header allows the server to deny the operation early so that libcurl can bail out before having to send any data. This is useful in authentication cases and others. However, many servers do not implement the Expect: stuff properly and if the server does not respond (positively) within 1 second libcurl will continue and send off the data anyway. You can disable libcurl's use of the Expect: header the same way you disable any header, using -H / CURLOPT_HTTPHEADER, or by forcing it to use HTTP 1.0. 4.17 Non-functional connect timeouts In most Windows setups having a timeout longer than 21 seconds make no difference, as it will only send 3 TCP SYN packets and no more. The second packet sent three seconds after the first and the third six seconds after the second. No more than three packets are sent, no matter how long the timeout is set. See option TcpMaxConnectRetransmissions on this page: https://support.microsoft.com/en-us/kb/175523/en-us Also, even on non-Windows systems there may run a firewall or anti-virus software or similar that accepts the connection but does not actually do anything else. This will make (lib)curl to consider the connection connected and thus the connect timeout will not trigger. 4.18 file:// URLs containing drive letters (Windows, NetWare) When using curl to try to download a local file, one might use a URL in this format: file://D:/blah.txt you will find that even if D:\blah.txt does exist, curl returns a 'file not found' error. According to RFC 1738 (https://www.ietf.org/rfc/rfc1738.txt), file:// URLs must contain a host component, but it is ignored by most implementations. In the above example, 'D:' is treated as the host component, and is taken away. Thus, curl tries to open '/blah.txt'. If your system is installed to drive C:, that will resolve to 'C:\blah.txt', and if that does not exist you will get the not found error. To fix this problem, use file:// URLs with *three* leading slashes: file:///D:/blah.txt Alternatively, if it makes more sense, specify 'localhost' as the host component: file://localhost/D:/blah.txt In either case, curl should now be looking for the correct file. 4.19 Why does not curl return an error when the network cable is unplugged? Unplugging a cable is not an error situation. The TCP/IP protocol stack was designed to be fault tolerant, so even though there may be a physical break somewhere the connection should not be affected, just possibly delayed. Eventually, the physical break will be fixed or the data will be re-routed around the physical problem through another path. In such cases, the TCP/IP stack is responsible for detecting when the network connection is irrevocably lost. Since with some protocols it is perfectly legal for the client to wait indefinitely for data, the stack may never report a problem, and even when it does, it can take up to 20 minutes for it to detect an issue. The curl option --keepalive-time enables keep-alive support in the TCP/IP stack which makes it periodically probe the connection to make sure it is still available to send data. That should reliably detect any TCP/IP network failure. TCP keep alive will not detect the network going down before the TCP/IP connection is established (e.g. during a DNS lookup) or using protocols that do not use TCP. To handle those situations, curl offers a number of timeouts on its own. --speed-limit/--speed-time will abort if the data transfer rate falls too low, and --connect-timeout and --max-time can be used to put an overall timeout on the connection phase or the entire transfer. A libcurl-using application running in a known physical environment (e.g. an embedded device with only a single network connection) may want to act immediately if its lone network connection goes down. That can be achieved by having the application monitor the network connection on its own using an OS-specific mechanism, then signaling libcurl to abort (see also item 5.13). 4.20 curl does not return error for HTTP non-200 responses Correct. Unless you use -f (--fail). When doing HTTP transfers, curl will perform exactly what you are asking it to do and if successful it will not return an error. You can use curl to test your web server's "file not found" page (that gets 404 back), you can use it to check your authentication protected web pages (that gets a 401 back) and so on. The specific HTTP response code does not constitute a problem or error for curl. It simply sends and delivers HTTP as you asked and if that worked, everything is fine and dandy. The response code is generally providing more higher level error information that curl does not care about. The error was not in the HTTP transfer. If you want your command line to treat error codes in the 400 and up range as errors and thus return a non-zero value and possibly show an error message, curl has a dedicated option for that: -f (CURLOPT_FAILONERROR in libcurl speak). You can also use the -w option and the variable %{response_code} to extract the exact response code that was returned in the response. 5. libcurl Issues 5.1 Is libcurl thread-safe? Yes. We have written the libcurl code specifically adjusted for multi-threaded programs. libcurl will use thread-safe functions instead of non-safe ones if your system has such. Note that you must never share the same handle in multiple threads. There may be some exceptions to thread safety depending on how libcurl was built. Please review the guidelines for thread safety to learn more: https://curl.se/libcurl/c/threadsafe.html 5.2 How can I receive all data into a large memory chunk? [ See also the examples/getinmemory.c source ] You are in full control of the callback function that gets called every time there is data received from the remote server. You can make that callback do whatever you want. You do not have to write the received data to a file. One solution to this problem could be to have a pointer to a struct that you pass to the callback function. You set the pointer using the CURLOPT_WRITEDATA option. Then that pointer will be passed to the callback instead of a FILE * to a file: /* imaginary struct */ struct MemoryStruct { char *memory; size_t size; }; /* imaginary callback function */ size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)data; mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); if (mem->memory) { memcpy(&(mem->memory[mem->size]), ptr, realsize); mem->size += realsize; mem->memory[mem->size] = 0; } return realsize; } 5.3 How do I fetch multiple files with libcurl? libcurl has excellent support for transferring multiple files. You should just repeatedly set new URLs with curl_easy_setopt() and then transfer it with curl_easy_perform(). The handle you get from curl_easy_init() is not only reusable, but you are even encouraged to reuse it if you can, as that will enable libcurl to use persistent connections. 5.4 Does libcurl do Winsock initialization on win32 systems? Yes, if told to in the curl_global_init() call. 5.5 Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on win32 ? Yes, but you cannot open a FILE * and pass the pointer to a DLL and have that DLL use the FILE * (as the DLL and the client application cannot access each others' variable memory areas). If you set CURLOPT_WRITEDATA you must also use CURLOPT_WRITEFUNCTION as well to set a function that writes the file, even if that simply writes the data to the specified FILE *. Similarly, if you use CURLOPT_READDATA you must also specify CURLOPT_READFUNCTION. 5.6 What about Keep-Alive or persistent connections? curl and libcurl have excellent support for persistent connections when transferring several files from the same server. curl will attempt to reuse connections for all URLs specified on the same command line/config file, and libcurl will reuse connections for all transfers that are made using the same libcurl handle. When you use the easy interface the connection cache is kept within the easy handle. If you instead use the multi interface, the connection cache will be kept within the multi handle and will be shared among all the easy handles that are used within the same multi handle. 5.7 Link errors when building libcurl on Windows You need to make sure that your project, and all the libraries (both static and dynamic) that it links against, are compiled/linked against the same run time library. This is determined by the /MD, /ML, /MT (and their corresponding /M?d) options to the command line compiler. /MD (linking against MSVCRT dll) seems to be the most commonly used option. When building an application that uses the static libcurl library, you must add -DCURL_STATICLIB to your CFLAGS. Otherwise the linker will look for dynamic import symbols. If you are using Visual Studio, you need to instead add CURL_STATICLIB in the "Preprocessor Definitions" section. If you get a linker error like "unknown symbol __imp__curl_easy_init ..." you have linked against the wrong (static) library. If you want to use the libcurl.dll and import lib, you do not need any extra CFLAGS, but use one of the import libraries below. These are the libraries produced by the various lib/Makefile.* files: Target: static lib. import lib for libcurl*.dll. ----------------------------------------------------------- MinGW: libcurl.a libcurldll.a MSVC (release): libcurl.lib libcurl_imp.lib MSVC (debug): libcurld.lib libcurld_imp.lib Borland: libcurl.lib libcurl_imp.lib 5.8 libcurl.so.X: open failed: No such file or directory This is an error message you might get when you try to run a program linked with a shared version of libcurl and your runtime linker (ld.so) could not find the shared library named libcurl.so.X. (Where X is the number of the current libcurl ABI, typically 3 or 4). You need to make sure that ld.so finds libcurl.so.X. You can do that multiple ways, and it differs somewhat between different operating systems. They are usually: * Add an option to the linker command line that specify the hard-coded path the runtime linker should check for the lib (usually -R) * Set an environment variable (LD_LIBRARY_PATH for example) where ld.so should check for libs * Adjust the system's config to check for libs in the directory where you have put the library (like Linux's /etc/ld.so.conf) 'man ld.so' and 'man ld' will tell you more details 5.9 How does libcurl resolve host names? libcurl supports a large number of name resolve functions. One of them is picked at build-time and will be used unconditionally. Thus, if you want to change name resolver function you must rebuild libcurl and tell it to use a different function. - The non-IPv6 resolver that can use one of four different host name resolve calls (depending on what your system supports): A - gethostbyname() B - gethostbyname_r() with 3 arguments C - gethostbyname_r() with 5 arguments D - gethostbyname_r() with 6 arguments - The IPv6-resolver that uses getaddrinfo() - The c-ares based name resolver that uses the c-ares library for resolves. Using this offers asynchronous name resolves. - The threaded resolver (default option on Windows). It uses: A - gethostbyname() on plain IPv4 hosts B - getaddrinfo() on IPv6 enabled hosts Also note that libcurl never resolves or reverse-lookups addresses given as pure numbers, such as 127.0.0.1 or ::1. 5.10 How do I prevent libcurl from writing the response to stdout? libcurl provides a default built-in write function that writes received data to stdout. Set the CURLOPT_WRITEFUNCTION to receive the data, or possibly set CURLOPT_WRITEDATA to a different FILE * handle. 5.11 How do I make libcurl not receive the whole HTTP response? You make the write callback (or progress callback) return an error and libcurl will then abort the transfer. 5.12 Can I make libcurl fake or hide my real IP address? No. libcurl operates on a higher level. Besides, faking IP address would imply sending IP packets with a made-up source address, and then you normally get a problem with receiving the packet sent back as they would then not be routed to you. If you use a proxy to access remote sites, the sites will not see your local IP address but instead the address of the proxy. Also note that on many networks NATs or other IP-munging techniques are used that makes you see and use a different IP address locally than what the remote server will see you coming from. You may also consider using https://www.torproject.org/ . 5.13 How do I stop an ongoing transfer? With the easy interface you make sure to return the correct error code from one of the callbacks, but none of them are instant. There is no function you can call from another thread or similar that will stop it immediately. Instead, you need to make sure that one of the callbacks you use returns an appropriate value that will stop the transfer. Suitable callbacks that you can do this with include the progress callback, the read callback and the write callback. If you are using the multi interface, you can also stop a transfer by removing the particular easy handle from the multi stack at any moment you think the transfer is done or when you wish to abort the transfer. 5.14 Using C++ non-static functions for callbacks? libcurl is a C library, it does not know anything about C++ member functions. You can overcome this "limitation" with relative ease using a static member function that is passed a pointer to the class: // f is the pointer to your object. static size_t YourClass::func(void *buffer, size_t sz, size_t n, void *f) { // Call non-static member function. static_cast<YourClass*>(f)->nonStaticFunction(); } // This is how you pass pointer to the static function: curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, YourClass::func); curl_easy_setopt(hcurl, CURLOPT_WRITEDATA, this); 5.15 How do I get an FTP directory listing? If you end the FTP URL you request with a slash, libcurl will provide you with a directory listing of that given directory. You can also set CURLOPT_CUSTOMREQUEST to alter what exact listing command libcurl would use to list the files. The follow-up question tends to be how is a program supposed to parse the directory listing. How does it know what's a file and what's a directory and what's a symlink etc. If the FTP server supports the MLSD command then it will return data in a machine-readable format that can be parsed for type. The types are specified by RFC 3659 section 7.5.1. If MLSD is not supported then you have to work with what you are given. The LIST output format is entirely at the server's own liking and the NLST output does not reveal any types and in many cases does not even include all the directory entries. Also, both LIST and NLST tend to hide unix-style hidden files (those that start with a dot) by default so you need to do "LIST -a" or similar to see them. Example - List only directories. ftp.funet.fi supports MLSD and ftp.kernel.org does not: curl -s ftp.funet.fi/pub/ -X MLSD | \ perl -lne 'print if s/(?:^|;)type=dir;[^ ]+ (.+)$/$1/' curl -s ftp.kernel.org/pub/linux/kernel/ | \ perl -lne 'print if s/^d[-rwx]{9}(?: +[^ ]+){7} (.+)$/$1/' If you need to parse LIST output in libcurl one such existing list parser is available at https://cr.yp.to/ftpparse.html Versions of libcurl since 7.21.0 also provide the ability to specify a wildcard to download multiple files from one FTP directory. 5.16 I want a different time-out Sometimes users realize that CURLOPT_TIMEOUT and CURLOPT_CONNECTIMEOUT are not sufficiently advanced or flexible to cover all the various use cases and scenarios applications end up with. libcurl offers many more ways to time-out operations. A common alternative is to use the CURLOPT_LOW_SPEED_LIMIT and CURLOPT_LOW_SPEED_TIME options to specify the lowest possible speed to accept before to consider the transfer timed out. The most flexible way is by writing your own time-out logic and using CURLOPT_XFERINFOFUNCTION (perhaps in combination with other callbacks) and use that to figure out exactly when the right condition is met when the transfer should get stopped. 5.17 Can I write a server with libcurl? No. libcurl offers no functions or building blocks to build any kind of Internet protocol server. libcurl is only a client-side library. For server libraries, you need to continue your search elsewhere but there exist many good open source ones out there for most protocols you could want a server for. There are also really good stand-alone servers that have been tested and proven for many years. There is no need for you to reinvent them. 5.18 Does libcurl use threads? Put simply: no, libcurl will execute in the same thread you call it in. All callbacks will be called in the same thread as the one you call libcurl in. If you want to avoid your thread to be blocked by the libcurl call, you make sure you use the non-blocking multi API which will do transfers asynchronously - still in the same single thread. libcurl will potentially internally use threads for name resolving, if it was built to work like that, but in those cases it will create the child threads by itself and they will only be used and then killed internally by libcurl and never exposed to the outside. 6. License Issues curl and libcurl are released under a MIT/X derivative license. The license is liberal and should not impose a problem for your project. This section is just a brief summary for the cases we get the most questions. (Parts of this section was much enhanced by Bjorn Reese.) We are not lawyers and this is not legal advice. You should probably consult one if you want true and accurate legal insights without our prejudice. Note especially that this section concerns the libcurl license only; compiling in features of libcurl that depend on other libraries (e.g. OpenSSL) may affect the licensing obligations of your application. 6.1 I have a GPL program, can I use the libcurl library? Yes Since libcurl may be distributed under the MIT/X derivative license, it can be used together with GPL in any software. 6.2 I have a closed-source program, can I use the libcurl library? Yes libcurl does not put any restrictions on the program that uses the library. 6.3 I have a BSD licensed program, can I use the libcurl library? Yes libcurl does not put any restrictions on the program that uses the library. 6.4 I have a program that uses LGPL libraries, can I use libcurl? Yes The LGPL license does not clash with other licenses. 6.5 Can I modify curl/libcurl for my program and keep the changes secret? Yes The MIT/X derivative license practically allows you to do almost anything with the sources, on the condition that the copyright texts in the sources are left intact. 6.6 Can you please change the curl/libcurl license to XXXX? No. We have carefully picked this license after years of development and discussions and a large amount of people have contributed with source code knowing that this is the license we use. This license puts the restrictions we want on curl/libcurl and it does not spread to other programs or libraries that use it. It should be possible for everyone to use libcurl or curl in their projects, no matter what license they already have in use. 6.7 What are my obligations when using libcurl in my commercial apps? Next to none. All you need to adhere to is the MIT-style license (stated in the COPYING file) which basically says you have to include the copyright notice in "all copies" and that you may not use the copyright holder's name when promoting your software. You do not have to release any of your source code. You do not have to reveal or make public any changes to the libcurl source code. You do not have to broadcast to the world that you are using libcurl within your app. All we ask is that you disclose "the copyright notice and this permission notice" somewhere. Most probably like in the documentation or in the section where other third party dependencies already are mentioned and acknowledged. As can be seen here: https://curl.se/docs/companies.html and elsewhere, more and more companies are discovering the power of libcurl and take advantage of it even in commercial environments. 7. PHP/CURL Issues 7.1 What is PHP/CURL? The module for PHP that makes it possible for PHP programs to access curl- functions from within PHP. In the cURL project we call this module PHP/CURL to differentiate it from curl the command line tool and libcurl the library. The PHP team however does not refer to it like this (for unknown reasons). They call it plain CURL (often using all caps) or sometimes ext/curl, but both cause much confusion to users which in turn gives us a higher question load. 7.2 Who wrote PHP/CURL? PHP/CURL was initially written by Sterling Hughes. 7.3 Can I perform multiple requests using the same handle? Yes - at least in PHP version 4.3.8 and later (this has been known to not work in earlier versions, but the exact version when it started to work is unknown to me). After a transfer, you just set new options in the handle and make another transfer. This will make libcurl re-use the same connection if it can. 7.4 Does PHP/CURL have dependencies? PHP/CURL is a module that comes with the regular PHP package. It depends on and uses libcurl, so you need to have libcurl installed properly before PHP/CURL can be used. 8. Development 8.1 Why does curl use C89? As with everything in curl, there is a history and we keep using what we have used before until someone brings up the subject and argues for and works on changing it. We started out using C89 in the 1990s because that was the only way to write a truly portable C program and have it run as widely as possible. C89 was for a long time even necessary to make things work on otherwise considered modern platforms such as Windows. Today, we do not really know how many users that still require the use of a C89 compiler. We will continue to use C89 for as long as nobody brings up a strong enough reason for us to change our minds. The core developers of the project do not feel restricted by this and we are not convinced that going C99 will offer us enough of a benefit to warrant the risk of cutting off a share of users. 8.2 Will curl be rewritten? In one go: no. Little by little over time? Maybe. Over the years, new languages and clever operating environments come and go. Every now and then the urge apparently arises to request that we rewrite curl in another language. Some the most important properties in curl are maintaining the API and ABI for libcurl and keeping the behavior for the command line tool. As long as we can do that, everything else is up for discussion. To maintain the ABI, we probably have to maintain a certain amount of code in C, and to remain rock stable, we will never risk anything by rewriting a lot of things in one go. That said, we can certainly offer more and more optional backends written in other languages, as long as those backends can be plugged in at build-time. Backends can be written in any language, but should probably provide APIs usable from C to ease integration and transition. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������licenses/ea-libargon2/LICENSE�����������������������������������������������������������������������0000644�����������������00000042727�15253072414�0011637 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Argon2 reference source code package - reference C implementations Copyright 2015 Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves You may use this work under the terms of a Creative Commons CC0 1.0 License/Waiver or the Apache Public License 2.0, at your option. The terms of these licenses can be found at: - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 The terms of the licenses are reproduced below. -------------------------------------------------------------------------------- Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. -------------------------------------------------------------------------------- Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������